文章目录

  • 一、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动态导入语法来进行代码按需加载(我们也叫懒加载,比如路由懒加载就是这样实现的)。

但是加载速度还不够好,比如:是用户点击按钮时才加载这个资源的,如果资源体积很大,那么用户会感觉到明显卡顿效果。

我们想在浏览器空闲时间,加载后续需要使用的资源。我们就需要用上PreloadPrefetch技术。

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,生成对应的哈希值。我们 jscss是同一个引入,会共享一个hash
  • contenthash:根据文件内容生成hash值,只有文件内容变化了,hash值才会变化。所有文件hash值是独享且不同的

2.3 怎么用

修改config/webpack.prod.jsconfig/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.jsmain.js引用的math.xxx.js
  • 更新后:math.yyy.jsmain.js引用的math.yyy.js, 文件名发生了变化,间接导致main.js也发生了变化

2.3.3 解决

hash值单独保管在一个runtime文件中。

我们最终输出三个文件:main、math、runtime。当math文件发送变化,变化的是mathruntime文件,main不变。

runtime文件只保存文件的hash值和它们与文件关系,整个文件体积就比较小,所以变化重新请求的代价也小。

修改config/webpack.prod.js文件:

optimization: {// 提取runtime文件runtimeChunk: {name: (entrypoint) => `runtime~${entrypoint.name}`, // runtime文件命名规则},
}

运行npm run build,查看结果:

这样就解决了引用文件名变化导致缓存失效的问题了。

三、core-js

3.1 为什么

过去我们使用babeljs代码进行了兼容性处理,其中使用@babel/preset-env智能预设来处理兼容性问题。

它能将ES6的一些语法进行编译转换,比如箭头函数、点点点运算符等。但是如果是async函数、promise对象、数组的一些方法(includes)等,它没办法处理。

所以此时我们 js代码仍然存在兼容性问题,一旦遇到低版本浏览器会直接报错,所以我们想要将 js兼容性问题彻底解决

3.2 是什么

core-js是专门用来做ES6以及以上APIpolyfill

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";

这样引入会将所有兼容性代码全部引入,体积太大了,我们只想引入promisepolyfill

3.3.4.2 手动按需引入

修改main.js,引入core-js

import "core-js/es/promise";

只引入打包promisepolyfill,打包体积更小。但是将来如果还想使用其他语法,还需要手动引入库很麻烦。

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排除或只检测某些文件,处理的文件更少,速度更快
  • 使用Cacheeslintbabel处理的结果进行缓存,让第二次打包速度更快
  • 使用Thead多进程处理eslintbabel任务,速度更快(需要注意的是,进程启动通信都有开销的,要在比较多代码处理时使用才有效果)

5.3 减少代码体积

  • 使用Tree Shaking剔除了没有使用的多余代码,让代码体积更小
  • 使用@babel/plugin-transform-runtime插件对babel进行处理,让辅助代码从中引入,而不是每个文件都生成辅助代码,从而体积更小
  • 使用Image Minimizer对项目中图片进行压缩,体积更小,请求速度更快(需要注意的是,如果项目中图片都是在线链接,那么就不需要了。本地项目静态图片才需要进行压缩)

5.4 优化代码运行性能

  • 使用Code Split对代码进行分割成多个js文件,从而使单个文件体积更小,并行加载js速度更快,并通过import动态导入语法进行按需加载,从而达到需要使用时才加载该资源,不用时不加载资源
  • 使用Preload / Prefetch对代码进行提前加载,等未来需要使用时就能直接使用,从而用户体验更好
  • 使用Network Cache能对输出资源文件进行更好的命名,来好做缓存,从而用户体验更好
  • 使用Core-jsjs进行兼容性处理,让我们代码能运行在低版本浏览器
  • 使用PWA能让代码离线也能访问,从而提升用户体验

Webpack5优化之提高代码运行性能(Preload、Network Cache、Core-js、PWA)相关推荐

  1. Java 性能优化:教你提高代码运行的效率

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:五月的仓颉 cnblogs.com/xrq730/p/486 ...

  2. iar代码优化影响运行速度吗_Java 性能优化:教你提高代码运行的效率

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:五月的仓颉 cnblogs.com/xrq730/p/486 ...

  3. J2EE网站开发与优化如何提高代码运行效率

    下面讨论的J2EE问题适合于使用JSP(Java Server Pages).EJB(Enterprise JavaBean)或JDBC(Java Data Base Connectivity,jav ...

  4. 看网易云公开课代码性能开发有感,怎样提高代码的性能

    看到网易云讲到写一个缓存机制,什么时候用缓存机制,当有大量重复计算的时候,计算的难度不是很简单,如果是很简单的计算不要用缓存机制,不然会浪费大量的性能 在取HTMLCollection对象时,通常循环 ...

  5. cmake release和debug代码运行效果不一样_这35个小细节,让你的Java 代码运行效率翻倍!...

    传智播客博学谷 加小谷vx:boxueguu 免费领IT各学科资料.课程 Get更多干货直播课 前言 代码 优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码 ...

  6. 泛型会让你的 Go 代码运行变慢

    以下内容来自公众号逆锋起笔,关注每日干货及时送达 作者 | Vicent Marti 译者 | 核子可乐 策划 | 褚杏娟 Go 1.18 已经到来,很多人期盼已久的首个支持泛型实现的版本也就此落地. ...

  7. 华为鸿蒙os设置界面,华为鸿蒙OS系统界面疑似曝光 运行性能提升超60%

    01华为鸿蒙OS系统界面疑曝光 近日,网上曝光了疑似华为鸿蒙OS操作系统的截图照片.据截图信息显示,此次"鸿蒙"OS操作系统的界面,不论在功能排列.状态栏,还是字体布局.按键配色等 ...

  8. 事件里面元素怎么立即刷新dom(页面),而不是等所有代码运行完再刷新。(强制刷新DOM)

    事件里面元素怎么立即刷新dom(页面),而不是等所有代码运行完再刷新. 用js更新dom是web系统中经常出现的场景,但是有时候可能会遇到这样的情况,在更新dom之后还执行了一段运行时间可能比较长的j ...

  9. 提高网站访问性能——Tomcat优化

    一.前言 tomcat 服务器在JavaEE项目中使用率非常高,所以在生产环境对tomcat的优化也变得非常重要了,对于tomcat的优化,主要是从2个方面入手,一是tomcat本身的配置,另一个是t ...

最新文章

  1. java orm 工具_GitHub - donnie4w/jdao: jdao是一个java的轻量级orm工具包
  2. DPDK架构与特点(转)
  3. java 能不能回收 文件流_Java文件流关闭和垃圾回收机制
  4. event对象获取方法总结在google浏览器下测试
  5. application time for the banking industry
  6. java调用 火眼臻睛,连接创新,发现未来,臻识科技受邀CCF-GAIR,论道浪潮之巅...
  7. chrome插件中调用ajax,Chrome扩展程序中的Ajax调用无效
  8. css 控制div高度自适应浏览器的高度
  9. 能根治乱象了?豆瓣私密小组将全部停用
  10. python 血缘进程共享数据
  11. WAMP的多站点配置
  12. xml文件转json文件
  13. 如何解决Photoshop导入视频不能错误
  14. Android Studio连接海马玩模拟器
  15. 如何获取所有基因的转录起始位点--转载
  16. 生成一个5位随机验证码(包含数字大小写字母)
  17. Streamlit(五) widgets-button
  18. 报表开发工具!DevExpress Reporting v19.1:WPF/Web平台报表
  19. 【CentOS7安装Redis及常用命令】
  20. DedeCMS搜索结果页面调用自定义字段的方法

热门文章

  1. 【Python】深入理解python格式化输出
  2. 【信息系统项目管理师】论多项目的资源管理(论文攻略篇)
  3. linux用户删组,如何在 Linux 下删除用户组(groupdel 命令)
  4. symbian s60 字符串操作
  5. 【javascript基础——系列10】js中隐藏元素的几种方法以及代码
  6. 【推荐系统】DeepFM模型分析
  7. IDEA中配置及使用Docker
  8. Embedded Qt 编译配置说明
  9. 第13章 逻辑架构和UML包图
  10. python模拟10086查询功能