乐趣区

Webpack5.0 新特性尝鲜实战

作者:志佳老师

本文首发微信公众号:jingchengyideng 欢迎关注,每天都给你推送新鲜的前端技术文章

在老袁写这篇文章的时候,v5 版本仍然处于早期阶段,可能仍然有问题。而且作为一个 major 版本,其中有一些 breaking changes,可能会导致一些配置和插件不工作。但这并无妨碍我们去开始对 changelog 上的新特性进行尝鲜实战。大家如果遇到什么问题可以移步到这进行反馈。另外有关于 Webpack4 的配置和 Compiler->Compilation->Chunk->Module->Template 整体运行原理国内外有很多优秀的文章我这里就不一一展开了。接下来天也不早了人也不少了,让我们一起干点正事。
(本图截自 twitter 列出了接下来 v5 版本的改进,嗯…感觉屏幕还是小了一点)
(本图截自 github, 截图时间为 3 月 12 日。我们看到目前开发进度到了 57%)
一顿操作猛如虎指南

升级你的 Node 到 8(V5 将 Node.js 版本从 6 升级到了 8)
npm install webpack@next —save-dev
npm install webpack-cli —save-dev
package.json 添加 “dev”: “webpack –mode development”
package.json 添加 “prod”: “webpack –mode production”

开始 Webpack V5 尝鲜之旅
新建 src 文件夹,然后新建 index.js。简单的写了一句 console.log(“Hello Webpack5″)
1. dist 打包文件测评
#激动的心 颤抖的手
npm run dev

我的内心毫无波澜…… 卒????…好了,到这里结束了。散了吧~
3 个小时以后…我依旧心不死 发现了这个 issues 解决。让我们一起看看运行成功之后 V5 和 V4 的对比图
<u>V5 打包到 dist 的 main.js</u><u>V4 打包到 dist 的 main.js</u><u>V5 打包过程 </u>

<u>V4 打包过程 </u>
没有文化的我只能说一句,哎呀我去!!体积小了一半之多,而且那个 startup 函数简直骚气的一批????
2. 让人揪心的按需加载
以前当我们想在 index.js 内部 import(./async.js”).then(…)的时候,如果我们什么也不加。V4 会默认对这些文件生成一堆 0.js,1.js,2.js…是多么的整齐. 所以我们需要使用 import(/* webpackChunkName: “name” */ “module”) 才能化解这份尴尬。今天 V5 可以在开发模式中启用了一个新命名的块 id 算法,该算法提供块 (以及文件名) 可读的引用。模块 ID 由其相对于上下文的路径确定。块 ID 是由块的内容决定的,所以你不再需要使用 Magic Comments。
//src 文件夹 index.js
import(“./async.js”).then((_)=>{
console.log(_.data);
})
console.log(“Hello Webpack5”)
//src 文件夹 async.js
const data = “ 异步数据????”;
export default data;
再次编译之后 src_async_js.js 就躺在了 dist 里????。如果这个时候去执行 npm run prod 会在 dist 里出现一个已数字开头的 js 文件。比如我的是 61.js,你可能非常好奇,这是什么鬼❓
3. moduleIds & chunkIds 得已确定
首先我们改造一下上面的文件。
//src 文件夹 index.js
import(“./async.js”).then((_) => {
console.log(_.data);
})
import(“./async2.js”).then((_) => {
console.log(_.data2);
})
console.log(“Hello Webpack5”)
//src 文件夹 async2.js
import common from “./common.js”
console.log(common)
const data2 = “ 异步数据????”;
export default data2;
在 V4 的版本中 async.js、async2.js 会被一次分配给一个 chunkId。然后生成的 main.js 根据 chunkId 加载对应的文件,但是悲剧的事如果此时我删掉 import(“./async.js”).then((_) => {console.log(_.data);}) 这一行的话会导致 async2 进行上位也就是原来的 1 变成了 0。如下图:

利用 BeyondCompare 我们也清晰的看到了 main 的变化。
有同学说这还不好办,我又可以用 Magic Comments、也可以用一些插件就可以固定住他的 moduleIds & chunkIds。是的你说的没错,但是 V5 将不需要引入任何的外力,如上我们遇到 prod 陌生的带数字的 JS,就是为了增强 long-term caching,增加了新的算法,并在生产模式下使用以下配置开启。这些算法以确定性的方式为模块和数据块分配非常短 (3 或 4 个字符) 的数字 id。
//Webpack4 生产环境的默认配置
module.exports = {
optimization:{
chunkIds: “deterministic”,
moduleIds: “deterministic”
}
}
//Webpack4 生产环境的默认配置
module.exports = {
optimization:{
chunkIds: “natural”,
moduleIds: “size”
}
}
如果你觉得这些新特性让你不爽,你依旧可以设置 optimization: {chunkIds: ‘named’} 它是兼容的,这一点还是值得点赞的。
4. 饱受诟病的编译速度
Webpack 的编译速度相信是很多同学比较头痛的问题,当然我们也有很多优化的办法。比如 HappyPack、Cache-loader、排除 node_modules、多线程压缩甚至可以采用分布式编译等等。其实 Webpack 编译慢还跟他的 laoder 机制不无关系,比如 string->ast->string 这一点跟 Parcel 确实有些差距 ????。那在 V5 的版本中都带来些哪些改变呢?其实你只要在配置文件中加上这样一句:
module.exports = {
cache: {
type: “filesystem”
}
}
其实 cache 在 V4 版本中就有 cache, 不过如上这个配置官网上也在说是一个实验性的,也说如果当使用持久缓存时,不再需要 cache-loader。对于 babel cacheDirectory 等也是如此。老袁太忙也没有时间详细的翻所有的 pr 和源码,不过大致运行了下貌似有的效果???? 如果哪位大神这里有空翻过了源码也欢迎在评论区讨论????
(开启缓存之后的编译速度)
5. minSize&maxSize 更好的方式表达
在 V4 版本中默认情况下,仅能处理 javascript 的大小????
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
commons: {
chunks: “all”,
name: “commons”,
minChunks: 1,
minSize: “ 数值 ”,
maxSize: “ 数值 ”
}
}
}
}
}
V5 版本的变更,这个变更简直是太皮了???? 老袁已经试过了,效果还是蛮不错的。
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
commons: {
chunks: “all”,
name: “commons”,
}
},
// 最小的文件大小 超过之后将不予打包
minSize: {
javascript: 0,
style: 0,
},
// 最大的文件 超过之后继续拆分
maxSize: {
javascript: 1, // 故意写小的效果更明显
style: 3000,
}
}
}
}
7. 编译器的优化
如果大家读过 Webpack 的源码一定知道 Compiler 的重要性,在 Webpack 中充斥着大量的钩子和触发事件。

在新的版本中,编译器在使用完毕后应该被关闭,因为它们在进入或退出空闲状态时,拥有这些状态的 hook。插件可以用这些 hook 来执行不太重要的工作(比如:持久性缓存把缓存慢慢地存储到磁盘上)。同时插件的作者应该预见到某些用户可能会忘记关闭编译器,所以 当编译器关闭所有剩下的工作时应尽快完成。然后回调将会通知已彻底完成。当你升级到 v5 时,请确保在完成工作后使用 Node.js API 调用 Compiler.close。
8. Node.js polyfills 自动被移除

过去,Webpack 4 版本附带了大多数 Node.js 核心模块的 polyfills,一旦前端使用了任何核心模块,这些模块就会自动应用,但是其实有些是不必要的。V5 中的尝试是自动停止 polyfilling 这些核心模块,并侧重于前端兼容的模块。当迁移到 v5 时,最好尽可能使用前端兼容的模块,并尽可能手动添加核心模块的 polyfills。Webpack 鼓励大家多提交自己的意见,因为这个更改可能会也可能不会进入最终的 v5 版本。现在微前端已经在很多国内的团队大量应用,老袁个人觉得这个改动对于前端更专注开发模块更有益处。

在本文开头的时候,我们列出了一张作者演讲的图有关于 Webpack 的改动。大家可以点击这里看到全部。新的版本变动必将引起很多插件会出问题,但是 V5 的性能改进是我们更加期待的。最后我想说天下武功出少林,天下技术出基础。大家夯实基础多悟原理才能跟的上变化如此快的前端娱乐圈。
作者 志佳老师
2019 年 03 月 12 日

欢迎继续阅读本专栏其它高赞文章:

12 个令人惊叹的 CSS 实验项目
世界顶级公司的前端面试都问些什么
CSS Flexbox 可视化手册
过节很无聊?还是用 JavaScript 写一个脑力小游戏吧!
从设计者的角度看 React
CSS 粘性定位是怎样工作的
一步步教你用 HTML5 SVG 实现动画效果
程序员 30 岁前月薪达不到 30K,该何去何从
7 个开放式的前端面试题
React 教程:快速上手指南

本文首发微信公众号:jingchengyideng
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章

退出移动版