一、 加载资源优化-- 减少请求资源大小和次数
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告诉浏览器去本地拉取数据