1、环境变量
想要消除 webpack.config.js 在 开发环境 和 生产环境 之间的差异,你可能需要 环境变量(environment variable)。
webpack 命令行 环境配置 的 --env 参数,可以允许你传入任意数量的环境变量。而 在 webpack.config.js 中可以访问到这些环境变量。例如, --env production 或 --env goal=local
webpack.config.js输出env为
{ production : true, goal : local }
npx webpack --env production --progress --env goal=local
对于我们的 webpack 配置,有一个必须要修改之处。通常, module.exports指向 配置对象。要使用 env 变量,你必须将 module.exports 转换成一个函数:
运行时输入 npx webpack --env production 则为生产环境
//...module.exports = (env) => {return {//...// 根据命令行参数 env 来设置不同环境的 modemode: env.production ? 'production' : 'development',//...}}
2、公共路径 publicPath
在 开发环境中,我们通常有一个 assets/ 文件夹,它与索引页面位于同一级别。这没太大问题,但是,如果我们将所有静态资源托管至 CDN,然后想在生 产环境中使用呢? 想要解决这个问题,可以直接使用一个 environment variable(环境变量)。
npx webpack --env ASSET_PATH=http://localhost:8080/
import webpack from 'webpack';// 尝试使用环境变量,否则使用根路径const ASSET_PATH = process.env.ASSET_PATH || '/';export default {output: {// 比如index.html中引入的 'build.js'会变成 'http://localhost:8080/build.js'//publicPath: 'http://localhost:8080/',publicPath: ASSET_PATH,},plugins: [// 这可以帮助我们在代码中安全地使用环境变量new webpack.DefinePlugin({'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH),}),],};
有可能你事先不知道 publicPath是什么,webpack 会自动根据 import.meta.url 、 document.currentScript、 script.src 或者 self.location变量设置 publicPath。你需要做的是将 output.publicPath 设为'auto':
module.exports = {output: {publicPath: 'auto',},};
3、拆分配置文件
目前,生产环境和开发环境使用的是一个配置文件,我们需要将这两个文件单独放到 不同的配置文件中。如 webpack.config.dev.js (开发环境配置)和 webpack.config.prod.js (生产环境配置)。在项目根目录下创建一个配置文件 夹 config 来存放他们。
具体的拆分内容看第5点提取 **公共配置**
拆分成两个配置文件后,分别运行这两个文件: -c 是 --config 的缩写
开发环境: npx webpack serve -c ./config/webpack.config.dev.js生产环境: npx webpack -c ./config/webpack.config.prod.js
由于放到cinfig文件下,输出时将./dist改为../dist
output: {...path: path.resolve(__dirname, '../dist'),...},
4、npm脚本
每次打包或启动服务时,都需要在命令行里输入一长串的命令 配置 npm 脚本来简化命令行的输入
分成了两个config文件 执行不同命令时找到对应文件
{"scripts": {"start": "npx webpack serve -c ./config/webpack.config.dev.js","build": "npx webpack -c ./config/webpack.config.prod.js"}}
运行 : npm run start &npm run build
5、提取公共配置
这时,我们发现这两个配置文件里存在大量的重复代码,可以手动的将这些重复的代 码单独提取到一个文件里, 创建 webpack.config.common.js ,配置公共的内容:
webpack.config.common.js
const path = require('path')const HtmlWebpackPlugin = require('html-webpack-plugin')const MiniCssExtractPlugin = require('mini-css-extract-plugin')const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')const TerserPlugin = require('terser-webpack-plugin')module.exports = {entry: {index: './src/index.js',another: './src/another-module.js'},output: {//注意这个dist的路径设置成上一级path: path.resolve(__dirname, '../dist'),clean: true,assetModuleFilename: 'images/[contenthash][ext]'},plugins: [new HtmlWebpackPlugin({template: './index.html',filename: 'app.html',inject: 'body'}),new MiniCssExtractPlugin({filename: 'styles/[contenthash].css'})],module: {rules: [{test: /\.png$/,type: 'asset/resource',generator: {filename: 'images/[contenthash][ext]'}},{test: /\.jpg$/,type: 'asset',parser: {dataUrlCondition: {maxSize: 4 * 1024 * 1024}}},{test: /\.(css|less)$/,use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']},{test: /\.js$/,exclude: /node_modules/,use: {loader: 'babel-loader',options: {presets: ['@babel/preset-env'],plugins: [['@babel/plugin-transform-runtime']]}}}]},optimization: {splitChunks: {cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/,name: 'vendors',chunks: 'all'}}}}}
webpack.config.dev.js 开发环境配置文件
module.exports = {
output: {
filename: 'scripts/[name].js'
},
mode: 'development',
devtool: 'inline-source-map',
devServer: {
static: './dist'
}
}
webpack.config.prod.js 生产环境配置文件
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
output: {
filename: 'scripts/[name].[contenthash].js',
publicPath: 'http://localhost:8080/'
},
mode: 'production',
optimization: {
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin()
]
},
performance: {
hints: false
}
}
6、合并配置文件
拆分好后,新的问题来了,如何保证配置合并没用问题呢?webpack-merge 这个工具可以完美解决这个问题。 npm install webpack-merge -D
webpack.config.js 总的配置文件
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.config.common')
const productionConfig = require('./webpack.config.prod')
const developmentConfig = require('./webpack.config.dev')
module.exports = (env) => {
switch(true) {
case env.development:
return merge(commonConfig, developmentConfig)
case env.production:
return merge(commonConfig, productionConfig)
defult:
return new Error('No matching configuration was found')
}
}
package.json 配置对应的env来merge对应环境下的json文件
"scripts": {
"start": "npx webpack serve -c ./config/webpack.config.js --env development",
"build": "npx webpack -c ./config/webpack.config.js --env production",
},
