资讯专栏INFORMATION COLUMN

如何优雅的升级到 webpack4

zhangfaliang / 2690人阅读

摘要:默认出入口在中,不再强制要求指定和路径。构建模式提供了两种构建模式可供选择和选项描述会将的值设为。如果是,那就会开启。默认只会对按需加载的代码做分割。在或更低版本中,如果你想为一个推导出来的定制选项,你不得不在自己的选项中将它重复一遍。

前言

现在距离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,喜欢的话可关注

参考

webpack 文档

webpack github release

Webpack 4 配置最佳实践

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96035.html

相关文章

  • 如何搭建一个基于react、webpack4、babel7项目(一)

    摘要:对的工作流程有点模糊,以及据官方文档称的升级,性能得到了极大的提升,而还是用的,于是决定从头开始搭建一个适合团队的脚手架。保证各文件获得一致的文件编码和缩进效果。这些在后面文章中,都会一个个涉及到,此处不做详细展开。 前言 写前端项目这么久了,以前用的 dva 框架,后来用过 create-react-app 框架,都需要针对团队做一些定制化的修改。对 webpack 的工作流程有点模...

    IamDLY 评论0 收藏0
  • 为什么我不推荐你使用vue-cli创建脚手架?

    摘要:后来经过排查你会发现是由于目前还没有版本。可以使用该方式解决。这就是我为什么不推荐你使用创建脚手架的原因此文的受众是想要进阶中级的初级前端人员。 最近在知乎看到一个问题,原问题如下: 很奇怪,为什么现在能找到自己手动创建vue脚手架的文章非常少,而且大家似乎对webpack4的热情并不高,对于想基于vue2.0+webpack4搭建一个脚手架的我来说资料真是少得可怜。难道现在一般的做...

    trigkit4 评论0 收藏0
  • webpack4升级完全指南

    摘要:官方已经于近日升级到了的稳定版本,对应的一些必备插件也陆续完成了更新支持,笔者在第一时间完成了项目由到的迁移,在此记录一下升级过程中遇到的种种问题和对应的解决手段,方便后续入坑者及时查阅,减少重复工作,如果觉得本篇文章对你有帮助,欢迎点赞 webpack4官方已经于近日升级到了V4.5的稳定版本,对应的一些必备插件(webpack-contrib)也陆续完成了更新支持,笔者在第一时间完...

    Michael_Ding 评论0 收藏0
  • webpack4.0测试版指南

    摘要:我们发布了新版本的插件系统,以便事件挂钩和处理程序是单态的。倒计时按照承诺,我们将从今天开始等待一个月,然后再释放稳定版。这为我们的插件,加载程序和集成生态系统提供了测试,报告和升级到的时间我们需要您帮助我们升级并测试此测试版。 自8月初以来—当我们将 nex branch 合并到webpack/webpack#master—我们看到了巨大的贡献! showImg(https://se...

    MageekChiu 评论0 收藏0
  • webpack4.x升级摘要

    摘要:以为例,编写来帮助我们完成重复的工作编译压缩我只要执行一下就可以检测到文件的变化,然后为你执行一系列的自动化操作,同样的操作也发生在这些的预处理器上。的使用是针对第三方类库使用各种模块化写法以及语法。 showImg(https://segmentfault.com/img/bVbtZYK); 一:前端工程化的发展 很久以前,互联网行业有个职位叫做 软件开发工程师 在那个时代,大家可能...

    levinit 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<