相信大家肯定看过很多产品的开箱测评,今天来跑一个软件新版的上手测评 — webpack5.0。自从2018年2月,webpack4 发布以来,webpack 就暂时没有更进一步的重大更新,阔别 2 年多后,webpack5正式发布!通过本文也希望为我们的项目是否值得升级v5提供一些参考。
本次介绍的升级重点:
时过境迁,webpack模块应用的思想也发生了变化
举个栗子:
// index.jsimport CryptoJS from 'crypto-js';const md5Password = CryptoJS.MD5('123123');console.log(md5Password);
v5 vs v4:
v5编译中,会出现polyfill添加提示,如果不需要node polyfille,按照提示 alias 设置为 false 即可,下面v5中的配置以及编译结果: (244KiB)
// webpack.config.js resolve: { // 1.不需要node polyfilss alias: { crypto: false }, // 2.手动添加polyfills // fallback: { // "crypto": require.resolve('crypto-browserify') // } },
如何迁移?
在v4之前, chunkId和moduleId默认值是自增id,这样的配置下,如果有新的entry增加,chunkId也会递增
缺点:当删除或者暂时不使用1.js这个文件后,那么2.js->1.js,3.js->2.js,这样就会造成原本线上的2.js请求时会造成缓存失效.
算法策略:对moduleId和chunkId的生成策略进行了优化。
再举个栗子来验证一下:
// webpack.config.jsmodule.exports = { entry: { a: "./src/a.js", b: "./src/b.js", main: "./src/index.js" }, // 长期缓存优化配置 optimization: { chunkIds: 'deterministic', moduleIds: 'deterministic' },}
编译后,会发现相应的模块和分块,分别被分配了确定的数字ID和名称,当项目中删除或者不使用某个模块时,对其他文件并不会产生影响。
注意: 虽然chuckId不变,但更改chunk内容时,chunkhash还是会改变的。
如何迁移?
Webpack的编译速度相信是很多同学比较头痛的问题,在 CI持续性集成或者构建线上应用包的阶段时,要对Webpack配置加入代码优化、代码压缩等插件,当然也有很多伟大的方法来进行优化,例如HappyPack、Cache-loader等方法,来缩减构建时间、减小成本。
存在问题:
v5性能优化可以总结为:
默认情况下,缓存配置是memory,目前项目编译的时间为3298ms
v5中,可以修改设置为filesystem, 将缓存写入硬盘,不在需要cache-loader等性能优化的方法。
// webpack.config.jsmodule.exports = { cache: { // 1. 将缓存类型设置为文件系统 type: 'filesystem', // 默认是memory // 2. 将缓存文件夹命名为 .temp_cache, // 默认路径是 node_modules/.cache/webpack cacheDirectory: path.resolve(__dirname, '.temp_cache') }};
配置后的编译时间为776ms, 相比之前的默认配置,大大缩减了编译时间。
4 Module Federation如果说上面的优化都是常规套路,那么本次升级的模块联邦,有点让人出乎意料~
什么是模块联邦?NPM
维护一个CommonComponents的NPM包,在不同项目中安装、使用。如果 NPM 包升级,对应项目都需要重新安装新版本,本地编译,打包到 bundle 中。
UMD
即Universal Module Definition(通用模块规范),基本原理是利用设计模式中的工厂函数来统一不同的模块定义规范。
类似于我们开发的时候,经常会把某些功能封装成可复用的模块。并且对外暴露一个API,比如jquery、lodash等这类第三方插件,也可以通过CND的方式直接应用。后续这个公共函数的升级改造,我们更新CND引用链接地址,应用就自然也更新了。
UMD优点在 runtime。缺点也明显,体积优化不方便,容易有版本冲突.
微前端
微前端也是一种模块共享的方式,主要解决多项目并存问题,多项目并存的最大问题就是模块共享,不能有冲突。
在资源加载方式上,一般有两种打包方式:
微前端架构如下:
v5中模块共享方式 — 模块联邦模块联邦的使用方式如下
module.exports = { // other webpack configs... plugins: [ new ModuleFederationPlugin({ // 1. name 当前应用名称,需要全局唯一 name: "app_one_remote", // 2. remotes 可以将其他项目的 name 映射到当前项目中 remotes: { app_two: "app_two_remote", app_three: "app_three_remote" }, // 3. exposes 表示导出的模块,只有在此申明的模块才可以作为远程依赖被使用 exposes: { AppContainer: "./src/App" }, // 4. shared可以让远程加载的模块对应依赖改为使用本地项目的 React或ReactDOM。 shared: ["react", "react-dom", "react-router-dom"] }), new HtmlWebpackPlugin({ template: "./public/index.html", chunks: ["main"] }) ]};
比如设置了remotes: { app_two: "app_two_remote" },在代码中就可以直接利用以下方式直接从对方应用调用模块
import { Search } from "app_two/Search";
app_two/Search来自于app_two 的配置:
// app_two的webpack 配置export default { plugins: [ new ModuleFederationPlugin({ name: "app_two", library: { type: "var", name: "app_two" }, filename: "remoteEntry.js", exposes: { Search: "./src/Search" }, shared: ["react", "react-dom"] }) ]};
正是因为 Search在exposes被导出,我们因此可以使用 [name]/[exposes_name] 这个模块,这个模块对于被引用应用来说是一个本地模块。
5 其他特性总体来说webpack5在打包体积、编译速度上都有了不错的提升,在很多功能的配置、迁移上也较灵活便。在升级中,一些细节和插件的兼容性是主要的问题,还有待继续完善。抛砖引玉,欢迎大家一起来吐槽~
小编是一个有着7年工作经验的前端工程师,关于web前端,自己有做材料的整合,一个完整学习web前端的学习路线,学习材料和工具。需要的伙伴可以私信我,发送“前端”等3秒后就可以获取领取地址,免费送给大家
作者:大转转FE
链接:https://juejin.cn/post/6901224334371930119
来源:掘金
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved