前端性能优化一直是个大话题,今天我们从资源处理、资源拉取、渲染三个方面来聊一下这个话题。
一、资源处理
1、合并
优点:合并js、css、图片等资源可以较少大量的http请求,减少网络延迟。
缺点:合并后的资源体积过大,造成首屏渲染问题,第一次加载渲染时间过长。
所以,对于文件合并,有如下改进建议
(1)公共库合并
(2)不同页面单独合并
(3)如果使用打包工具可配置按需加载
2、压缩
HTML压缩、CSS压缩、JS压缩与混乱、图片压缩、开启gzip
图片压缩方法:
雪碧图:随着字体图片、SVG图片的流行,该技术渐渐退出了历史舞台
Base64:由于Base64编码用8位字符表示信息中的6个位,所以编码后大小大约比原始值扩大了33%
二、资源拉取
1、CDN
当浏览器访问一个域名的时候,需要解析一次DNS,获得对应域名的ip地址。在解析过程中,按照浏览器缓存、系统缓存、路由器缓存、ISP(运营商)DNS缓存、根域名服务器、顶级域名服务器、主域名服务器的顺序,逐步读取缓存,直到拿到IP地址
DNS Prefetch,即DNS预解析就是根据浏览器定义的规则,提前解析之后可能会用到的域名,使解析结果缓存到系统缓存中,缩短DNS解析时间,来提高网站的访问速度
方法是在 head 标签里面写上几个 link 标签
<link rel="dns-prefecth" href="https://www.google.com">
<link rel="dns-prefecth" href="https://www.google-analytics.com">
2、模块按需加载
在SPA等业务逻辑比较复杂的系统中,需要根据路由来加载当前页面需要的业务模块
按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载
webpack 提供了两个类似的技术,优先选择的方式是使用符合 ECMAScript 提案 的 import() 语法。第二种则是使用 webpack 特定的 require.ensure
3、使用资源预加载preload和资源预读取prefetch
preload让浏览器提前加载指定资源,需要执行时再执行,可以加速本页面的加载速度
prefetch告诉浏览器加载下一页面可能会用到的资源,可以加速下一个页面的加载速度
4、资源懒加载与资源预加载
资源延迟加载也称为懒加载,延迟加载资源或符合某些条件时才加载某些资源
资源预加载是提前加载用户所需的资源,保证良好的用户体验
资源懒加载和资源预加载都是一种错峰操作,在浏览器忙碌的时候不做操作,浏览器空间时,再加载资源,优化了网络性能
三、渲染
通过优化资源加载位置,更改资源加载时机,使尽可能快地展示出页面内容,尽可能快地使功能可用,减少重绘回流
1、CSS文件放在head中,先外链,后本页
2、JS文件放在body底部,先外链,后本页
3、处理页面、处理页面布局的JS文件放在head中,如babel-polyfill.js文件、flexible.js文件,减少重绘回流
4、body中间尽量不写style标签和script标签
5、js缓存DOM
6、使用DocumentFragment对象,让DOM操作发生在内存中,而不是页面上
7、事件代理
8、防抖和节流
使用函数节流(throttle)或函数去抖(debounce),限制某一个方法的频繁触发
9、及时清理环境
及时消除对象引用,清除定时器,清除事件监听器,创建最小作用域变量,可以及时回收内存
webpack优化
1、打包公共代码
使用CommonsChunkPlugin插件,将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存中供后续使用。这会带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件
webpack 4 将移除 CommonsChunkPlugin, 取而代之的是两个新的配置项 optimization.splitChunks 和 optimization.runtimeChunk
通过设置 optimization.splitChunks.chunks: "all" 来启动默认的代码分割配置项
2、动态导入和按需加载
webpack提供了两种技术通过模块的内联函数调用来分离代码,优先选择的方式是,使用符合 ECMAScript 提案 的 import() 语法。第二种,则是使用 webpack 特定的 require.ensure
3、剔除无用代码
tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 export。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup
JS的tree shaking主要通过uglifyjs插件来完成,CSS的tree shaking主要通过purify CSS来实现的
4、长缓存优化
1、将hash替换为chunkhash,这样当chunk不变时,缓存依然有效
2、使用Name而不是id
每个 module.id 会基于默认的解析顺序(resolve order)进行增量。也就是说,当解析顺序发生变化,ID 也会随之改变
下面来使用两个插件解决这个问题。第一个插件是 NamedModulesPlugin,将使用模块的路径,而不是数字标识符。虽然此插件有助于在开发过程中输出结果的可读性,然而执行时间会长一些。第二个选择是使用 HashedModuleIdsPlugin,推荐用于生产环境构建
5、公用代码内联
使用html-webpack-inline-chunk-plugin插件将mainfest.js内联到html文件中