从基于webpack4的vue-cli@4升级到原生webpack5过程

4,817 阅读3分钟

背景


我们项目准备做成微前端项目或者组件库给别的项目组使用,目前国内比较成熟的方案主要有:

  1. 基于single-spa的qiankun框架[qiankun.umijs.org/zh/guide]
  2. 基于Webpack5 Module Federation的emp框架[github.com/efoxTeam/em…]
  3. 开发自己的组件库,类似于ElementUI

为了便于以后扩展,最终还是选择把vue-cli改成webpack5(没事找事)

主要提供两种思路,一种使用官方提供的方法从vue-cli4升级打vue-cli5,另一种是自己搭建一个新的webpack5

升级步骤

1. 搭建webapck5(强烈推荐)

输出 vue.config.js 配置,能看到vue-cli最终生成的配置在output.js

vue inspect > output.js

创建一个webpack项目

mkdir your-project
cd your-project
npm init -y
npm install webpack webpack-cli --save-dev

然后可以把output.js的配置都拷贝过去,以下主要说一下output.js没有涵盖到的内容:

  1. webpack5使用资源模块来代替raw-loader、url-loader、file-loader       webpack5之前代码:
rules: [
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    loader: 'url-loader',
        options: {
            limit: 10000,
            name: 'static/img/[hash][ext][query]'
        } 
    }
]

      webpack5代码:

rules: [
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    type: 'asset',
    generator: {
        filename: 'static/img/[hash][ext][query]'
    },
    parser: {
        dataUrlCondition: {
            maxSize: 10000
        }
    }
]
  1. output.js没有打印出来devServer的配置,需要自己手动添加一下       vue.config.js里面的配置:
const port = process.env.port || process.env.npm_config_port || 9528;

module.exports = {
    ……
    devServer: {
    port,
    overlay: {
        errors: true,
        warnings: false
    }

},
    ……
}

      webpack5中devServer的配置

const port = process.env.port || process.env.npm_config_port || 9528;

module.exports = {
    ……
    devServer: {
    port,
+   client: {
        overlay: {
            errors: true,
            warnings: false
+       }

    }

},
    ……
}
  1. output.js没有对环境进行区分,所以我们自己可以设置不同环境间的配置:       开始进行配置拆分
your-project
  |- package.json
  |- package-lock.json
- |- webpack.config.js
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
  |- /dist
  |- /node_modules

      可以通过在命令行中使用 --config 标志修改,在package.json:

"main": "src/index.js",
    "scripts": {
-     "start": "webpack serve --open",
+     "start": "webpack serve --open --config webpack.dev.js",
-     "build": "webpack"
+     "build": "webpack --config webpack.prod.js"
    },
    "keywords": [],

      在webpack.prod.js和webpack.dev.js分别都合并webpack.common.js代码

 const { merge } = require('webpack-merge');
 const common = require('./webpack.common.js');

 module.exports = merge(common, {
   ……
 });
  1. webpack 命令行的 --env 参数需要将 module.exports 转换成一个函数:       例如在package.json:
    "scripts": {
        "start": "webpack serve --env VUE_APP_API_MODE=dev --config webpack.dev.js",
        "dev": "npm run start",
        "build:dev": "webpack build --env VUE_APP_API_MODE=dev --config webpack.prod.js",
    }

      则 webpack.dev.js/webpack.prod.js 需要使用函数 注:webpack5自带DefinePlugin

module.exports = (env) => {
  const VUE_APP_API_MODE = env.VUE_APP_API_MODE;

  return {
    ……
    plugins: [
        new webpack.DefinePlugin({
            "process.env": {
                VUE_APP_API_MODE: JSON.stringify(VUE_APP_API_MODE)
            }
        })
    ]
  };
};

1. 升级vue-cli

查看vue-cli版本

vue -V 

低于5.0则先卸载

npm uninstall vue-cli -g
# OR
yarn global remove vue-cli

再安装

npm install -g @vue/cli
# OR
yarn global add @vue/cli

进入到项目升级vue-cli

cd your-project

vue upgrade --next

2.webpack5迁移指南(vue-cli5和webpack5都适用)


  1. 不再为 Node.js 模块 自动引用 Polyfills,如(process、Buffer等),解决方法如下:
  • 引入包(以下是 webpack 在 webpack 5 之前使用过的 polyfill 包列表)
module.exports = {
    resolve: {
        assert: require.resolve('assert'),
        buffer: require.resolve('buffer'),
        console: require.resolve('console-browserify'),
        constants: require.resolve('constants-browserify'),
        crypto: require.resolve('crypto-browserify'),
        domain: require.resolve('domain-browser'),
        events: require.resolve('events'),
        http: require.resolve('stream-http'),
        https: require.resolve('https-browserify'),
        os: require.resolve('os-browserify/browser'),
        path: require.resolve('path-browserify'),
        punycode: require.resolve('punycode'),
        process: require.resolve('process/browser'),
        querystring: require.resolve('querystring-es3'),
        stream: require.resolve('stream-browserify'),
        string_decoder: require.resolve('string_decoder'),
        sys: require.resolve('util'),
        timers: require.resolve('timers-browserify'),
        tty: require.resolve('tty-browserify'),
        url: require.resolve('url'),
        util: require.resolve('util'),
        vm: require.resolve('vm-browserify'),
        zlib: require.resolve('browserify-zlib')
    }
}
  • 忽略包(二选一)
fallback: {
    assert: false
    ……
},
  • 新规范中将不再支持下面这种方式,如此做会发出警告:
import { version } from './package.json';
console.log(version);

// 请使用如下方式代替:
import pkg from './package.json';
console.log(pkg.version);

总结


    当初,我在打算升级webpack5(主要是为了调研Webpack5 Module Federation)的时候,一开始就是打算直接升级vue-cli完成的,然而我当时搭建的时候官方只有公测版,会出现各种不可预期的bug(官方更新带有比较严重的滞后性),为了能保证项目以后能快速适应各种变化,还是建议大家自己搭一套出来(当然,脚手架是一个很好的东西这点不可置疑)