Webpack5优化:提高代码运行性能(Preload、Network Cache、Core-js、PWA)
一、Preload/Prefetch
1.1 为什么
我们前面已经做了代码分割,同时会使用import
动态导入语法来进行代码按需加载(我们也叫懒加载,比如路由懒加载就是这样实现的)。
但是加载速度还不够好,比如:是用户点击按钮时才加载这个资源的,如果资源体积很大,那么用户会感觉到明显卡顿效果。
我们想在浏览器空闲时间,加载后续需要使用的资源。我们就需要用上Preload
或Prefetch
技术。
1.2 是什么
Preload
:告诉浏览器立即加载资源Prefetch
:告诉浏览器在空闲时才开始加载资源
1.2.1 共同点:
- 都只会加载资源,并不执行
- 都有缓存
1.2.2 区别:
Preload
加载优先级高,Prefetch
加载优先级低Preload
只能加载当前页面需要使用的资源,Prefetch
可以加载当前页面资源,也可以加载下一个页面需要使用的资源
1.2.3 问题
兼容性较差
我们可以去 Can I Use 网站查询API
的兼容性问题
Preload
相对于Prefetch
兼容性好一点,如图
1.2.4 总结
- 当前页面优先级高的资源用
Preload
加载 - 下一个页面需要使用的资源用
Prefetch
加载
1.3 怎么样
1.3.1 安装依赖
npm i @vue/preload-webpack-plugin -D
1.3.2 配置
修改config/webpack.prod.js
:
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin')
plugins: [
// 配置预加载
new PreloadWebpackPlugin({
rel: 'preload',// preload兼容性更好
as: 'script'
})
],
1.3.3 测试
执行
npm run build
二、Network Cache
2.1 为什么
将来开发时我们对静态资源会使用缓存来优化,这样浏览器第二次请求资源就能读取缓存了,速度很快。
但是这样的话就会有一个问题, 因为前后输出的文件名是一样的,都叫main.js
,一旦将来发布新版本,因为文件名没有变化导致浏览器会直接读取缓存,不会加载新资源,项目也就没法更新了。
所以我们从文件名入手,确保更新前后文件名不一样,这样就可以做缓存了。
2.2 是什么
它们都会生成一个唯一的 hash 值。
fullhash(webpack4 是 hash)
:每次修改任何一个文件,所有文件名的hash
值都将改变。所以一旦修改了任何一个文件,整个项目的文件缓存都将失效chunkhash
:根据不同的入口文件(Entry)
进行依赖文件解析、构建对应的chunk
,生成对应的哈希值。我们js
和css
是同一个引入,会共享一个hash
值contenthash
:根据文件内容生成hash
值,只有文件内容变化了,hash
值才会变化。所有文件hash
值是独享且不同的
2.3 怎么用
修改config/webpack.prod.js
和config/webpack.dev.js
output: {
// 文件输出路径
// __dirname nodejs变量,代表当前文件的文件夹目录
path: path.resolve(__dirname, '../dist'),
// [contenthash:8]使用contenthash,取8位长度
filename: "static/js/[name].[contenthash:8].js", // 入口文件打包输出资源命名方式
chunkFilename: "static/js/[name].[contenthash:8].chunk.js", // 动态导入输出资源命名方式
assetModuleFilename: "static/media/[name].[hash][ext]", // 图片、字体等资源命名方式(注意用hash)
clean: true, // 自动将上次打包目录资源清空
},
plugins: [
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/[name].[contenthash:8].css",
chunkFilename: "static/css/[name].[contenthash:8].chunk.css",
}),
]
执行
npx webpack
结果如下:
2.3.1 问题
当我们修改math.js
文件再重新打包的时候,因为contenthash
原因,math.js
文件hash
值发生了变化(这是正常的)。
但是main.js
文件的hash
值也发生了变化,这会导致main.js
的缓存失效。
明明我们只修改math.js
, 为什么main.js
也会变身变化呢?
2.3.2 原因
- 更新前:
math.xxx.js
⇒main.js
引用的math.xxx.js
- 更新后:
math.yyy.js
⇒main.js
引用的math.yyy.js
, 文件名发生了变化,间接导致main.js
也发生了变化
2.3.3 解决
将hash
值单独保管在一个runtime
文件中。
我们最终输出三个文件:main、math、runtime
。当math
文件发送变化,变化的是math
和runtime
文件,main
不变。
runtime
文件只保存文件的hash
值和它们与文件关系,整个文件体积就比较小,所以变化重新请求的代价也小。
修改config/webpack.prod.js
文件:
optimization: {
// 提取runtime文件
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}`, // runtime文件命名规则
},
}
运行npm run build
,查看结果:
这样就解决了引用文件名变化导致缓存失效的问题了。
三、core-js
3.1 为什么
过去我们使用babel
对js
代码进行了兼容性处理,其中使用@babel/preset-env
智能预设来处理兼容性问题。
它能将ES6
的一些语法进行编译转换,比如箭头函数、点点点运算符等。但是如果是async
函数、promise
对象、数组的一些方法(includes)
等,它没办法处理。
所以此时我们 js
代码仍然存在兼容性问题,一旦遇到低版本浏览器会直接报错,所以我们想要将 js
兼容性问题彻底解决
3.2 是什么
core-js
是专门用来做ES6
以及以上API
的polyfill
。
polyfill
翻译过来叫做垫片/补丁
,就是用社区上提供的一段代码,让我们在不兼容某些新特性的浏览器上,使用该新特性
3.3 怎么用
3.3.1 修改代码
修改main.js
,添加promise
// 添加Promise代码
const promise = Promise.resolve()
promise.then(() => {
console.log('hello promise');
})
3.3.2 配置eslint
安装依赖:
npm i @babel/eslint-parser -D
修改.eslintrc.js
module.exports = {
...
parser: "@babel/eslint-parser", // 支持最新的最终 ECMAScript 标准
...
}
3.3.3 测试
运行
npm run build
此时观察打包输出的js
文件,我们发现Promise
语法并没有编译转换,所以我们需要使用core-js
来进行polyfill
。
3.3.4 使用core-js
安装依赖:
npm i core-js
3.3.4.1 手动全部引入
修改main.js
,引入core-js
import "core-js";
这样引入会将所有兼容性代码全部引入,体积太大了,我们只想引入promise
的polyfill
3.3.4.2 手动按需引入
修改main.js
,引入core-js
import "core-js/es/promise";
只引入打包promise
的polyfill
,打包体积更小。但是将来如果还想使用其他语法,还需要手动引入库很麻烦。
3.3.4.3 自动按需引入
修改babel.config.js
presets: [
[
"@babel/preset-env",
// 按需加载core-js的polyfill
{ useBuiltIns: "usage", corejs: { version: "3", proposals: true } },
],
],
此时就会自动根据我们代码中使用的语法,来按需加载相应的polyfill
了。
四、PWA
4.1 为什么
开发Web App
项目,项目一旦处于网络离线情况,就没法访问了。
我们希望给项目提供离线体验。
4.2 是什么
渐进式网络应用程序(progressive web application - PWA)
:是一种可以提供类似于native app
(原生应用程序) 体验的Web App
的技术。
其中最重要的是,在离线(offline)
时应用程序能够继续运行功能。
内部是通过Service Workers
技术实现的。
4.3 怎么样
4.3.1 安装依赖
npm i workbox-webpack-plugin -D
4.3.2 配置文件
修改config/webpack.prod.js
const WorkboxPlugin = require('workbox-webpack-plugin')
plugins: [
// 配置pwa
new WorkboxPlugin.GenerateSW({
// 这些选项帮助快速启用 ServiceWorkers
// 不允许遗留任何“旧的” ServiceWorkers
clientsClaim: true,
skipWaiting: true,
})
]
4.3.3 修改main.js
// pwa
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/service-worker.js")
.then((registration) => {
console.log("SW registered: ", registration);
})
.catch((registrationError) => {
console.log("SW registration failed: ", registrationError);
});
});
}
4.3.4 测试
运行指令
npm run build
此时如果直接通过VSCode
访问打包后页面,在浏览器控制台会发现SW registration failed
。
因为我们打开的访问路径是:http://127.0.0.1:5500/dist/index.html
,此时页面会去请求service-worker.js
文件,请求路径是:http://127.0.0.1:5500/service-worker.js
,这样找不到会 404
。
实际service-worker.js
文件路径是:http://127.0.0.1:5500/dist/service-worker.js
4.3.5 解决路径问题
安装依赖
npm i serve -g
serve
是用来启动开发服务器来部署代码查看效果的
运行指令
serve dist
此时通过serve
启动的服务器我们service-worker
就能注册成功了
五、小结
我们从4
个角度对webpack
和代码进行了优化:
5.1 提升开发体验
- 使用
Source Map
让开发或上线时代码报错能有更加准确的错误提示
5.2 提升打包构建速度
- 使用
HotModuleReplacement
让开发时只重新编译打包更新变化了的代码,不变的代码使用缓存,从而使更新速度更快 - 使用
OneOf
让资源文件一旦被某个loader
处理了,就不会继续遍历了,打包速度更快 - 使用
Include/Exclude
排除或只检测某些文件,处理的文件更少,速度更快 - 使用
Cache
对eslint
和babel
处理的结果进行缓存,让第二次打包速度更快 - 使用
Thead
多进程处理eslint
和babel
任务,速度更快(需要注意的是,进程启动通信都有开销的,要在比较多代码处理时使用才有效果)
5.3 减少代码体积
- 使用
Tree Shaking
剔除了没有使用的多余代码,让代码体积更小 - 使用
@babel/plugin-transform-runtime
插件对babel
进行处理,让辅助代码从中引入,而不是每个文件都生成辅助代码,从而体积更小 - 使用
Image Minimizer
对项目中图片进行压缩,体积更小,请求速度更快(需要注意的是,如果项目中图片都是在线链接,那么就不需要了。本地项目静态图片才需要进行压缩)
5.4 优化代码运行性能
- 使用
Code Split
对代码进行分割成多个js
文件,从而使单个文件体积更小,并行加载js
速度更快,并通过import
动态导入语法进行按需加载,从而达到需要使用时才加载该资源,不用时不加载资源 - 使用
Preload / Prefetch
对代码进行提前加载,等未来需要使用时就能直接使用,从而用户体验更好 - 使用
Network Cache
能对输出资源文件进行更好的命名,来好做缓存,从而用户体验更好 - 使用
Core-js
对js
进行兼容性处理,让我们代码能运行在低版本浏览器 - 使用
PWA
能让代码离线也能访问,从而提升用户体验
这篇文章转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: https://www.swvq.com/boutique/detail/tanhfcjhgc
- 联系方式: luke.wu●vfv.cc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
excel下划线不显示怎么办
PHP中文网 06-23 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
抖音国际版要用什么加速器能流畅刷Tiktok的加速器
TK小达人 08-02