webpack4 升级

webpack4升级之坑

webpack4出来已经好久,看到之前的vue-cli项目还是基于"webpack": “^3.6.0”,所以参考了一些资料,对webpack3做了升级。

webpack版本升级

"webpack": "^4.29.6"

cnpm i 或者 npm i ,依赖安装,npm run dev 看下效果,出现一堆的错误。不难发现是webpack-dev-server 导致:

webpack-dev-server --inline --progress --config build/webpack.dev.conf.js

module.js:491
    throw err;
    ^

Error: Cannot find module 'webpack/bin/config-yargs'
    at Function.Module._resolveFilename (module.js:489:15)
    at Function.Module._load (module.js:439:25)
    at Module.require (module.js:517:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/xumingxing/Desktop/h5-vue/node_modules/webpack-dev-server/bin/webpack-dev-server.js:54:1)
    at Module._compile (module.js:573:30)
    at Object.Module._extensions..js (module.js:584:10)
    at Module.load (module.js:507:32)
    at tryModuleLoad (module.js:470:12)
    at Function.Module._load (module.js:462:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] dev: `webpack-dev-server --inline --progress --config build/webpack.dev.conf.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:

紧接着,我们就应该继续升级webpack-dev-server ,我将其升级为最新版本,npm run dev 也出错了。主要是compilation.mainTemplate.applyPluginsWaterfall报错,查了资料是 html-webpack-plugin 版本不兼容导致。同样也可将其升级为最新版:

"webpack-dev-server": "^3.2.1",

//报错主要信息
...es/[email protected]1.4.1@punycode/punycode.js/Users/xumingxing/Desktop/h5-vue/node_modules/html-webpack-plugin/lib/compiler.js:81
        var outputName = compilation.mainTemplate.applyPluginsWaterfall('asset-path', outputOptions.filename, {
                                                  ^

TypeError: compilation.mainTemplate.applyPluginsWaterfall is not a function
    at /Users/xumingxing/Desktop/h5-vue/node_modules/html-webpack-plugin/lib/compiler.js:81:51
    at compile (/Users/xumingxing/Desktop/h5-vue/node_modules/[email protected]4.29.6@webpack/lib/Compiler.js:306:11)
    at hooks.afterCompile.callAsync.err 

升级html-webpack-plugin

"html-webpack-plugin": "^3.2.0",

升级完成后,我们再继续npm run dev 看下效果:

Module build failed (from ./node_modules/vue-loader/index.js):
TypeError: Cannot read property 'vue' of undefined
    at Object.module.exports (/Users/xumingxing/Desktop/h5-vue/node_modules/vue-loader/lib/loader.js:61:17)

 @ ./src/main.js 4:0-24 13:16-19
 @ multi ./node_modules/_webpack-dev-[email protected]3.2.1@webpack-dev-server/client?http://localhost:8081 (webpack)/hot/dev-server.js ./src/main.js

页面依旧报错,查询资料后是继续要升级vue-loader,这里将其升级为"15.7.0":

"vue-loader": "^15.7.0"

升级完成后,npm run dev ,又是一大堆错误:

 webpack-dev-server --inline --progress --config build/webpack.dev.conf.js

 94% after seal                                                                

 ERROR  Failed to compile with 2 errors                                                                                                                              15:53:25

 error  in ./src/App.vue

Module build failed (from ./node_modules/vue-loader/index.js):
TypeError: Cannot read property 'vue' of undefined
    at Object.module.exports (/Users/xumingxing/Desktop/h5-vue/node_modules/vue-loader/lib/loader.js:61:17)

 @ ./src/main.js 4:0-24 13:16-19
 @ multi ./node_modules/_webpack-dev-[email protected]3.2.1@webpack-dev-server/client?http://localhost:8081 (webpack)/hot/dev-server.js ./src/main.js

 error  in ./src/components/HelloWorld.vue
star:h5-vue xumingxing$ npm run dev 

> h5-[email protected]1.0.0 dev /Users/xumingxing/Desktop/h5-vue
> webpack-dev-server --inline --progress --config build/webpack.dev.conf.js

 94% after seal                                                                

 ERROR  Failed to compile with 5 errors                                                                                                                              15:56:38

 error  in ./src/components/HelloWorld.vue

Module Error (from ./node_modules/_vue-[email protected]15.7.0@vue-loader/lib/index.js):
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.

 @ ./src/router/index.js 3:0-49 11:15-25
 @ ./src/main.js
 @ multi ./node_modules/_webpack-dev-[email protected]3.2.1@webpack-dev-server/client?http://localhost:8081 (webpack)/hot/dev-server.js ./src/main.js

 error  in ./src/App.vue?vue&type=style&index=0&lang=css&

Module parse failed: Unexpected character '#' (15:0)
You may need an appropriate loader to handle this file type.
| 
| 
> #app {
|   font-family: 'Avenir', Helvetica, Arial, sans-serif;
|   -webkit-font-smoothing: antialiased;

 @ ./src/App.vue 4:0-63
 @ ./src/main.js
 @ multi ./node_modules/_webpack-dev-[email protected]3.2.1@webpack-dev-server/client?http://localhost:8081 (webpack)/hot/dev-server.js ./src/main.js

 error  in ./src/components/HelloWorld.vue?vue&type=template&id=469af010&scoped=true&

错误提示:vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config。这边的错误主要是vue-loader 比较新导致的,新版的vue-loader需要增加新的VueLoaderPlugin:
主要需要在webpack.dev.conf.js以及webpack.prod.conf.js 添加:
const VueLoaderPlugin = require(‘vue-loader/lib/plugin.js’)
并在plugins再实例化一下:

	//...
const VueLoaderPlugin = require('vue-loader/lib/plugin')
	//...
 plugins: [
 	//....
    new VueLoaderPlugin(),
    //...
    ]

之前不小心写成了require(‘vue-loader’),系统报错了。写配置的同学需要注意下

 loaderContext.emitError(new Error(
                  ^

TypeError: loaderContext.emitError is not a function

看了一些资料说是webpack4需要制定打包的模式(mode),自己在npm run dev 的时候并未出现类似的提示,故未作配置。不过有兴趣的也可配置一下,在webpack.dev.conf.js以及webpack.prod.conf.js里添加一下mode:‘development’/mode:‘production’

const webpackConfig = merge(baseWebpackConfig, {
    mode: 'production',
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true,
      usePostCSS: true
    })
  },
  //...
  })

npm run dev ,运行成功了,效果如下:
webpack4 升级
如果需要执行 npm run build,发现又有问题了,系统报错:

Error: webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead.
  at Object.get [as CommonsChunkPlugin] (/Users/xumingxing/Desktop/h5-vue/node_modules/[email protected]4.29.6@webpack/lib/webpack.js:185:10)
  at Object.<anonymous> (/Users/xumingxing/Desktop/h5-vue/build/webpack.prod.conf.js:85:25)
  at Module._compile (module.js:573:30)
  at Object.Module._extensions..js (module.js:584:10)
  at Module.load (module.js:507:32)
  at tryModuleLoad (module.js:470:12)
  at Function.Module._load (module.js:462:3)
  at Module.require (module.js:517:17)
  at require (internal/module.js:11:18)
  at Object.<anonymous> (/Users/xumingxing/Desktop/h5-vue/build/build.js:12:23)
  at Module._compile (module.js:573:30)
  at Object.Module._extensions..js (module.js:584:10)
  at Module.load (module.js:507:32)
  at tryModuleLoad (module.js:470:12)
  at Function.Module._load (module.js:462:3)
  at Function.Module.runMain (module.js:609:10)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! h5-[email protected]1.0.0 build: `node build/build.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the h5-[email protected]1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:

出错的原因是webpack4中 webpack.optimize.CommonsChunkPlugin 已经被弃用,需要使用新的配置 config.optimization.splitChunks。修改webpack.prod.conf.js。首先找到和CommonsChunkPlugin相关的代码,并全部注释。与plugins同级,插入optimization配置

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
     )
   }
 }),
 // extract webpack runtime and module manifest to its own file in order to
 // prevent vendor hash from being updated whenever app bundle is updated
 new webpack.optimize.CommonsChunkPlugin({
   name: 'manifest',
   minChunks: Infinity
 }),
 // This instance extracts shared chunks from code splitted chunks and bundles them
 // in a separate chunk, similar to the vendor chunk
 // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
 new webpack.optimize.CommonsChunkPlugin({
   name: 'app',
   async: 'vendor-async',
   children: true,
   minChunks: 3
})

optimization配置:

 optimization: {
      splitChunks: {
          cacheGroups: {
              commons: {
                  name: "commons",
                  chunks: "initial",
                  minChunks: 2
              }
          }
      }
  },

更改后,再重新执行npm run build ,又报错了:

Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
    at Chunk.get (/Users/xumingxing/Desktop/h5-vue/node_modules/[email protected]4.29.6@webpack/lib/Chunk.js:849:9)
    at /Users/xumingxing/Desktop/h5-vue/node_modules/_extract-text-webpack-[email protected]3.0.2@extract-text-webpack-plugin/dist/index.js:176:47
    at Array.forEach (<anonymous>)
    at /Users/xumingxing/Desktop/h5-vue/node_modules/_extract-text-webpack-[email protected]3.0.2@extract-text-webpack-plugin/dist/index.js:171:18
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/xumingxing/Desktop/h5-vue/node_modules/[email protected]1.1.1@tapable/lib/HookCodeFactory.js:32:10), <anonymous>:7:1)

不难发现,Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead。上网查了下,解决这个问题方法较多。可以升级extract-text-webpack-plugin:

 "extract-text-webpack-plugin": "^4.0.0-beta.0",

同样也是可以用 mini-css-extract-plugin进行处理,我这里就是用mini-css-extract-plugin进行处理。
本文升级成功后的demo下载地址:https://github.com/yzbyxmx/h5-vue.git