为了账号安全,请及时绑定邮箱和手机立即绑定

如何优雅的升级到webpack4

文章地址:leizore---原文地址

前言

现在距离2018年2月15号webpack4.0.0出来已经有一段时间了,现在已经出了 @vue/cli 3.0,但是楼主还没试过,听说很强大,想要试水的可以看文档 @vue/cli,官方脚手架都用上webpack4了,你项目还停留在webpack3,甚至webpack2,是不是觉得落伍了。 受号称0配置的parcel启发,webpack4 增加了一些默认配置,摒弃掉了一些难懂的配置,对用户更加友好,下面我来讲一讲比较大的一些变化

环境

不再支持 Node.js 4。

默认出入口

在 Webpack 4 中,不再强制要求指定 entry 和 output 路径。webpack 4 会默认 entry 为 ./src,output 为 ./dist,当然了,这只是开胃菜。

mode 构建模式

webpack 提供了两种构建模式可供选择 development 和 production

选项描述
development会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin(固化 runtime 内以及在使用动态加载时分离出的 chunk 的 chunk id) 和 NamedModulesPlugin(开启 HMR[热重载]的时候使用该插件会显示模块的相对路径)。
production会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin.

也就是说如果 mode 为development 时候官方脚手架可以砍掉的代码

// webpack.development.config.js module.exports = { + mode: 'development' - plugins: [ -   new webpack.NamedModulesPlugin(), -   new webpack.DefinePlugin({ -     'process.env': require('../config/dev.env') -   }), - ] } 复制代码

如果 mode 为production 时候官方脚手架可以砍掉的代码

 // webpack.production.config.js module.exports = { +  mode: 'production', -  plugins: [ -    new UglifyJsPlugin(/* ... */), -    new webpack.DefinePlugin({ -       'process.env': require('../config/dev.env') -    }), -    new webpack.optimize.ModuleConcatenationPlugin() -  ] } 复制代码

import(): 动态导入

在 webpack 4 中,import() 会返回一个带命名空间(namespace)的对象,这对 ES Module 不会有影响,但对于遵循 commonjs 规范的模块则会加一层包裹:

// webpack 2/3 import("./commonjs").then(exports => { // ... }) // webpack 4 import("./commonjs").then({default: exports}=> { // ... }) 复制代码

optimization 配置项

配置项新增了 optimization 选项,智能的根据所选模式mode为做运行优化。

使用这个配置的时候之前的一些插件可以使用 optimization 里的配置代替

  • NoEmitOnErrorsPlugin 替换为 optimization.noEmitOnErrors (默认只在 production 模式)

  • ModuleConcatenationPlugin 替换为 optimization.concatenateModules(默认只在 production 模式)

  • NamedModulesPlugin 替换为 optimization.namedModules(默认只在 develoment 模式) CommonsChunkPlugin 插件被弃用,使用 optimization.splitChunks, optimization.runtimeChunk 代替

// webpack.prod.conf.js const config = {    // ...    plugins: [ -    new webpack.NoEmitOnErrorsPlugin(), -    new webpack.optimize.ModuleConcatenationPlugin(),    // 预编译 -    new webpack.optimize.CommonsChunkPlugin({ -      name: 'vendor', -      minChunks (module) { -        // any required modules inside node_modules are extracted to vendor -        return ( -          module.resource && -          /\.js$/.test(module.resource) && -          module.resource.indexOf( -            path.join(__dirname, '../node_modules') -          ) === 0 -        ) -      } -    }), -    new webpack.optimize.CommonsChunkPlugin({ -      name: 'manifest', -      minChunks: Infinity -    }),    ], +  optimization: { +    noEmitOnErrors: true, +    concatenateModules: true, +    splitChunks: {  +       chunks: 'all',  +       name: 'common',  +    },  +    runtimeChunk: {  +        name: 'runtime' +    } +  } }; 复制代码
// webpack.dev.conf.js const config = {    // ...    plugins: [ -    new webpack.NamedModulesPlugin()    ] +  optimization: { +    namedModules: true +  } }; 复制代码

optimization.splitChunks 默认是不用设置的。如果 mode 是 production,那 Webpack 4 就会开启 Code Splitting。默认 Webpack 4 只会对按需加载的代码做分割。如果我们需要配置初始加载的代码也加入到代码分割中,可以设置 splitChunks.chunks 为 'all'

压缩

webpack4 的mode 设置成 production 时,默认开启代码压缩,但是我要敲黑板,划重点了,uglifyjs-webpack-plugin 终于到 v1.0.0 版本了,支持多进程压缩,缓存以及es6语法,无需单独安装转换器。感动不感动。想看的话可以看这里顺风车。想要覆盖配置可以这样

const UglifyJsPlugin = require('uglifyjs-webpack-plugin') module.exports = {   // ...   optimization: {     minimizer: [       new UglifyJsPlugin() // 具体配置可看github     ]   } } 复制代码

##移除的功能 ## 移除了 module.loaders 移除了 loaderContext.options 移除了 Compilation.notCacheable 移除了 NoErrorsPlugin 移除了 Dependency.isEqualResource 移除了 NewWatchingPlugin 移除了 CommonsChunkPlugin

周边

既然讲了 webpack 做了比较大的更新,周边的配套设施也不要不舍得,改换久换,由于我平时项目中使用vue,如果你也使用vue的话,那么针对vue的有几个变化你要知道:

vue-loader

什么?学不动了,只要用官网的脚手架不就好了?前端的知识不断更新,固步自封,只会不进则退。但是你要相信,webpack也好,vue-loader 也好,api 会越来越好懂,性能也会更加高效,所以,扶我起来,我还能学。。。

Vue Loader v15 使用了一个不一样的策略来推导语言块使用的 loader。vue-loader v15 在 v14 或更低版本中,如果你想为一个推导出来的 loader 定制选项,你不得不在 Vue Loader 自己的 loaders 选项中将它重复一遍。在 v15 中你再也没有必要这么做了。 拿官方脚手架来说, 可以看到两个函数,用来生成 vue-loader 的 options 还有 module.rule, 我把他们摘出来,就可以看出来了。

// util.js exports.cssLoaders = function (options) {    // ... } // Generate loaders for standalone style files (outside of .vue) exports.styleLoaders = function (options) {   // ... } 复制代码
// vue-loader-conf.js module.exports = {   loaders: utils.cssLoaders({     sourceMap: sourceMapEnabled,     extract: isProduction   }),   ... } 复制代码
// webpack.dev.config const devWebpackConfig = merge(baseWebpackConfig, {   module: {     rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })   },   ... } 复制代码

我刚入脚手架的坑的时候都蒙了,为什么要这样写,为了德玛西亚么?当然不是,是因为填 vue-loader v14 的坑 vue-loader v15版本只要写一遍就好了,但是要注意请确保在你的 webpack 配置中添加 Vue Loader 的插件

// webpack.config.js const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = {   module: {     rules: [       {         test: /\.vue$/,         loader: 'vue-loader'       },       // ...     ]   },   plugins: [     // 请确保引入这个插件!     new VueLoaderPlugin()   ] } 复制代码

然后由于生产和测试环境对 css 文件处理不同。在webpack.dev.config.js和webpack.prod.config.js里分别配置 less/scss css 的loader就好了:

{   module: {     rules: [       // ...       {         test: /\.less$/,         use: [           'vue-style-loader',           'css-loader',           'less-loader'         ]       }     ]   } } 复制代码

mini-css-extract-plugin css 抽取

webpack v4 官方不在推荐使用 extract-text-webpack-plugin 了,改换 mini-css-extract-plugin

// webpack4 npm install -D mini-css-extract-plugin // webpack.config.js var MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = {   // 其它选项...   module: {     rules: [       // ... 忽略其它规则       {         test: /\.css$/,         use: [           process.env.NODE_ENV !== 'production'             ? 'vue-style-loader'             : MiniCssExtractPlugin.loader,           'css-loader'         ]       }     ]   },   plugins: [     // ... 忽略 vue-loader 插件     new MiniCssExtractPlugin({       filename: style.css     })   ] } 复制代码
// webpack3 npm install -D extract-text-webpack-plugin // webpack.config.js var ExtractTextPlugin = require("extract-text-webpack-plugin") module.exports = {   // 其它选项...   module: {     rules: [       // ...其它规则忽略       {         test: /\.css$/,         loader: ExtractTextPlugin.extract({           use: 'css-loader',           fallback: 'vue-style-loader'         })       }     ]   },   plugins: [     // ...vue-loader 插件忽略     new ExtractTextPlugin("style.css")   ] } 复制代码

福利

对webpack3官方脚手架还不是很了解的同学可以看我根据自己理解写的注释,详情点这里 觉得麻烦,不想自己搞?那也没关系,我自己按照脚手架改了一套,感兴趣的可以试试点这里 觉得不错请star哦,另外,我准备在下一篇文章中将如何如优化webpack,喜欢的话可关注

参考

  1. webpack 文档

  2. webpack github release

  3. Webpack 4 配置最佳实践


点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消