原文链接
前端优化之路必不可少的知识点。
本文按一定顺序总结与前端性能优化的基本点,大家可以按步骤逐一检查自己的项目,找出性能的瓶颈。如有错误遗漏欢迎补充纠正。
文章有些原理细节都在参考文章中,价值较高建议读一读。
默认的 webpack4
很多优化内部已经做到很好了,但无法满足所有的业务场景,
如果发现开发时打包慢、打包体积太大,这是你就要审视下配置了。
npm i webpack-bundle-analyzer -D
webpack.config.js
// 在头部添加
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
// 在plugins: [] 中新增配置如下
new BundleAnalyzerPlugin({
analyzerMode: 'server',
analyzerHost: '127.0.0.1',
analyzerPort: 8000,
reportFilename: 'report.html',
defaultSizes: 'parsed',
openAnalyzer: true,
generateStatsFile: false,
statsFilename: 'stats.json',
statsOptions: null,
logLevel: 'info'
})
http://127.0.0.1:8000
比如,由于业务中频繁 antd
中的UI组件,但他们都小于 30kb
不会被独立打包,导致过多重复的代码打入不同 chunk
中。
这时根据实际业务情况,默认的配置就不满足需求了。修改策略:
vendor
包lib
包common
包// 默认配置
splitChunks: {
chunks: 'all',
name: false,
}
// 修改后的配置
splitChunks: {
chunks: 'all',
name: false,
cacheGroups: {
vendor: {
name: 'vendor',
test: module = >/(react|react-dom|react-router-dom|mobx|mobx-react)/.test(module.context),
chunks: 'initial',
priority: 11
},
libs: {
name: 'libs',
test: (module) = >/(moment|antd|lodash)/.test(module.context),
chunks: 'all',
priority: 14
},
common: {
chunks: "async",
test: /[\\/] node_modules[\\ / ] / ,
name: "common",
minChunks: 3,
maxAsyncRequests: 5,
maxSize: 1000000,
priority: 10
}
}
}
结论:
npm i glob purgecss-webpack-plugin -D
// 在webpack.config.js中的plugins: []中添加.
// 需要注意的是paths一定要是绝对路径,比如antd的样式不在src目录下就需要写成一个数组,要不然antd的样式就会不见了
new purgecssWebpackPlugin({
paths: glob.sync(`${paths.appSrc}/**/*`, { nodir: true })
})
结论:CSS
资源减小很多
一番操作下来
webp
是一种新式图片格式,在保证品质的同时提供无损和有损压缩。
webp
对于图片较多的站点是必不可少的优化手段,一般 CDN
都有提供转换服务。
png
减少 26%
的大小,有损下比 jpeg
小 25-34%
。// check_webp_feature:
// 'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
// 'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}
accept: image/webp
,服务端进行自动判断,支持则返回 webp
不支持则原图。多个图片拼成一个图片,在利用 background-position
定位。
减少 http 请求。
HTTP2 可以解决线头阻塞问题。
svg 版雪碧图
// 字符转
window.btoa('str');
// canvas 转
canvas.toDataURL();
// 图片转
const reader = new FileReader();
const imgUrlBase64 = reader.readAsDataURL(file);
// webpack 打包转
// url-loader
30%
左右。适用于少量小图的场景。
查找过程
hosts
文件域名 IP
映射(你知道背墙DNS污染但没封的IP,可以设置hosts文件访问)DNS解析器
(路由) 缓存DNS
解析占大头时间,优化还是很有必要的dns-prefetch
,例如访问某宝首页,猜测你接下来要访问某些域名,提前去解析。以节省下个页面的 DNS
查询。简单提下,对于现在 SPA
项目,一般静态资源放在 CDN 上,
对经常变动入口文件index.html
设置强制检验过期 Cache-Control: no-cahce
或直接不缓存。
其他 hash
命名的资源直接设置长缓存(max-age: 一年半载)。
具体详情已在另一篇文字阐释,文末链接。
优点:
CDN
,网站很卡或崩溃。优点:可以存储较大的数据 Chrome 5M
相比 storage
:
http1.x
每次会上报给服务器,造成网络浪费。建议:对服务器安全数据设置 http-only
,能少用尽量少用,只用来与服务器进行状态维护和用户识别。
@import
的使用,浏览器解析 html
会优化嗅探获并发获取文件,如果使用 @import
需要下载解析了当前 CSS
文件,才能下载。只对外联脚本有效。众所周知,脚本解析会阻塞 DOM
解析,这两个属性就是为了解决这个问题。
defer
下载时不阻塞 HTML 解析成 DOM,下载完成会等待 DOM
构建完毕且在 DOMContentLoaded
事件触发之前执行,多个 defer
脚本保证脚本执行顺序。
async
下载时不阻塞 HTML 解析成 DOM,下载完毕后尽量安排JS执行。意思说执行时间不确定,早下载早执行。如果 DOM
未构建完,脚本可能会阻塞DOM构建。
例如某宝大量在头部使用 async
async
应该用在对 DOM构建
和脚本顺序无依赖的场景,而且下载太快还可能阻塞 DOM构建
。感觉 defer
更合适。在其他文章有详细说明,在此不再赘述,请看参考索引。
will-change: transform
transform: translateZ(0)
会单独把元素提升层级交给 GPU
渲染,适合一些 Animation
动画。
google
文档上有很多探讨,检测计算长任务的新 api
进展。Facebook
最新 react
中的 fiber
调度,就使用了 requestAnimation
, requestIdelCallback
来DOM
树更新产生长耗时甚至抖动。对于需要大量计算会占用渲染主线程,适合放到 web worker
来执行。
http1.1 对比 http 1.0 主要进步有
Etag
range
头,响应码206(Partial Content)
支持断点续传host
头,多个域名可以绑定一个 IP
Connection: keep-alive
,长连接,客户端与同一个主机通信不必多次 三次握手
https 与 http
CA
证书,要钱;https 在 http 上多了层安全协议 SSL/TLS
;CA
认证,连接需要非对称加密(耗时),传输数据使用对称加密;80
,https 443
。http2 对比 http1.x
keep-alive
区分。前者是连接共享,每个请求有个唯一 id
来确认归属,多个请求可以同时相互混杂。http2 可以提升传输效率。nginx 有必要做好 http2 的升级和降级处理。
服务器开启压缩,文本类型的文件能够减少网络传输。
特别是文件较大且重复率高的文本压缩效果更明显。
如图 index.html
文件压缩 (383-230)/383=39.95%
。
Accept-Encoding: gzip, deflate, br
Content-Encoding: gzip
gzip on;
// 不压缩临界值,大于1K的才压缩,一般不用改
gzip_min_length 1k;
// 压缩级别,1-10,数字越大压缩的越细,时间也越长
gzip_comp_level 2;
// 进行压缩的文件类型
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
// ie兼容性不好所以放弃
gzip_disable "MSIE [1-6]\.";
npm i compression-webpack-plugin -D
const CompressionWebpackPlugin = require('compression-webpack-plugin');
// 在webpack.config.js中的plugins: []中添加.
new CompressionWebpackPlugin({
asset: '[path].gz[query]', // 目标文件名
algorithm: 'gzip', // 使用gzip压缩
test: /\.(js|css)$/, // 压缩 js 与 css
threshold: 10240, // 资源文件大于10240B=10kB时会被压缩
minRatio: 0.8 // 最小压缩比达到0.8时才会被压缩
})
nginx
开启 gzip
,发现有压缩好的 gzip
压缩文件,就会直接使用,减少服务器 cpu
的资源的使用。CDN
,gzip
是CDN服务器基本的服务,webpack
默认支持 es6
的新特性 tree-shaking
,可以摇掉不用的代码,且新api的性能很高。
推荐全面使用。
// 会根据ua返回不同的内容
https://polyfill.io/v3/polyfill.min.js
方案 | 优点 | 缺点 |
---|---|---|
babel-polyfill | React 官方推荐 | 体积200kb |
babel-plugin-transform-runtime | 体积小 | 不能poyfill原型上的方法 |
polyfill-service | 动态根据ui加载 | 兼容性,国内部分浏览器有问题 |
结论:可以减少资源大小,但依赖外部服务,自建麻烦的话,放弃。