webpack5打包vue2项目文件配置

957 阅读2分钟

分享一些用webpack5打包vue2项目文件配置以及在配置过程中所遇到的坑

webpack配置文件

// webpack.config.js
// 项目生产环境和开发环境合并配置文件
const path = require('path')
const { DefinePlugin } = require('webpack')
const ESLintPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
// css样式压缩
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
// 提取css为单独文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

// 压缩html
const CopyPlugin = require("copy-webpack-plugin")
const TerserPlugin = require("terser-webpack-plugin")

// 判断是开发环境还是生产环境
const isProduction = process.env.NODE_ENV === 'production' //true


const getStyleLoader = (pre) => {
  return [
    isProduction? MiniCssExtractPlugin.loader : 'vue-style-loader',
    'css-loader',
    'postcss-loader',
    pre      
  ].filter(Boolean)
}

// [1, 2, undefined].filter(Boolean) 过滤掉undefined

module.exports = {
  entry: './src/main.js',

  output: {
    path: isProduction? path.resolve(__dirname, '../dist') : undefined,
    filename: isProduction? 'static/js/[name].[contenthash:10].js' : 'static/js/[name].js',
    // 打包异步代码
    chunkFilename: isProduction? 'static/js/[name].[contenthash:10].js' : 'static/js/[name].chunk.js',
    // 图片资源
    assetModuleFilename: 'static/media/[hash:5][ext][query]',
    clean: true
  },

  module: {
    rules: [
      // 处理css、less
      {
        test: /\.css$/,
        use: getStyleLoader()
      },
      {
        test: /\.less$/,
        use: getStyleLoader('less-loader')
      },
      // 处理图片
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        type: "asset",
        parser: {
          dataUrlCondition: {
            // 如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中
            maxSize: 10 * 1024,
          }
        },
        generator: {
          filename: 'static/media/[hash:5][ext][query]'
        }
      },

      // 处理其他资源
      {
        test: /\.(ttf|woff2?)/,
        type: "asset/resource"
      },

      // 处理js
      {
        test: /\.js$/,
        include: path.resolve(__dirname, '../src'),
        loader: 'babel-loader',
        options: {
          // 是否缓存(使第二次打包更快)
          cacheDirectory: true,
          // 是否压缩
          cacheCompression: false
        }
      },

      // 处理vue
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }

    ]
  },

  plugins: [
    // 处理eslint
    new ESLintPlugin({
      context: path.resolve(__dirname, '../src'), // 指定检查的目录
      exclude: 'node_modules', // 指定排除检查的目录
    }),

    // 处理html
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../public/index.html')
    }),

    // 处理vue
    new VueLoaderPlugin(),

    // cross-env定义的环境变量是给打包工具使用
    // DefinePlugin定义的环境变量是给源代码使用, 从而解决v3页面警告问题
    new DefinePlugin({
      _VUE_OPTIONS_API_: true,
      _VUE_PORD_DEVTOOL_: false
    }),
    // // 提取css为单独文件
    isProduction && new MiniCssExtractPlugin({
      filename: 'static/css/[name].[contenthash:10].css',
      chunkFilename: 'static/css/[name].[contenthash:10].chunk.css'
    }),

    isProduction && new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, '../public'),
          to: path.resolve(__dirname, '../dist'),
          globOptions: {
            // 忽略index.html文件
            ignore: ["**/index.html"]
          }
        },
      ],
    })
  ].filter(Boolean),

  // 配置文件解析模块
  resolve: {
    // configuration options
    extensions: ['.vue', '.js', '.json']
  },

  mode: isProduction? 'production' : 'development',
  // 调试模式
  devtool: isProduction? 'source-map' : 'cheap-module-source-map',

  optimization: {
    splitChunks: {
      chunks: 'all'
    },
    // 判断是否需要压缩
    minimize: isProduction,
    minimizer: [
      new CssMinimizerPlugin(),
      new TerserPlugin()
    ]
  },

  devServer: {
    host: 'localhost',
    port: 9000,
    open: true,
    hot: true,
    historyApiFallback: true
  }
}

使用copy-webpack-plugin插件

在使用copy-webpack-plugin插件时,有个配置项globOptions

globOptions: { 
    // 忽略index.html文件 
    ignore: ["**/index.html"] 
 }

此时要注意,在copy时,要保证被copy的源文件目录下(本文是public目录)含有两个及以上文件,因为当index.html文件被忽略时,public就是空目录,会报unable to locate 'C:/Users/xxx/demo/vue-cli/public/**/*' glob错误,文件无法被锁定。

依赖包版本问题

在用webpack5打包vue2项目,依赖包版本的选择也是一个坑,下面是我试了许多次的结果

// vue版本
 "dependencies": {
    "vue": "^2.7.10",
    "vue-router": "^3.6.5"
  }
  
// vue-loader
// 打包vue2项目vue-loader最好使用17版本以下,v3可以使用17版本
"vue-loader": "^15.10.0",
"vue-style-loader": "^4.1.3"
// vue-template-compiler最好和vue版本同步
"vue-template-compiler": "^2.7.13"

favicon.icon图标引入问题

假如你在打包过程中,出现 ERROR in Template execution failed: ReferenceError: BASE_URL is not definedCannot find element: #app错误,不妨排查一下是不是某个文件引入错误。