webpack4:连奏中的进化

webpack4在2月底的时候发布,这次webpack4有了一个名字"Legato",也就是"连奏"的意思,寓意webpack在不断进化,而且是无缝(no-gaps)的进化。webpack的进化点是通过捐赠者和用户投票来决定的,之前在介绍webpack3的时候,曾给出过投票数在前几名的优化点,集中在用户体验、构建性能(速度和产出大小)、通用和适配性(es module、typescript、web assemble)等。webpack4发布了,下面将结合文档和实践,验证一下webpack是否兑现了当初的诺言。

webpack4中的新特性

webpack3官方发布的时候,提到了下个版本可能的改动点,翻译过来如下所示:

高性能的构建缓存

提升初始化速度和增量构建效率

更好的支持Type Script

修订长期缓存

支持WASM 模块支持

提升用户体验

webpack4官方发布的文档之中主要提及了以下新特性:

支持零配置(Zero Configuration)

该特性主要用于解决webpack的门槛高问题,webpack是一个配置声明式的操作模式,npm、gulp是指令式的,需要描述每一步是干什么的,而webpack的配置项凌乱且无序,让很多开发者头疼。
webpack4提供了零配置方案,默认入口属性为./src,默认输出路径为./dist,不再需要配置文件,实现了开箱即用的封装能力,更通俗的讲,webpack会自动查找项目中src目录下的index.js文件,然后选择的模式进行相应的打包操作,最后新建dist目录并生成一个main.js文件。此外针对开发环境和线上环境提供了两种打包模式:"production"和"development","production"模式内置了项目产出时的基本配置项,"development"模式基本满足了快速构建和开发体验。使用的方法是在运行webapck命令的时候,设置好mode参数的值即可,默认是production属性。

"scripts": { "dev": "webpack --mode development", "build": "webpack --mode production" }

具体的案例可以前往github进行下载。

下面根据官方的文档介绍一下两种模式。

Production模式

提供了发布程序时的优化配置项,旨在更小的产出文件、更快的运行速度、不暴露源码和路径。会默认采用代码压缩(minification),作用域提升(scope hoisting),tree-shaking,NoEmitOnErrorsPlugin,无副作用模块修剪(side-effect-free module pruning)等。

Development模式

旨在提升开发调试过程中的体验,如更快的构建速度、调试时的代码易读性、暴露运行时的错误信息等。会默认采用bundle的输出包含路径名和eval-source-map等,提升代码的可读性和构建速度。

两种模式就是两个箱子,箱子里面就是各种插件工具,只是有些是开启的,有些是关闭的,具体有哪些工具可以参考这篇文章。

废弃CommonsChunkPlugin

webpack4废弃了CommonsChunkPlugin,引入了optimization.splitChunks和optimization.runtimeChunk,旨在优化chunk的拆分。先介绍一下code splitting下的CommonsChunkPlugin有什么缺点,然后仔介绍一下chunk split是怎么进行优化的。

CommonsChunkPlugin的问题

CommmonsChunkPlugin的思路是Create this chunk and move all modules matching minChunks into the new chunk,即将满足minChunks配置想所设置的条件的模块移到一个新的chunk文件中去,这个思路是基于父子关系的,也就是这个新产出的new chunk是所有chunk的父亲,在加载孩子chunk的时候,父亲chunk是必须要提前加载的。举个例子:

example: entryA: vue vuex someComponents entryB: vue axios someComponents entryC: vue vux axios someComponents minchunks: 2

产出后的chunk:

vendor-chunk:vue vuex axios chunkA~chunkC: only the components

带来的问题是:对entryA和entryB来说,vendor-chunk都包含了多余的module。
CommonsChunkPlugin另外一个问题是:对异步的模块不友好。下面也举例说明:

example: entryA: vue vuex someComponents asyncB:vue axios someComponents entryC: vue vux axios someComponents minchunks: 2

产出后的chunk:

vendor-chunk:vue vuex chunkA: only the components chunkB: vue axios someComponents chunkC: axios someComponents

带来的问题是:如果asyncB在entryA中动态引入,则会引入多余的module。
总的来说CommonsChunkPlugin有以下三个问题:

产出的chunk在引入的时候,会包含重复的代码;

无法优化异步chunk;

高优的chunk产出需要的minchunks配置比较复杂。

SplitChunksPlugin

与CommonsChunkPlugin的父子关系思路不同的是,SplitChunksPlugin引入了chunkGroup的概念,在入口chunk和异步chunk中发现被重复使用的模块,将重叠的模块以vendor-chunk的形式分离出来,也就是vendor-chunk可能有多个,不再受限于是所有chunk中都共同存在的模块,原理的示意如下图所示:

webpack4:连奏中的进化

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydxyp.html