webpack4:连奏中的进化 (2)

其中,可以发现SplitChunksPlugin产出的vendor-chunk有多个,对于入口A来说,引入的代码只有chunkA、vendor-chunkA-B、vendor-chunkA-C、vendor-chunkA-B-C;这时候chunkA、vendor-chunkA-B、vendor-chunkA-C、vendor-chunkA-B-C形成了一个chunkGroup。下面举个列子:

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

产出后的chunk:

vendor-chunkA-C:vuex vendor-chunkB-C:axios vendor-chunkA-B-C:vue chunkA: only the components chunkB: only the components chunkC: only the components

SplitChunksPlugin能够解决掉CommonsChunkPlugin中提到的三个问题,SplitChunksPlugin在production模式下是默认开启的,但是它默认只作用于异步chunk,如果要作用于入口chunk的话,需要配置optimization.splitChunks.chunks: "all",同时webpack自动split chunks是有几个限制条件的:

新产出的vendor-chunk是要被共享的,或者模块来自npm包;

新产出的vendor-chunk的大小得大于30kb;

并行请求vendor-chunk的数量不能超出5个;

对于entry-chunk而言,并行加载的vendor-chunk不能超出3个。

这些限制可以在SplitChunks的默认配置项中可以一一对应的看到。

splitChunks: { chunks: "async", minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, name: true, cacheGroups: { default: { minChunks: 2, priority: -20 reuseExistingChunk: true, }, vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 } } }

其实不难理解这些限制,因为SplitChunksPlugin产生的结果就是原来chunk被拆分了,引入的文件数量会变多,因此需要在文件数量上进行限制。

runtimeChunkPlugin

在使用CommonsChunkPlugin的时候,我们通常会把webpack runtime的基础函数提取出来,单独作为一个chunk,毕竟code splitting想把不变的代码单独抽离出来,方便浏览器缓存,提升加载速度。webpack4废弃了CommonsChunkPlugin,采用了runtimeChunkPlugin可以将每个entry chunk中的runtime部分的函数分离出来,只需要一个简单的配置:optimization.runtimeChunk: true。

sideEffects

在webapck2开始支持ESModule后,webpack提出了tree-shaking进行无用模块的消除,主要依赖ES Module的静态结构。在webapck4之前,主要通过在.babelrc文件中设置"modules": false来开启无用的模块检测,该方法显然比较粗暴。webapck4灵活扩展了如何对某模块开展无用代码检测,主要通过在package.json文件中设置sideEffects: false来告诉编译器该项目或模块是pure的,可以进行无用模块删除。
官方的github上提供了一个sideEffects的demo示例供参考,如果对tree-shaking的概念不是太了解,可去官方的文档中tree-shaking部分详细了解。下面是官方提供的一个减包效果示例,仅供欣赏。

webpack4:连奏中的进化

支持压缩ES6+代码

在webapck4之前,webpack.prod.conf.js中关于UglifyJsPlugin的注释会有这么一段话:

// UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify

意思就是UglifyJs无法对ES6+的代码进行压缩,需使用babel-minify获取更好的treeshaking效果。webapck4目前已经支持压缩ES6+的代码。

// 源代码 import {sayHello} from './libs/js/util.js' let output = sayHello('hwm'); console.log(output); // 产出 ...let r=(e=>`Hello ${e}!`)("hwm");console.log(r)}... 支持更多的模块类型

webpack4支持以import和export形式加载和导出本地的WebAssembly模块,这一块本人实际项目并未使用到,暂不做介绍;此外,webpack4支持json模块和tree-shaking,之前json文件的加载需要json-loader的支持,webpack4已经能够支持json模块(JSON Module),不需要额外的配置;此外,当json文件用ESModule的语法import引入的时候,webpack4还能支持对json模块进行tree-shaking处理,把用不到的字段过滤掉,起到减包的作用。下面是个示例:

// 引用数据的三种方法 let jsonData = require('./data/test.json'); import jsonData from './data/test.json' // 打包时只会提取test.json文件中onePart部分。 import { onePart } from './data/test.json' 如何迁移升级到webpack4 0配置的局限性

webpack4声称能够0配置,但是0配置有很多局限性,比如只能是单入口的项目,入口和产出的文件名是固定的,entry是src目录下的index.js,产出是dist目录下的main.js,很明显不能满足实际项目应用。于是,开发者还是得自己配置webpack.config.js文件。

webpack4配置文件的变化点

如何配置webpack4下的配置文件,需要大致了解webapck4的配置项的改动点。
mode:开发模式 development

开启dev-tool,方便浏览器调试

提供详细的错误提示

利用缓存机制,实现快速构建

开启output.pathinfo,在产出的bundle中显示模块路径信息

开启NamedModulesPlugin

开启NoEmitOnErrorsPlugin

mode:生产模式 production

启动各种优化插件(ModuleConcatenationPlugin、optimization.minimize、ModuleConcatenationPlugin、Tree-shaking),压缩、合并、拆分,产出更小体积的chunk

关闭内存缓存

开启NoEmitOnErrorsPlugin

plugin

内置optimization.minimize来压缩代码,不用再显示引入UglifyJsPlugin;

废弃CommonsChunkPlugin插件,使用optimization.splitChunks和optimization.runtimeChunk来代替;

使用optimization.noEmitOnErrors来替换NoEmitOnErrorsPlugin插件

使用optimization.namedModules来替换NamedModulesPlugin插件

loader

废弃json-loader,友好支持json模块,以ESMoudle的语法引入,还可以对json模块进行tree-shaking处理;

其他的改动信息建议查看webpack的中文升级日志。

vue-cli项目如何改造

介绍完了webpack4中核心配置项的变化,接下来结合vue-cli示例项目介绍一下,如何配置webpack.conf.js文件。
1.升级npm包版本

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

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