Webpack5优化之提高代码运行性能(Preload、Network Cache、Core-js、PWA)
文章目录
- 一、Preload/Prefetch
- 1.1 为什么
- 1.2 是什么
- 1.2.1 共同点:
- 1.2.2 区别:
- 1.2.3 问题
- 1.2.4 总结
- 1.3 怎么样
- 1.3.1 安装依赖
- 1.3.2 配置
- 1.3.3 测试
- 二、Network Cache
- 2.1 为什么
- 2.2 是什么
- 2.3 怎么用
- 2.3.1 问题
- 2.3.2 原因
- 2.3.3 解决
- 三、core-js
- 3.1 为什么
- 3.2 是什么
- 3.3 怎么用
- 3.3.1 修改代码
- 3.3.2 配置eslint
- 3.3.3 测试
- 3.3.4 使用core-js
- 3.3.4.1 手动全部引入
- 3.3.4.2 手动按需引入
- 3.3.4.3 自动按需引入
- 四、PWA
- 4.1 为什么
- 4.2 是什么
- 4.3 怎么样
- 4.3.1 安装依赖
- 4.3.2 配置文件
- 4.3.3 修改main.js
- 4.3.4 测试
- 4.3.5 解决路径问题
- 五、小结
- 5.1 提升开发体验
- 5.2 提升打包构建速度
- 5.3 减少代码体积
- 5.4 优化代码运行性能
一、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: [// 配置pwanew WorkboxPlugin.GenerateSW({// 这些选项帮助快速启用 ServiceWorkers// 不允许遗留任何“旧的” ServiceWorkersclientsClaim: 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
能让代码离线也能访问,从而提升用户体验
Webpack5优化之提高代码运行性能(Preload、Network Cache、Core-js、PWA)相关推荐
- Java 性能优化:教你提高代码运行的效率
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:五月的仓颉 cnblogs.com/xrq730/p/486 ...
- iar代码优化影响运行速度吗_Java 性能优化:教你提高代码运行的效率
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:五月的仓颉 cnblogs.com/xrq730/p/486 ...
- J2EE网站开发与优化如何提高代码运行效率
下面讨论的J2EE问题适合于使用JSP(Java Server Pages).EJB(Enterprise JavaBean)或JDBC(Java Data Base Connectivity,jav ...
- 看网易云公开课代码性能开发有感,怎样提高代码的性能
看到网易云讲到写一个缓存机制,什么时候用缓存机制,当有大量重复计算的时候,计算的难度不是很简单,如果是很简单的计算不要用缓存机制,不然会浪费大量的性能 在取HTMLCollection对象时,通常循环 ...
- cmake release和debug代码运行效果不一样_这35个小细节,让你的Java 代码运行效率翻倍!...
传智播客博学谷 加小谷vx:boxueguu 免费领IT各学科资料.课程 Get更多干货直播课 前言 代码 优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码 ...
- 泛型会让你的 Go 代码运行变慢
以下内容来自公众号逆锋起笔,关注每日干货及时送达 作者 | Vicent Marti 译者 | 核子可乐 策划 | 褚杏娟 Go 1.18 已经到来,很多人期盼已久的首个支持泛型实现的版本也就此落地. ...
- 华为鸿蒙os设置界面,华为鸿蒙OS系统界面疑似曝光 运行性能提升超60%
01华为鸿蒙OS系统界面疑曝光 近日,网上曝光了疑似华为鸿蒙OS操作系统的截图照片.据截图信息显示,此次"鸿蒙"OS操作系统的界面,不论在功能排列.状态栏,还是字体布局.按键配色等 ...
- 事件里面元素怎么立即刷新dom(页面),而不是等所有代码运行完再刷新。(强制刷新DOM)
事件里面元素怎么立即刷新dom(页面),而不是等所有代码运行完再刷新. 用js更新dom是web系统中经常出现的场景,但是有时候可能会遇到这样的情况,在更新dom之后还执行了一段运行时间可能比较长的j ...
- 提高网站访问性能——Tomcat优化
一.前言 tomcat 服务器在JavaEE项目中使用率非常高,所以在生产环境对tomcat的优化也变得非常重要了,对于tomcat的优化,主要是从2个方面入手,一是tomcat本身的配置,另一个是t ...
最新文章
- java orm 工具_GitHub - donnie4w/jdao: jdao是一个java的轻量级orm工具包
- DPDK架构与特点(转)
- java 能不能回收 文件流_Java文件流关闭和垃圾回收机制
- event对象获取方法总结在google浏览器下测试
- application time for the banking industry
- java调用 火眼臻睛,连接创新,发现未来,臻识科技受邀CCF-GAIR,论道浪潮之巅...
- chrome插件中调用ajax,Chrome扩展程序中的Ajax调用无效
- css 控制div高度自适应浏览器的高度
- 能根治乱象了?豆瓣私密小组将全部停用
- python 血缘进程共享数据
- WAMP的多站点配置
- xml文件转json文件
- 如何解决Photoshop导入视频不能错误
- Android Studio连接海马玩模拟器
- 如何获取所有基因的转录起始位点--转载
- 生成一个5位随机验证码(包含数字大小写字母)
- Streamlit(五) widgets-button
- 报表开发工具!DevExpress Reporting v19.1:WPF/Web平台报表
- 【CentOS7安装Redis及常用命令】
- DedeCMS搜索结果页面调用自定义字段的方法