0


前端白屏性能优化、资源加载优化的具体操作

1、路由懒加载

SPA 项目,一个路由对应一个页面,如果不做处理,项目打包后,会把所有页面打包成一个文件,当用户打开首页时,会一次性加载所有的资源,造成首页加载很慢,降低用户体验

列一个实际项目的打包详情:

app.js 初始体积:

1175kb

app.css 初始体积:

274kb

将路由全部改成懒加载

// 通过webpackChunkName设置分割后代码块的名字constHome=()=>import(/* webpackChunkName: "home" */"@/views/home/index.vue");constMetricGroup=()=>import(/* webpackChunkName: "metricGroup" */"@/views/metricGroup/index.vue");const routes =[{
    path:"/",
    name:"home",
    component: Home
  },{
    path:"/metricGroup",
    name:"metricGroup",
    component: MetricGroup
  },]

重新打包后,首页资源拆分为 app.js 和 home.js,以及对应的 css 文件

  • app.js:244 KB、 home.js: 35KB

  • app.css:67 KB、home.css: 15KB

通过路由懒加载,该项目的首页资源压缩约

52%

懒加载前提的实现:ES6的动态地加载模块——

import()

webpackChunkName 作用是 webpack 在打包的时候,对异步引入的库代码(lodash)进行代码分割时,设置代码块的名字。webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中
vite也有类似的功能

2、组件懒加载

home 页面 和 about 页面,都引入了 dialogInfo 弹框组件,该弹框不是一进入页面就加载,而是需要用户手动触发后才展示出来

home 页面示例:

<template><divclass="homeView"><p>home 页面</p><el-button@click="dialogVisible = !dialogVisible">打开弹框</el-button><dialogInfov-if="dialogVisible"/></div></template><script>import dialogInfo from'@/components/dialogInfo';exportdefault{
    name:'homeView',
    components:{
      dialogInfo
    }}</script>

项目打包后,发现 home.js 和 about.js 均包括了该弹框组件的代码(在 dist 文件中搜索dialogInfo弹框组件)

当用户打开 home 页时,会一次性加载该页面所有的资源,我们期望的是用户触发按钮后,再加载该弹框组件的资源

这种场景下,就很适合用懒加载的方式引入

弹框组件懒加载:

<script>constdialogInfo=()=>import(/* webpackChunkName: "dialogInfo" */'@/components/dialogInfo');exportdefault{
  name:'homeView',
  components:{
    dialogInfo
  }}</script>

重新打包后,home.js 和 about.js 中没有了弹框组件的代码,该组件被独立打包成 dialogInfo.js,当用户点击按钮时,才会去加载 dialogInfo.js 和 dialogInfo.css

最终,使用组件路由懒后,该项目的首页资源进一步减少约

11%

组件懒加载的使用场景
有时资源拆分的过细也不好,可能会造成浏览器 http 请求的增多
总结出三种适合组件懒加载的场景:
1)该页面的 JS 文件体积大,导致页面打开慢,可以通过组件懒加载进行资源拆分,利用浏览器并行下载资源,提升下载速度(比如首页)
2)该组件不是一进入页面就展示,需要一定条件下才触发(比如弹框组件)
3)该组件复用性高,很多页面都有引入,利用组件懒加载抽离出该组件,一方面可以很好利用缓存,同时也可以减少页面的 JS 文件大小(比如表格组件、图形组件等)

骨架屏优化白屏时长

用骨架屏,可以缩短白屏时间,提升用户体验。国内大多数的主流网站都使用了骨架屏,特别是手机端的项目

SPA 单页应用,无论 vue 还是 react,最初的 html 都是空白的,需要通过加载 JS 将内容挂载到根节点上,这套机制的副作用:会造成长时间的白屏

常见的骨架屏插件就是基于这种原理,在项目打包时将骨架屏的内容直接放到 html 文件的根节点中

使用骨架屏插件,打包后的 html 文件(根节点内部为骨架屏):

同一项目,对比使用骨架屏前后的 FP 白屏时间: 1063ms

有骨架屏:白屏时间

144ms

骨架屏插件
vue-skeleton-webpack-plugin 
// 骨架屏const SkeletonWebpackPlugin =require("vue-skeleton-webpack-plugin");
module.exports ={
  configureWebpack:{
    plugins:[newSkeletonWebpackPlugin({// 实例化插件对象
        webpackConfig:{
          entry:{
            app: path.join(__dirname,'./src/skeleton.js')// 引入骨架屏入口文件}},
        minimize:true,// SPA 下是否需要压缩注入 HTML 的 JS 代码
        quiet:true,// 在服务端渲染时是否需要输出信息到控制台
        router:{
          mode:'hash',// 路由模式
          routes:[// 不同页面可以配置不同骨架屏// 对应路径所需要的骨架屏组件id,id的定义在入口文件内{ path:/^\/home(?:\/)?/i, skeletonId:'homeSkeleton'},{ path:/^\/detail(?:\/)?/i, skeletonId:'detailSkeleton'}]}})]}}

JS 的6种加载方式

1)正常模式
<scriptsrc="index.js"></script>
2)async 模式
<scriptasyncsrc="index.js"></script>

async 模式下,它的加载是异步的,JS 不会阻塞 DOM 的渲染,async 加载是无顺序的,当它加载结束,JS 会立即执行

使用场景:若该 JS 资源与 DOM 元素没有依赖关系,也不会产生其他资源所需要的数据时,可以使用async 模式,比如埋点统计

3)defer 模式
<scriptdefersrc="index.js"></script>

defer 模式下,JS 的加载也是异步的,defer 资源会在

DOMContentLoaded

执行之前,并且 defer 是有顺序的加载

如果有多个设置了 defer 的 script 标签存在,则会按照引入的前后顺序执行,即便是后面的 script 资源先返回

所以 defer 可以用来控制 JS 文件的执行顺序,比如 element-ui.js 和 vue.js,因为 element-ui.js 依赖于 vue,所以必须先引入 vue.js,再引入 element-ui.js

<scriptdefersrc="vue.js"></script><scriptdefersrc="element-ui.js"></script>

defer 使用场景:一般情况下都可以使用 defer,特别是需要控制资源加载顺序时

4)module 模式
<scripttype="module">import{ a }from'./a.js'</script>

在主流的现代浏览器中,script 标签的属性可以加上

<font style="color:rgb(152, 195, 121);background-color:rgb(40, 44, 52);">type</font><font style="color:rgb(171, 178, 191);background-color:rgb(40, 44, 52);">=</font><font style="color:rgb(152, 195, 121);background-color:rgb(40, 44, 52);">"module"</font>

,浏览器会对其内部的 import 引用发起 HTTP 请求,获取模块内容。这时 script 的行为会像是 defer 一样,在后台下载,并且等待 DOM 解析

Vite 就是利用浏览器支持原生的

<font style="color:rgb(171, 178, 191);background-color:rgb(40, 44, 52);">es</font><font style="color:rgb(171, 178, 191);background-color:rgb(40, 44, 52);"> </font><font style="color:rgb(198, 120, 221);background-color:rgb(40, 44, 52);">module</font>

模块,开发时跳过打包的过程,提升编译效率

5) preload
<linkrel="preload"as="script"href="index.js">

link 标签的 preload 属性:用于提前加载一些需要的依赖,这些资源会优先加载(如下图红框)

async、defer 是 script 标签的专属属性,对于网页中的其他资源,可以通过 link 的 preload、prefetch 属性来预加载
如今现代框架已经将 preload、prefetch 添加到打包流程中了,通过灵活的配置,去使用这些预加载功能,同时我们也可以审时度势地向 script 标签添加 async、defer 属性去处理资源,这样可以显著提升性能

图片的懒加载
<imgsrc=""alt=""data-src="./images/1.jpg"><imgsrc=""alt=""data-src="./images/2.jpg">
图片转 base64 格式

将小图片转换为 base64 编码字符串,并写入 HTML 或者 CSS 中,减少 http 请求

// 安装
npm install url-loader --save-dev

// 配置
module.exports ={
  module:{
    rules:[{
      test:/.(png|jpg|gif)$/i,
      use:[{
        loader:'url-loader',
        options:{// 小于 20kb 的图片转化为 base64
          limit:1024*20}}]}]}};
标签: 前端 性能优化

本文转载自: https://blog.csdn.net/display_flex_/article/details/143476803
版权归原作者 display_flex_ 所有, 如有侵权,请联系我们删除。

“前端白屏性能优化、资源加载优化的具体操作”的评论:

还没有评论