拆分开发环境和生产环境
目前我们都是手动修改 mode 配置来切换开发环境和生产环境,但是很多配置在生产环境和开发环境是不一样的,比如开发环境没有必要设置缓存,生产环境需要设置公共路径等。
公共路径
publicPath 配置选项在各个场景中都非常有用,你可以通过他来指定应用程序中所有资源的基础路径。
准备
我们打开 dist/app.html 看下我们的资源引用,发现都是通过相对路径去引用的。那么如果我们想将静态资源托管到 CDN 上在生产环境中使用呢?
配置
output: { // 出口文件
publicPath: 'http://localhost:8080/' // 这里可以写我们的前端域名或者CDN服务期的域名等
},
效果
运行 npx webpack 再次查看 dist/app.html 看下我们的资源引用,已经变成了我们的前端域名:
环境变量
环境变量可以帮助我们消除 开发环境 和 生成环境 之间的差异。
配置
webpack 命令行 环境配置的 —env 参数,可以允许我们传入任意数量的环境变量,并且在 webpack.config.js 中可以访问到,例如:npx webpack --env production
我们改造一下我们的配置:
module.exports = (env) =>{
console.log(env)
return {
entry: './src/index.js', // 配置 index.js 打包入口
mode: 'development', // 设置模式 'none' | 'development' | 'production'
output: { // 出口文件
filename: '[name].[contenthash].js', // 出口文件名
path: path.resolve(__dirname, './dist'), // 出口文件路径
clean: true, // 生成新文件的同时是否删除旧文件
publicPath: 'http://localhost:8080/'
},
optimization: {
minimizer: [
new CssMinizerPlugin()
],
moduleIds: 'deterministic',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
},
}
}
}
}
运行一下npx webpack --env production
我们看到打印出了如下内容:
这样我们就可以根据 production 来进行配置了,如下:
mode: env.production ? 'production' : 'development',
这样我们就可以根据用户传来的参数来判断是开发环境还是生产环境了
注意;
如果设置了 env 变量却没有赋值,默认将 env.production 设置为 true
代码压缩
我们发现打包好的 js 文件并没有进行压缩,为什么 webpack 开箱即用的 terser 没有生效呢?因为我们配置了一个 new CssMinizerPlugin(),所以这里想要让 terser 生效我们要配置一下
optimization: {
minimizer: [
new CssMinizerPlugin()
],
}
安装
npm install terser-webpack-plugin -D
配置
const TerserPlugin = require('terser-webpack-plugin') // 引入 terser-webpack-plugin 插件
optimization: {
minimizer: [
new CssMinizerPlugin(),
new TerserPlugin()
],
}
效果
运行 npx webpack —env production,再次查看打包好的js文件发现全都已经压缩好了
注意
只有在 production 环境下代码才会进行压缩,在 development 下是不会压缩的,这就是配置环境变量的意义
拆分配置文件
思考
如果我们将所有 开发环境 和 生产环境 的区别都在 webpack.config.js 中进行配置显然是很糟糕的,所以我们需要将他们拆分出来。
配置开发环境
新建 config 文件夹,并在下面新建一个 webpack.config.dev.js 文件,将 webpack.config.js 文件copy过来,进行改造,如下:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入 html-webpack-plugin 插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 引入 mini-css-extract-plugin 插件
module.exports = {
entry: {
index: './src/index.js', // 配置 index.js 打包入口
another: './src/another.js', // 配置 another.js 打包入口
}, // 入口文件路径
output: { // 出口文件
filename: './script/[name].js', // 出口文件名
path: path.resolve(__dirname, './dist'), // 出口文件路径
clean: true, // 生成新文件的同时是否删除旧文件
},
mode: 'development', // 设置模式 'none' | 'development' | 'production'
devtool: 'inline-source-map',
devServer: {
static: '../dist' // 路径
},
plugins: [
new HtmlWebpackPlugin({ // 实例化 HtmlWebpackPlugin,它将帮我们生成一个 dist/index.html 文件
template: './index.html', // 指定模板
filename: 'app.html', // 生成的文件名
inject: 'body' // script标签的生成位置
}),
new MiniCssExtractPlugin({
filename: 'styles/[contenthash].css'
})
],
module: {
rules: [ // 配置资源模块
{
test: /\.css$/, // 利用正则匹配以 .css 结尾的文件
use: [MiniCssExtractPlugin.loader, 'css-loader'] // 使用的 loader
},
{
test: /\.js$/, // 匹配 js 文件
exclude: /node_modules/, // 去除编译 node_modules 包
use: {
loader: 'babel-loader', // 使用 loader
options: {
presets: ['@babel/preset-env'], // 添加预设
plugins: [
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
optimization: {
moduleIds: 'deterministic',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
},
}
}
}
效果
打开控制台运行 npx webpack -c ./config/webpack.config.dev.js 打包,发现打包好的文件如预期没有压缩
注意
我们的输出文件路径要改为 ../dist 否则会打包到 config 文件夹下。
配置生产环境
我们在 config 文件夹下面新建一个 webpack.config.prod.js 文件,将 webpack.config.js 文件copy过来,进行改造,如下:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入 html-webpack-plugin 插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 引入 mini-css-extract-plugin 插件
const CssMinizerPlugin = require('css-minimizer-webpack-plugin'); // 引入 css-minimizer-webpack-plugin 插件
const TerserPlugin = require('terser-webpack-plugin') // 引入 terser-webpack-plugin 插件
module.exports = {
entry: {
index: './src/index.js', // 配置 index.js 打包入口
another: './src/another.js', // 配置 another.js 打包入口
}, // 入口文件路径
output: { // 出口文件
filename: './script/[name].[contenthash].js', // 出口文件名
path: path.resolve(__dirname, '../dist'), // 出口文件路径
clean: true, // 生成新文件的同时是否删除旧文件
publicPath: 'http://localhost:8080/'
},
mode: 'production', // 设置模式 'none' | 'development' | 'production'
plugins: [
new HtmlWebpackPlugin({ // 实例化 HtmlWebpackPlugin,它将帮我们生成一个 dist/index.html 文件
template: './index.html', // 指定模板
filename: 'app.html', // 生成的文件名
inject: 'body' // script标签的生成位置
}),
new MiniCssExtractPlugin({
filename: 'styles/[contenthash].css'
})
],
module: {
rules: [ // 配置资源模块
{
test: /\.css$/, // 利用正则匹配以 .css 结尾的文件
use: [MiniCssExtractPlugin.loader, 'css-loader'] // 使用的 loader
},
{
test: /\.js$/, // 匹配 js 文件
exclude: /node_modules/, // 去除编译 node_modules 包
use: {
loader: 'babel-loader', // 使用 loader
options: {
presets: ['@babel/preset-env'], // 添加预设
plugins: [
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
optimization: {
minimizer: [
new CssMinizerPlugin(),
new TerserPlugin()
],
moduleIds: 'deterministic',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
},
}
}
}
效果
打开控制台运行 npx webpack -c ./config/webpack.config.prod.js 打包,发现打包好的文件如预期进行了压缩
注意
我们的输出文件路径要改为 ../dist 否则会打包到 config 文件夹下。