最近公司项目从webpack4升级到webpack5。配置了webpack5的长期缓存后,二次构建的速度直接提升了80%以上,打包体积也减少了。当然,前提是调查清楚太多。网上有一些做法是直接升级所有相关的包,不过我是一个一个升级的。如果需要再次升级,有些包还没有升级(比如babel-loader等),大部分项目本身使用的都是较新的。版本。Webpack5的新特性首先我们要先了解升级Webpack5能给我们带来哪些好处。首先我们来看一下Webpack5的新特性。通过持久的硬盘缓存能力提高构建性能,通过更好的算法提高长期缓存(降低产品资源的缓存失败率)通过更好的TreeShaking能力和代码生成逻辑优化产品的大小提高web的兼容性platform清理Webpack4引入一些新特性时遗留下来的一些奇怪的东西,内部结构没有大的更新状态通过引入一些大的变化为一些未来的特性做准备,使其在Webpack5版本上长期稳定。最吸引我的是构建性能的提升和更好的treeshaking能力来优化产品的大小。Webpack5版本的构建速度为什么会有质的飞跃?主要原因是:webpack4是根据代码的结构生成chunkhash,添加空行或者注释会导致chunkhash发生变化,而webpack5是根据内容生成chunkhash,改变注释或者变量不会改变chunkhash,浏览器可以继续使用缓存。优化缓存使用效率。在webpack4中,chunkId和moduleId都是自增的id。只要我们添加一个新的模块,代码中的模块数量就会发生变化,从而导致moduleId发生变化,因此文件内容也会发生变化。chunkId也是一样。添加条目时,chunk数量的变化导致chunkId的变化,从而导致文件内容发生变化。因此,实际未改变的chunk文件无法得到有效利用。webpack5使用一种新的算法来计算确定性的chunkId和moduleId。可以有效地利用缓存。在生产模式下,optimization.chunkIds和optimization.moduleIds默认设置为'deterministic'。添加了可以将缓存写入磁盘的配置项。在命令行中终止当前构建任务,再次开始构建时,可以复用上次写入硬盘的缓存,加快构建过程。以上三个解释引用自Webpack5惊人的构建速度提升,早升级早受益我们的项目直接升级到最新版本后不需要兼容库。本身配置不多,但是如果你的项目插件写的配置项比较多,可能会有需要兼容的地方。webpackwebpack-clihtml-webpack-pluginterser-webpack-pluginmini-css-extract-pluginstyle-loader,css-loader,postcss,postcss-loader(upgrade)兼容的资源模块类型在webpack4及之前,我们会使用各种loader来处理一些资源,如file-loader、url-loader、raw-loader等,但是webpack5内置了静态资源构建能力,不需要安装这些额外的loader,通过简单的配置就可以实现静态资源打包。asset模块类型通过添加4个新的模块类型替换了所有这些加载器:asset/resource发送一个单独的文件并导出URL。以前通过使用文件加载器实现。asset/inline导出资产的数据URI。以前是通过使用url-loader实现的。asset/source导出资产的源代码。以前是通过使用raw-loader实现的。资产会自动在导出数据URI和发送单独的文件之间进行选择。之前是通过使用url-loader并配置资源量限制来实现的。示例:module:{rules:[{test:/\.(png|jpg|jpeg|gif)$/,type:`asset/resource`}]},webpack-dev-server需要注意:webpack-dev-serverv4.0.0+要求node>=v12.13.0将webpack-dev-server升级到^4(next)版本,否则HMR会出现异常的wbepack4启动方式:webpack-dev-server。webpack5修改为:webpackserver//v4devServer:{contentBase:path.resolve(__dirname,'../dist'),compress:true,inline:true,//构建变化后的代码将由代理控制客户端网页刷新host:'0.0.0.0',port:PORT,clientLogLevel:'info',historyApiFallback:true,stats:'errors-only',disableHostCheck:true,}//v5devServer:{//contentBase变成静态对象配置静态:{directory:path.resolve(__dirname,'../dist'),},client:{logging:'info',},compress:true,//inline:true,//直接删除,否alternativehost:'0.0.0.0',port:PORT,historyApiFallback:true,allowedHosts:'all',//而不是disableHostCheck:true//新的中间件配置devMiddleware:{stats:'errors-only',},},相关文章:webpack-dev-serverv3migrationv4guideWebpack5removesNode.jsPolyfill(compatible)Webpack5removesNode.jsPolyfill,会导致部分包不可用(会在控制台输出'XXX'未定义),如果需要兼容process/buffer等NodejsPolyfills,需要安装相关的Polyfill:process,并在Plugin中显式声明注入。业务代码中使用到流程变量,需要兼容,同时安装流程/缓冲库。{plugins:[newwebpack.ProvidePlugin({process:'process/browser',}),]}升级废弃的配置项项目配置项改动前的含义(config/webpack_prod.ts):splitChunks:{chunks:'all',minSize:30000,//模块大于30kb才会被提取minChunks:1,//最小引用数,默认1maxAsyncRequests:5,//加载时最大并发请求数codeasynchronouslymustnotexceed5maxInitialRequests:3,//加载入口文件时最大并发请求数不能超过3。automaticNameDelimiter:'_',//模块文件名前缀名:true,//自动生成文件名cacheGroups:{//模块从node_modules中提取到一个普通文件vendors:{test:/[\\/]node_modules[\\/]/,priority:-10,//执行优先级,默认为0},//其他不在node_modules中的模块,如果被引用不少于2次,也会被提取default:{minChunks:2,priority:-20,reuseExistingChunk:true,//如果当前代码块包含的模块已经存在,则不会产生重复块},},},//v5splitChunks:{cacheGroups:{//vendors——>defaultVendorsdefaultVendors:{test:/[\\/]node_modules[\\/]/,priority:-10,//执行优先级,默认为0},},},改名在(config/webpack_prod.ts)到splitChunks.name(删除)splitChunks.name表示提取文件的名称。在v4中,这个配置默认为true,表示文件名是自动生成的。在v5中,删除了optimization.splitChunks的名称:true:不再支持自动命名迁移:使用默认值chunkIds:“named”将为您的文件提供一个有用的名称,用于调试输出配置(兼容性)(节点:58337)[DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_HASH]DeprecationWarning:[hash]isnow[fullhash](alsoconsiderusing[chunkhash]or[contenthash],seedocumentationfordetails)hashhasbeendeprecated,改为fullhash,这个名字比原来的hashconfig/webpack_dev更清晰.ts//v4output:{filename:'js/[name].[hash].js',chunkFilename:'js/[name].[hash].js',},//v5output:{filename:'js/[name].[fullhash].js',chunkFilename:'js/[name].[fullhash].js',},优化配置项(弃用和移除)(config/webpack_prod.ts)//webpackv4有在v5中被弃用,因此需要移除newwebpack.HashedModuleIdsPlugin()HashedModuleIdsPlugin功能:实现持久化缓存。模块ID由HashedModuleIdsPlugin计算,它将基于数字增量的ID替换为模块本身的哈希值。这样,一个模块的ID只会在重命名或移除时发生变化,新模块不会影响其ID的变化。webpack5增加了对确定性moduleId和chunkId的支持,如下:optimization.moduleIds='deterministic'optimization.chunkIds='deterministic'该配置在生产模式下默认开启,其作用是确定性地定义模块并为chunk分配一个3-5位的id,替代了v4版本的HashedModuleIdsPlugin。全局变量写法(兼容性)module.exports=()=>{return{//...plugins:[//webpack5定义环境变量写法变了newwebpack.DefinePlugin({'process.env.NODE_ENV':JSON.stringify('production'),}),//webpack4的写法//newwebpack.DefinePlugin({//'process.env':{//NODE_ENV:JSON.stringify('production'),//},//}),],};};使用缓存属性优化缓存(新添加)。默认情况下,webpack5不会开启持久化缓存,如果不手动添加缓存配置,webpack5等于没有优化,可以直接升级二次构建,反而更慢;升级时不会自动提速,或者手动配置cache.type:"filesystem"时,webpack会在内部分层开启文件系统缓存和内存缓存。从缓存中读取时,首先检查内存缓存,如果没有找到内存缓存,则降级为文件系统缓存。写缓存将写入内存缓存和文件系统缓存。文件系统缓存不直接序列化写入磁盘的请求。它将等到编译过程完成并且编译器空闲后再执行。这样做的原因是序列化和磁盘写入是资源密集型的,我们不想额外延迟编译过程。cache:{//设置缓存类型为文件系统,默认为memorytype:'filesystem',buildDependencies:{//当config文件的内容(通过requiredependency)改变时,缓存会失效config:[__filename],//如果你有其他构建依赖的东西,可以在这里添加},},为了防止缓存过于固定,导致改变构建配置没有感知,旧的缓存是仍然使用,默认情况下,每次构建修改配置文件都会导致缓存重新启动。当然你也可以主动设置版本来控制缓存的更新。最终优化结果第一次编译:第二次编译:效果:二次构建提速85%以上升级惊艳,早升级早受益
