vue-element-admin升级到webpack5

352 阅读3分钟

升级原因

  1. 基于App端webpack5升级经验,webpack5性能很好

  2. vue-cli在webpack的基础上包了一层,遇到过一些bug, 而且构建配置的可定制性没有webpack5。相当鸡肋

  3. webpack使用更广泛

本地服务升级步骤

  1. 删除package.json中vue-cli相关的npm包
  2. 添加webpack相关npm包
npm i -D webpack webpack-cli webpack-bundle-analyzer webpack-dev-server
  1. 添加@babel相关npm包, 需要babel-loader。并删除其他旧的babel npm包
npm i -D @babel/core @babel/eslint-parser @babel/preset-env babel-loader
  1. package.json中添加start命令 "dev": "webpack serve --config build/webpack.dev.conf.js",
  2. 删除vue-config.js,删除build/index.js,添加build/webpack.dev.conf.js。根据webpack开发环境基本常识,代三如下
const chalk = require('chalk')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const EslintWebpackPlugin = require('eslint-webpack-plugin')

const { VueLoaderPlugin } = require('vue-loader')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  mode: 'development',
  stats: 'minimal',
  entry: resolve('src/main.js'), // js入口
  output: {
    filename: '[name].js',
    publicPath: '/'
  },
  cache: {
    type: 'filesystem' // 开启webpack硬盘缓存
  },
  devtool: 'eval-source-map',
  devServer: {
    hot: true,
    static: {},
    port: 8888,
    host: 'localhost'
  },
  resolve: {
    extensions: ['.js', '.vue'],
    alias: {
      '@': resolve('src'),
      utils: resolve('src/utils'),
      '@assets': resolve('src/assets')
    }
  },
  module: {
    rules: [
      {
        test: /.vue$/,
        exclude: /node_modules/,
        include: resolve('src'),
        loader: 'vue-loader'
      },
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        include: resolve('src'),
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env']
            }
          }
        ]
      },
      {
        test: /.(png|jpg|jpeg|gif|svg)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name].[hash:8][ext]'
        }
      },
      {
        test: /.scss$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              sourceMap: false
            }
          }
        ]
      },
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [
    new EslintWebpackPlugin({
      context: path.resolve(__dirname, '../src'),
      exclude: 'node_modules',
      extensions: ['vue', 'js'],
      cache: true
    }),
    new HtmlWebpackPlugin({
      template: 'public/index.html', // html模板
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      }
    }),
    new VueLoaderPlugin()
  ]
}
  1. 运行npm run dev, 开始解决一堆报错
  2. tui-editor npm包由于npm register的原因装不上,删除相关页面及代码
  3. babel-config.js 需要支持jsx语法
module.exports = {
  presets: [
    '@vue/babel-preset-jsx',
    [
      '@babel/preset-env',
      {
        useBuiltIns: 'entry',
        corejs: '3.9.1'
      }
    ]
  ]
}
  1. .eslintrc.js 要使用@babel/eslint-parser, 并添加rules忽略
module.exports = {
  root: true,
  parserOptions: {
    parser: '@babel/eslint-parser',
    sourceType: 'module',
    ecmaVersion: 6,
    // 如果有需要,可以启用特定的语言特性支持
    ecmaFeatures: {
      jsx: true, // 如果你的项目包含 JSX
      impliedStrict: false, // 启用严格模式('use strict')
      globalReturn: false, // 是否允许在全局作用域下返回值
    },
  },
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  extends: ['plugin:vue/essential', 'eslint:recommended'],
  plugins: ['vue'],
  rules: {
    "vue/no-mutating-props": "off",
    "vue/max-attributes-per-line": "off",
    "vue/name-property-casing": "off",
    "vue/multi-word-component-names": "off",
   //  ...
  1. 解决“can't resolve 'path'...”。原因是:webpack v5版本移除了node内置模块的自动引入,页面有使用到相关模块需要在resolve.fallback中引入并安装依赖
  resolve: {
    extensions: ['.js', '.vue'],
    alias: {
      '@': resolve('src'),
      utils: resolve('src/utils'),
      '@assets': resolve('src/assets')
    },
    fallback: {
      path: require.resolve('path-browserify'),
      stream: require.resolve("stream-browserify"),
      "buffer": require.resolve("buffer/")
    }
  }
  1. "vnodes.push(<i class={[icon, 'sub-el-icon']} />)", 不支持jsx语法。

    1. script需要声明lang="jsx"
        <script lang="jsx">
        ```
    1.  添加`@vue/babel-preset-jsx`
    
    
  2. public/index.html中webpack命令报错,直接移除变量。简单处理了

  3. scss导出变量在js中使用, 也需要相关npm包支持,写死颜色,简单处理了。

至此本地服务启动了

image.png

生产构建升级步骤

  1. 添加build/webpack.prod.conf.js
module.exports = {
  mode: 'production',
  stats: 'minimal',
  entry: resolve('src/main.js'),
  output: {
    clean: true,
    filename: 'static/js/[name].[contenthash:8].js',
    path: path.join(__dirname,'../dist/'),
  },
  1. package.json中添加build命令
"build": "webpack --config build/webpack.prod.conf.js",

升级效果

此处用我另一个项目升级数据。vue-element-admin和tui-editor装不了

指标vue-cli4webpack5升级后
本地启动速度首次80秒,二次30秒首次64秒,二次5秒
本地热更新速度5秒3秒
生产构建速度106秒68秒
生产构建包大小6.8M8.2M

总结

  1. vue-cli4升级到webpack5效果并不明显,启动和构建速度差不多,甚至生产构建包大涉还大了。可能的解释:

    1. webpack5升级后,我没有splitChunks处理
    2. vue-cli4构建有缓存处理,可能类似于webpack5的缓存

项目地址:github.com/jovenwang12…