Vue:首屏优化

416 阅读4分钟

一. SPA

1、定义

SPAsingle-page-application,只有一个HTML页面,通过路由实现页面内的局部替换,公共资源只加载一次。

2、优缺点

优点:
a、用户体验好,加载速度快,内容改变不需要重新加载整个页面
b、前后端分离
c、页面效果比较炫酷,能制作页面切换动画等

缺点:
a、不利于seo
b、导航不可用,如果一定要导航需要自行实现前进后退功能
c、不支持低版本浏览器。最低只支持到IE9
d、初次加载耗时多,白屏时间长
e、页面复杂度高

3、加载过程

拉取HTML --> 加载静态资源(css, js) --> 解析js,生成HTML --> 请求数据 --> 解析数据,渲染页面


二. FP、FCP、FMP

1、指标解释

FP First Paint 渲染出第一个像素的时间
FCP First Contentful Paint 首次内容绘制时间,包括文本、图片、非空canvas、svg
FMP First Meaningful Paint 首次有意义绘制时间

2、白屏和首屏

白屏时间:地址栏输入网址后回车浏览器出现第一个元素 的时间
首屏时间:地址栏输入网址后回车浏览器第一屏渲染完成 的时间

白屏结束时间 = FP指标触发时间
首屏结束时间 = FCP指标触发时间

3、各指标所对应的SPA加载过程

FP -- HTML拉取完毕
FCP -- 静态资源(css, js)加载完毕
FMP -- 数据请求完毕

首屏优化操作主要集中在FMP阶段,FCP阶段次之。
FP阶段的优化操作作用不大。


三. 首屏优化操作方法

1、路由动态加载

@babel/plugin-syntax-dynamic-import 解析识别import()动态导入语法。并非转换,而是解析识别

在根目录新建babel.config.js,配置如下:

module.exports = {
  ... ,
  "plugins": ['@babel/plugin-syntax-dynamic-import']
}

实际应用

const routes = [
  {
    path: '/',
    component: () => import('@/xxx')
  }, {
    path: '/A',
    component: () => import('@/xxx/A')
  }
]

2、提取公共库

optimization.splitChunks设置

optimization: {
  splitChunks: {
    chunks: "all",    //async异步代码分割 initial同步代码分割 all同步异步分割都开启
    minSize: 30000,         //引入的文件大于30kb才进行分割
    //maxSize: 50000,       //尝试将大于50kb的文件拆分成n个50kb的文件
    minChunks: 1,           //模块至少使用次数
    maxAsyncRequests: 5,    //同时加载的模块数量最多5个,只分割出同时引入的前5个文件
    maxInitialRequests: 3,  //首页加载的时候引入的文件最多3个
    automaticNameDelimiter: '~', //缓存组和生成文件名称之间的连接符
    name: true,                  //缓存组里面的filename生效,覆盖默认命名
    cacheGroups: { //缓存组,将所有加载模块放在缓存里面一起分割打包
      vendors: {  //自定义打包模块
        test: /[\\/]node_modules[\\/]/,
        priority: -10, //优先级,先打包到哪个组里面,值越大,优先级越高
        filename: 'vendors.js',
      },
      default: { //默认打包模块
        priority: -20,
        reuseExistingChunk: true, //模块嵌套引入时,判断是否复用已经被打包的模块
        filename: 'common.js'
      }
    }
  }
}

3、SSR、预渲染、同构

SSR 服务端渲染
通过vue-server-renderer插件将.vue文件转化为json文件,并通过index.html的注解插槽<!--vue-ssr-outlet-->json文件内容插入到index.html模板中

同构渲染
一套代码多端使用

预渲染 即 预先渲染
使用webpackvue打包出来的项目通过无头浏览器获取预渲染页面的html内容并渲染到index.html,然后储存到CDN上,用户请求时直接获取CDN上的index.html

4、loading

1)、添加loading图或进度条。
2)、制作首屏骨架图,作为特殊的loading图

5、骨架屏

骨架屏就是在页面内容未加载完成的时候,先使用一些图形或简单样式进行占位,待内容加载完成之后再把它替换掉。

在FP阶段注入骨架屏。

Vue中骨架屏实现方式:
1)、在模板中实现
  在index.html中的div#app实现骨架屏,程序渲染后就会替换掉div#app中的骨架屏内容
2)、结合 [SSR] (Vue:结合SSR实现骨架屏 - 掘金 (juejin.cn))
3)、自动生成并自动插入静态骨架屏
  使用 page-skeleton-webpack-pluginvue-skeleton-webpack-plugin 插件

6、webpack entry 单页改多页

module.exports = {
  ... ,
  entry: {
    app: './xxxx/index.js',
    aJs: './xxxx/a.js',
    bJs: './xxxx/b.js'
  }
}

7、资源请求时间片的处理

8、CDN 服务端处理

9、quickLink 在浏览器空闲的时候去解析预加载可能要跳转的页面

preload

<link rel="preload" href="/css/mystyles.css" as="style">

prefetch

  • link prefetch
<link rel='next' href='xxx.html'>
  • dns 移动端优化多
<link rel='dns-prefetch' href='xxx.html'>
  • prerendering
<link rel="prerender" href="http://www.cmcm.com">

preconnect
DNS TLS协商 TCP握手