Web前端性能优化——如何提高页面加载速度

一、 加载资源优化-- 减少请求资源大小和次数

1、合并css和压缩css、js文件。

原因:

主要是为了减少http请求次数以及减少请求资源的大小

方法:

webpack中mini-css-extract-plugin将css样式抽离到一个文件中;

optimize-css-assets-webpack-plugin压缩css

terser-webpack-plugin压缩js

2、代码分割Code Splitting-为了减少HTTP 请求

把业务代码和第三方库代码分离出来,因为业务代码更新频率大,相反第三方库代码更新迭代相对较慢且可以锁版本,所以可以利用浏览器的缓存来加载这些第三方库。

做法:

1、利用webpack的CommonsChunkPlugin插件自动化分离公共模块,将公共模块单独打包成一个chunk --- 不推荐了,老方法
2、利用webpack4的splitChunksPlugin

webpack4 最核心的特性是 【splitChunks】,splitChunks 最核心的配置是 cacheGroups!

默认配置如下:

模块被重复引用或者来自node_modules中的模块
minSize: 30000,// 引入的模块,只有大于30kb时,才会做代码分割

maxAsyncRequests: 5, 在按需加载时,请求数量小于等于5进行代码分割

 maxInitialRequests: 3, 在初始化加载时,请求数量小于等于3进行代码分割

异步代码分割import(),不需要做任何配置,webpack会自动完成分包。

SplitChunksPlugin有三种模式async,all,initial

默认情况下为async,即只拆分import()动态加载的模块

all 模式下,入口文件(webpack定义的entry)依赖的文件和动态引入文件都会进行拆分打包

initial 模式下,会将入口文件中的依赖包重新切割为一个新的文件,其它文件中动态引入的不会进行拆分

cacheGroups**** - ****缓存组****--****同步代码分割打包必须配置项

按需加载-利用() => [import()] 语法将组件单独打包到一个chunk里,即async chunk 。

场景:

「访问某个路由的时候再去加载对应的组件」,用户不一定会访问所有的路由,所以没必要把所有路由对应的组件都先在开始的加载完;

「某些用户他们的权限只能访问某些页面」,所以没必要把他们没权限访问的页面的代码也加载。

3、采用图片的懒加载(延迟加载) 目的为了,减少页面第一次加载的请求次数;防止并发加载资源过多造成页面阻塞 具体步骤: 1、页面开始加载时不去发送http请求,而是放置一张占位图 2、当页面加载完(window.onload)时,并且图片在可视区域再去请求加载图片信息

具体方案:

vue图片懒加载 —— vue-lazyload的使用;https://blog.csdn.net/halo1416/article/details/81302419

原理:先将img 标签中的src链接设为同一张占位图,将其真正的图片地址存储再在自定义属性中(比如data-src)。当js监听到该图片元素进入可视窗口时,即将自定义属性中的地址存储到src属性中,达到懒加载的效果。

    // 判断图片是否出现在视窗的函数

    function isShow($node) {

      return $node.offset().top <= $(window).height() + $(window).scrollTop();

    }

1、当 window.onload 事件触发时,页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了。

2、当 DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash。

4、避免引入大量第三方的库

能用css做的效果,不要用js做;能用原生js做的,不要去使用第三方插件。

5、使用雪碧图

为了减少网络请求数量,提高网站的访问速度,我们可以把一些小的图片合并成一张sprite图,然后根据background-position来进行定位

6、使用CDN让静态资源加载更快(CDN能够让你请求最近/最快的服务器)
7、tree shaking

tree shaking 用于移除 JavaScript 中的未引用代码(dead-code)。它依赖于 ES2015 模块module语法的静态结构特性,例如import 和 export,能够编译时就能确定模块的依赖关系,以及输入和输出的变量。

ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。

配置方法:

在webpack.config.js里添加

 mode: 'development', //production模式下,默认开启

 optimization: {

   usedExports: true,   // 开启Tree Shaking功能

 }

package.json中配置"sideEffects" 属性

"sideEffects": ["./src/some-side-effectful-file.js"] //该文件有副作用,不要进行tree shaking

通过配置副作用文件列表,提示编译器不进行tree shaking

二、 提高渲染效率

1、 尽量所使用的字体图标或者SVG图标来代替传统png图  因为字体图标或者SVG是矢量图,是代码编写出来的,放大不会变形,而且渲染速度快
2、 事件的节流、防抖--提高js运行效率
3、 把css放在head中,把js放在body下面

css放在body标签尾部时, DOMTree构建完成之后便开始构建RenderTree, 并计算布局渲染网页, 等加载解析完css之后, 开始构建CSSOMTree, 并和DOMTree重新构建RenderTree, 重新计算布局渲染网页

css放在head标签中时, 先加载css, 之后解析css构建CSSOMTree, 于此同时构建DOMTree, CSSOMTree和DOMTree都构建完毕之后开始构建RenderTree, 计算布局渲染网页

对比两者, css放在head标签中比css放在body标签尾部少了一次构建RenderTree, 一次计算布局和一次渲染网页, 因此性能会更好; 并且css放在body标签尾部时会在网页中短暂出现"裸奔"的HTML, 这不利于用户体验

4、 基于script标签下载js文件时,可以使用defer或者async来异步加载
5、减少重流、重绘

(1)减少dom操作,多个操作尽量合并到一起执行(浏览器会累积DOM 变动,然后一次性执行。)
(2)可将元素绝对定位脱离文档流,减少对其他元素的影响
(3)不要一项一项地改变样式,而是使用预先定义的CSS class(类名)一次性改变样式。
(4)使用window.requestAnimationFrame(),因为它可以把代码推迟到下一次重绘之前执行,而不是立即要求页面重绘

下面是一个window.requestAnimationFrame()对比效果的例子。

// 重流代价高function doubleHeight(element) {

  var currentHeight = element.clientHeight;

  element.style.height = (currentHeight * 2) + 'px';

}

all_my_elements.forEach(doubleHeight);

// 重绘代价低function doubleHeight(element) {

  var currentHeight = element.clientHeight;

  window.requestAnimationFrame(function () {

    element.style.height = (currentHeight * 2) + 'px';

  });

}

all_my_elements.forEach(doubleHeight);

上面的第一段代码,每读一次DOM,就写入新的值,会造成不停的重排和重流。第二段代码把所有的写操作,都累积在一起,从而 DOM 代码变动的代价就最小化了。

6、首屏内容使用SSR(server side render)服务端渲染

服务端渲染就是在服务端加载执行js,并且将数据直接输出到html,返回给客户端的是渲染好的html;

7、预渲染

通过Webpack 预渲染插件(prerender-spa-plugin)将一些特定静态页面组件 build 时就编译为 html 文件,直接以静态资源的形式输出给搜索引擎。

预渲染不执行js的,只适应于纯静态页面。

三、存储

1、Ajax请求使用缓存

GET请求,是可以(而且默认)在客户端进行缓存的,除非指定了不同的地址,否则同一个地址的AJAX请求,不会重复在服务器执行,而是返回304告诉浏览器去本地拉取数据

2、利用h5的新特性(localStorage、Application Cache)做一些简单数据的存储,避免向后台请求数据或者说在离线状态下做一些数据展示。

你可能感兴趣的:(Web前端性能优化——如何提高页面加载速度)