Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

记录vue-cli项目升级到webpack4以及升级到Babel7一步一步踩坑以及解决 #35

Open
heyushuo opened this issue May 9, 2020 · 2 comments

Comments

@heyushuo
Copy link
Owner

heyushuo commented May 9, 2020

1. 优先升级webpack3至webpack4,因为webpack需要和webpack-cli配合使用所以两个需要同时升级

cnpm i -D webpack@latest webpack-cli@latest

然后运行 npm run dev 运行之后报错

Error: Cannot find module 'webpack/bin/config-yargs'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
    at Function.Module._load (internal/modules/cjs/loader.js:562:25)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.<anonymous> (E:\project\heyushuo-cli\node_modules\_webpack-dev-server@2.11.5@webpack-dev-server\bin\webpack-dev-server.js:54:1)

通过报错大概知道是webpack-dev-server版本不匹配所以升级版本

cnpm i -D webpack-dev-server@latest

2. 继续npm run dev 运行之后报错

:\project\heyushuo-cli\node_modules\_html-webpack-plugin@2.30.1@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 E:\project\heyushuo-cli\node_modules\_html-webpack-plugin@2.30.1@html-webpack-plugin\lib\compiler.js:81:51
    at compile (E:\project\heyushuo-cli\node_modules\_webpack@4.43.0@webpack\lib\Compiler.js:343:11)
    at hooks.afterCompile.callAsync.err (E:\project\heyushuo-cli\node_modules\_webpack@4.43.0@webpack\lib\Compiler.js:681:15)

从报错中可以看出是html-webpack-plugin插件中的某些函数报错了,接着升级到最新版本

cnpm i -D html-webpack-plugin@latest

3. 继续npm run dev 运行之后报错如下

Module build failed (from ./node_modules/_eslint-loader@1.9.0@eslint-loader/index.js):
TypeError: Cannot read property 'eslint' of undefined
    at Object.module.exports (E:\project\heyushuo-cli\node_modules\_eslint-loader@1.9.0@eslint-loader\index.js:148:18)

可以看出是eslint报错的原因,接着升级,把package.json中所有和eslint相关的都升级一下

cnpm i D eslint@latest eslint-config-standard@latest eslint-friendly-formatter@latest eslint-loader@latest eslint-plugin-import@latest eslint-plugin-node@latest eslint-plugin-promise@latest eslint-plugin-standard@latest eslint-plugin-vue@latest eslint-plugin-html@latest

4. 继续npm run dev 运行之后报错如下

Module build failed (from ./node_modules/_vue-loader@13.7.3@vue-loader/index.js):
TypeError: Cannot read property 'vue' of undefined
    at Object.module.exports (E:\project\heyushuo-cli\node_modules\_vue-loader@13.7.3@vue-loader\lib\loader.js:61:18)

可以看出是vue-loader报错的原因(顺便把和vue相关的都进行升级),接着升级到最新版本

cnpm i D vue-loader@latest vue-style-loader@latest vue-template-compiler@latest

5. 继续npm run dev 运行之后报错如下

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

报错可以看出Make sure to include VueLoaderPlugin in your webpack config需要修改webpack配置如下

//分别在webpack.base.conf.js中添加VueLoaderPlugin

const { VueLoaderPlugin } = require('vue-loader')
plugins:[
  new VueLoaderPlugin()
]

6. 继续npm run dev 成功启动应用了,接下来打包试试npm run build 报错如下

Error: webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead.
    at Object.get [as CommonsChunkPlugin] (E:\project\heyushuo-cli\node_modules\_webpack@4.43.0@webpack\lib\webpack.js:189:10)

由于webpack4 移除了 CommonsChunkPlugin,所以需要在配置上做一些修改。去除webpack.prod.conf.js中与 CommonsChunkPlugin,webpack4中使用optimization替换掉了CommonsChunkPlugin

 // split vendor js into its own file
    // 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默认使用''压缩代码性能要比UglifyJsPlugin好,所以直接把vue-cli中使用`UglifyJsPlugin'地方去掉就可以了

7. 继续npm run build,报错如下

Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
    at Chunk.get (E:\project\heyushuo-cli\node_modules\_webpack@4.43.0@webpack\lib\Chunk.js:866:9)
    at E:\project\heyushuo-cli\node_modules\_extract-text-webpack-plugin@3.0.2@extract-text-webpack-plugin\dist\index.js:176:48
    at Array.forEach (<anonymous>)
    at E:\project\heyushuo-cli\node_modules\_extract-text-webpack-plugin@3.0.2@extract-text-webpack-plugin\dist\index.js:171:18

由报错可以看出是ExtractTextWebpackPlugin 插件的问题,通过查看官网有这样一句话

⚠️ Since webpack v4 the extract-text-webpack-plugin should not be used for css. Use mini-css-extract-plugin instead.
webpack4中不能使用extract-text-webpack-plugin来提取css,需要使用mini-css-extract-plugin插件

cnpm i D mini-css-extract-plugin

修改webpack.prod.conf中的内容如下

// webpack4不支持extrack-text-webpack-plugin 用在css上
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
new MiniCssExtractPlugin({
  filename: utils.assetsPath('css/[name].[contenthash:8].css'),
  chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css')
})

修改build/utils.js中的内用如下

// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
 if (options.extract) {
  //webpack4已经不支持了
  // return ExtractTextPlugin.extract({
  //   use: loaders,
  //   fallback: 'vue-style-loader'
  // })
  return [MiniCssExtractPlugin.loader].concat(loaders)
} else {
  return ['vue-style-loader'].concat(loaders)
}

8. 继续npm run build 报错如下

building for production...Unhandled rejection Error: "dependency" is not a valid chunk sort mode
    at HtmlWebpackPlugin.sortEntryChunks (E:\project\heyushuo-cli\node_modules\_html-webpack-plugin@4.3.0@html-webpack-plugin\index.js:472:11)

通过全局搜索"dependency" 在``

 new HtmlWebpackPlugin({
  filename: process.env.NODE_ENV === 'testing' ?
    'index.html' : config.build.index,
  template: 'index.html',
  inject: true,
  minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: true
    // more options:
    // https://github.com/kangax/html-minifier#options-quick-reference
  },
  // necessary to consistently work with multiple chunks via CommonsChunkPlugin
  chunksSortMode: 'dependency'
}),

通过官网查看 chunksSortMode可使用的值如下,控制插入html的js的顺序的,manual手动排序,将chunks按引入的顺序排序['vender','main']

chunksSortMode:

Allows to control how chunks should be sorted before they are included to the HTML. Allowed values are 'none' | 'auto' | 'manual' | {Function}

9. 继续 npm run build 终于打包成功了.

webpack4新增了mode字段,在开发环境加上mode:'development' 生产环境添加mode: 'production',默认会添加很多默认配置和优化(包括代码分割),具体默认配置可以查看链接,分别在webpack.dev.conf.jswebpack.prod.conf.js文件做修改

const devWebpackConfig = merge(baseWebpackConfig, {
  mode: 'development'
}

在开发环境加上mode:'development'

会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。可以把vue-cli中的这两个插件注释掉

// new webpack.DefinePlugin({
//   'process.env': require('../config/dev.env')
// }),
// new webpack.NamedModulesPlugin(),

开启mode: 'development'相当于开启如下默认配置和优化

module.exports = {
+ mode: 'development'
- devtool: 'eval',
- cache: true,
- performance: {
-   hints: false
- },
- output: {
-   pathinfo: true
- },
- optimization: {
-   namedModules: true,
-   namedChunks: true,
-   nodeEnv: 'development',
-   flagIncludedChunks: false,
-   occurrenceOrder: false,
-   sideEffects: false,
-   usedExports: false,
-   concatenateModules: false,
-   splitChunks: {
-     hidePathInfo: false,
-     minSize: 10000,
-     maxAsyncRequests: Infinity,
-     maxInitialRequests: Infinity,
-   },
-   noEmitOnErrors: false,
-   checkWasmTypes: false,
-   minimize: false,
- },
- plugins: [
-   new webpack.NamedModulesPlugin(),
-   new webpack.NamedChunksPlugin(),
-   new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
- ]
}

开启mode: 'production '相当于开启如下默认配置和优化,可以把vue-cli中相应的地方注释掉

// webpack.production.config.js
module.exports = {
+  mode: 'production',
- performance: {
-   hints: 'warning'
- },
- output: {
-   pathinfo: false
- },
- optimization: {
-   namedModules: false,
-   namedChunks: false,
-   nodeEnv: 'production',
-   flagIncludedChunks: true,
-   occurrenceOrder: true,
-   sideEffects: true,
-   usedExports: true,
-   concatenateModules: true,
-   splitChunks: {
-     hidePathInfo: true,
-     minSize: 30000,
-     maxAsyncRequests: 5,
-     maxInitialRequests: 3,
-   },
-   noEmitOnErrors: true,
-   checkWasmTypes: true,
-   minimize: true,
- },
- plugins: [
-   new TerserPlugin(/* ... */),
-   new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
-   new webpack.optimize.ModuleConcatenationPlugin(),
-   new webpack.NoEmitOnErrorsPlugin()
- ]
}

10. 这个时候在npm run dev的时候还有一个警告如下

- building for production...(node:7012) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
Hash: a38a1834a1cb2ff61367
Version: webpack 4.43.0

犹豫新版本的webpack的hook做了修改,替换了新的api,所以尽量把所有得loader或者plugin都做一个升级
如下是我的项目中的一些loader

cnpm i D css-loader@latest url-loader@latest postcss-loader@latest file-loader@latest vue-style-loader@latest vue-template-compiler@latest

如下是一些项目中用的plugin

cnpm i D optimize-css-assets-webpack-plugin@latest copy-webpack-plugin@latest friendly-errors-webpack-plugin@latest 

都升级一遍后继续 npm run dev ,擦直接报错了如下

plugins: [new VueLoaderPlugin()],

TypeError: VueLoaderPlugin is not a constructor

在Vueloader的官网查到了,点击查看具体

// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
 plugins: [
    // 请确保引入这个插件!
    new VueLoaderPlugin()
  ]

到此终于完成升级了

其实在跟新的时候还会遇到各种问题,需要自己来判断解决

2020/5/11 发现 babel 有 7 版本了,尝试升级一下

"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.5",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.26.0",

官方升级指南升级指南

babel-loader要8版本以上

babel 的核心

"@babel/core"

可以将 es5 转 es6,但是一些新的 api 例如 promise,arr.includes 等不支持

"@babel/preset-env"

需要 polyfill 垫片来解决这个问题

"@babel/polyfill"

我们需要按需引入 polyfill 而不是全部引入

  • @babel/preset-env 提供了一个 useBuiltIns 参数,设置值为 usage 时,就只会包含代码需要的 polyfill 。有一点需要注意:配置此参数的值为 usage ,必须要同时设置 corejs (如果不设置,会给出警告,默认使用的是"corejs": 2) ,注意: 这里仍然需要安装 @babel/polyfill(当前 @babel/polyfill 版本默认会安装 "corejs": 2):
  • 首先说一下使用 core-js@3 的原因,core-js@2 分支中已经不会再添加新特性,新特性都会添加到 core-js@3。例如你使用了 Array.prototype.flat(),如果你使用的是 core-js@2,那么其不包含此新特性。为了可以使用更多的新特性,建议大家使用 core-js@3。
cnpm install --save core-js@3

babel6使用如下几个插件支持 jsx

"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-helper-vue-jsx-merge-props": "^2.0.3",    

babel7替换成了如下插件

@vue/babel-plugin-transform-vue-jsx   

因为使用了@babel/preset-env设置polyfill按需引用了,就不用如下方式了,下边的方式有自己优势,也有自己的缺点

cnpm install --save-dev @babel/plugin-transform-runtime
cnpm install --save @babel/runtime

babel7去掉了stage-x这个功能,如果需要使用在提案中的功能需要自己单独引入.例如如下插件(使用import(),跟好的使用Es6的class)

 @babel/plugin-syntax-dynamic-import
 @babel/plugin-proposal-class-properties
@heyushuo heyushuo changed the title 记录vue-cli项目升级到webpack4一步一步踩坑以及解决 记录vue-cli项目升级到webpack4以及升级到Babel7一步一步踩坑以及解决 Sep 3, 2020
@mytart
Copy link

mytart commented Nov 2, 2020

看你发的记录,吐槽下这些东西就不能智能化一点么。。。感觉把时间和精力都花在这个上面了。

@heyushuo
Copy link
Owner Author

heyushuo commented Nov 4, 2020

看你发的记录,吐槽下这些东西就不能智能化一点么。。。感觉把时间和精力都花在这个上面了。

没办法,老项目打包速度太慢了,升级只能这样一步一步升级

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants