需求背景

  • Vue, React 等框架简化了 SPA 开发,由于打包了整个应用,用户首次打开时需要加载全部代码,速度慢,严重影响用户体验,Bounce Rate 居高不下

  • 用户通常只浏览网站少数页面,大部分的页面代码不需要全部加载进来,需要实现网站代码按需加载

  • 随着网站不断完善,功能越来越多,第三方 npm 包占据大量代码空间,导致加载速度慢

解决方案

异步加载

浏览器的机制:解析过程遇到脚本标签,如<script src="a.js"></script> 会暂停内容解析,优先下载脚本,完成后继续解析。同步模式的阻塞问题可以通过 async 和 defer 属性实现异步加载,提高访问速度。

<script type="text/javascript" src="./a.js" async></script><script type="text/javascript" src="./b.js" defer></script>

Note: async、defer 属性是 HTML5 中的新属性,使用时需要注意区别,async加载后立即执行代码,需要注意js文件的依赖问题,避免冲突,无依赖可放心使用,典型例子google analytics

动态加载

由于异步加载的依赖问题难以控制,利用 webpack 实现动态加载成为 SPA 优化的主要方式。ES6 语法中提供import、export方式管理模块。其import关键字是被设置成静态的,不支持动态绑定。不过在es6的stage 3规范中,引入了一个新的方法 import() 使得动态加载模块成为可能。

Vue 中在 router.js 中添加 /* webpackChunkName: "test" */注释分割代码,实现动态加载相应代码,达到按需加载的目的。

import Vue from 'vue';import Router from 'vue-router';Vue.use(Router);export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/test',
      name: 'test',
      component: () => import(/* webpackChunkName: "test" */ './views/Test.vue'),
    },
  ]});
CDN

无论是否为 SPA 网站,CDN都是一个很大的提高,网站的静态文件(js,img,css)等,通过CDN缓存,物理上降低静态文件到用户的传输距离,减少中间路由,极大提高静态资源访问速度。目前各大云厂商都提供CDN加速或全站加速(更加智能的缓存,不只是静态文件)。

并发请求数优化、多域名
浏览器并发请求限制
IE 72
IE 8/96
IE 108
IE 1113
Firefox6
Chrome6
Safari6
Opera6
iOS WebView6
Android WebView6

浏览器并发请求限制一般是6个http连接,单个域名限制并发请求 6 个资源。在连接限制下有两个优化方法:

  1. 尽量较少请求数量,考虑合并部分请求减少请求,以6个连接为限制(应用复杂时较难实现)

  2. 多域名请求资源,如图片可以使用img1.abc.com、img2.abc.com进行请求,避开单独域名限制,同步加载图片

浏览器缓存

http 请求头增加缓存字段,后台前端均可使用

字段说明标记端
Expires资源的过期时间
Cache-Control缓存控制字段,精确控制缓存策略
If-Modified-Since资源最近修改时间浏览器
Last-Modified资源最近修改时间服务器
Etag资源标识服务器
If-None-Match缓存资源标识浏览器
  • 后台缓存:部分资源不需要频繁请求,可以设置Cache-Control字段,避免前端频繁请求,如图片等资源

# Nginx 配置server {
  server_name localhost;
  listen 8000;
  
  location ~ ^/img/(\w+)$ {
      alias /var/lib/abc/image/$1.jpeg;
      default_type image/jpeg;
      add_header Cache-Control 600;
  }}
  • 前端缓存:通常前端代码由自身开发代码和第三方库组成,自身代码经常改动,第三方库较少改动,可以通过分开webpack代码打包方式解决

Http2

http2 相比http1性能提高较大,通过压缩头部,保持连接等方式提高资源利用率,效果可参考这个网站

其他解决方案

为了充分分析加载优化方案,除了常规做法,这里汇总特定场景使用或者已经弃用的方案,补全文章完整性,这部分优化效果没有前面的方案明显。

require.ensure

与 import() 类似,webpack 1.x 官方提供的懒加载方案。已被 import() 语法取代了。弃用

preload

w3c新出的一个标准。利用link的rel属性来声明相关“proload",从而实现预加载的目的,如下:

<link rel="preload" href="/styles/other.css" as="style"><link rel="preload" href="example.js" as="script">

preload 关键字告知浏览器启用preload功能,浏览器检测到这个属性后,就会预先加载资源,目前兼容性较差。webpack 有相关插件,有兴趣可以尝试:preload-webpack-plugin

长页面滚动场景

通过监听滚动条,判断视图区域,只加载对应资源,如社交网站的评论区滚动,google 搜索 image 的滚动加载。

分页预加载

项目较多时通常采用分页方式提供用户浏览,如用户在浏览页面1的间隙,import() 等动态加载方式将第二页数据下载下来,用户点击下一页时可立即看到页面,用户体验较好。使用场景如:电商的商品页面。

Skeleton

事先撑开即将渲染的元素,避免闪屏,同时提示用户这要渲染东西,减少用户焦虑

https://github.com/lavas-project/vue-skeleton-webpack-plugin


点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部