从0到1:webpack5 搭建 Vue3 项目——生产环境
可以从 GitHub 获取本文所对应的代码
分离不同环境的配置文件
上篇文章中所讲的都是在开发环境下的配置,当我们开发完成打包上线时,有些配置并不合适,需要进行修改。 为方便起见,我们创建两个配置文件来对应这两种环境,在开发和打包时,分别使用各自的配置文件。
将上篇文章中我们创建的 webpack.config.json
文件,改名为 webpack.config.dev.js
,再创建一个用于生产环境的配置文件 webpack.config.prod.js
。
我们先将 dev 中的所有内容直接复制一份到 prod 中,接下来我们继续对它进修修改和添加新的内容。
生产环境配置
1、修改和删除不相关的配置
首先将 mode
字段修改为 production
,然后删除 devServer
相关的设置。
2、抽取 css 文件
在开发时,我们将样式直接以 style
标签的形式添加进页面中,在打包时,如果样式也被打进 js 文件中,会导致 js 文件太大,所以我们将 css 样式单独抽取出来,放入对应的 css 文件中。
首先安装 mini-css-extract-plugin
插件
npm install --save-dev mini-css-extract-plugin
配置插件,这个插件需要配置的地方有两个:
一个是在 module.rules
中,用 MiniCssExtractPlugin.loader
替换原来的 style-loader
;
另一个是在 plugins
中,添加这个插件。
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 提取 css 文件
const config = {
module: {
rules: [
// 处理 css 文件
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
},
// 处理 scss 文件
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']
},
]
},
plugins: [
// 抽取 css 文件
new MiniCssExtractPlugin({
filename: `css/[name]_[contenthash:8].css`, // 指定 css 文件的名称
})
]
};
做完上面的配置,我们需要在 package.json
文件中,增加一个打包的脚本:
"scripts": {
"dev": "webpack-dev-server --config webpack.config.dev.js",
"build": "webpack --config webpack.config.prod.js"
},
执行 npm run build
,就会在根目录下生成一个 dist
文件夹,此时 js 和 css 文件已经被分到不同的文件夹里面了。
3、安装 clean-webpack-plugin
打包之后的文件都存放在 dist
文件夹下,如果我们修改过代码之后,再次打包时,新生成的文件也在这个文件夹下,而那些旧文件已经没有用了,如果每次手动删除又比较费事,所以我们添加一个 clean-webpack-plugin
插件,在每次打包时,自动删除旧的打包文件。
npm install --save-dev clean-webpack-plugin
配置:
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 删除旧的打包文件
const config = {
plugins: [
// 打包时删除旧文件
new CleanWebpackPlugin(),
]
};
以上这些配置已经可以正常打包了,但是 webpack.config.prod.js
与 webpack.config.dev.js
里面有些配置是公共的,两份文件里面都写一遍有些重复,下面我们抽取一个配置文件。
抽取配置文件
在根目录下创建一个 config
文件夹,并将原来的两个配置文件移动到这里,同时再创建一个 webpack.config.base.js
,注意修改 package.json
文件中脚本里的配置文件的路径。
接下来,我们把 dev 和 prod 中的公共部分移动到 webpack.config.base.js
文件中,这里因为文件位置变了,配置里面所写的一些路径也需要做修改:
const path = require('path');
const { resolve } = path;
const { VueLoaderPlugin } = require('vue-loader');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 用于生成 html 文件
const config = {
entry: {
main: resolve(__dirname, '../src/main.js')
},
output: {
path: resolve(__dirname, '../dist'), // 打包后的文件输出的目录
filename: `js/[name]_[chunkhash:8].js` // 设置打包后的 js 文件名,如果在文件名前增加文件路径,会将打包后的 js 文件放在指定的文件夹下
},
module: {
rules: [
// 它会应用到普通的 `.js` 文件
// 以及 `.vue` 文件中的 `<script>` 块
{
test: /\.js$/,
use: ['babel-loader'],
exclude: [
/node_modules/,
// \\ for Windows, / for macOS and Linux
/node_modules[\\/]core-js/
]
},
// 处理 .vue 文件
{
test: /\.vue$/,
loader: 'vue-loader'
},
// 使用 webpack 内置的资源模块,对图片资源的处理
{
test: /\.(jpg|png|gif|jpeg)$/,
type: 'asset',
generator: {
// 设置图片被处理之后的名称,可以通过在名字前面加路径,将图片都放置在一个文件夹下
// 注意这里的 [ext],它已经包含了 . ,所以不能再在[has:8] 和 [ext] 之间加上点了
filename: 'img/[name]_[hash:8][ext][query]'
},
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 // 4kb,设置阈值,小于这个大小的,会被处理成 base 64 的字符串,默认是8kb
}
}
},
// 参考上面图片的处理方式,可以设置其它资源的处理方式
// 视频、音频等
{
test: /\.(mp3|mp4|mov)$/,
type: 'asset',
generator: {
filename: 'media/[name]_[hash:8][ext][query]'
},
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 // 4kb,设置阈值,小于这个大小的,会被处理成 base 64 的字符串,默认是8kb
}
}
}
]
},
plugins: [
// 请确保引入这个插件!
new VueLoaderPlugin(),
// 生成 html 文件
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../index.html'), // 以根目录下的 index.html 文件为模板,生成项目的入口文件
filename: 'index.html', // 生成的入口文件名
chunks: ['main'],
inject: true,
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
})
]
};
module.exports = config;
然后在 dev 和 prod 的文件中,将 base 的内容引入,再使用 插件,将本文件中的配置与 base 中的配置合并,得到最终的配置。 这样我们在 dev 和 prod 中,就只需要配置各自环境所需要的配置项了。
webpack-merge
在这里我们需要使用到 webpack-merge
,可以很好的将我们的配置进行合并,想要了解更多的用法,可直接在 GitHub 上查看。
以下为调整后的 dev 和 prod 文件
webpack.config.dev.js
// const path = require('path');
// const { resolve } = path;
// const { VueLoaderPlugin } = require('vue-loader');
// const HtmlWebpackPlugin = require('html-webpack-plugin'); // 用于生成 html 文件
const { merge } = require('webpack-merge'); // 用于合并配置
// 合并配置
const baseWebpackConfig = require('./webpack.config.base.js');
const devWebpackConfig = merge(baseWebpackConfig, {
mode: 'development',
devServer: {
hot: true, // 开启热更新
open: false, // 编译之后自动打开网页
port: 9000 // 指定端口
},
module: {
rules: [
// 处理 css 文件
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
// 处理 scss 文件
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
}
]
}
});
module.exports = devWebpackConfig;
webpack.config.prod.js
const { merge } = require('webpack-merge'); // 用于合并配置
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 提取 css 文件
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 删除旧的打包文件
// 合并配置
const baseWebpackConfig = require('./webpack.config.base.js');
const prodWebpackConfig = merge(baseWebpackConfig, {
mode: 'production',
module: {
rules: [
// 处理 css 文件
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
},
// 处理 scss 文件
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']
},
]
},
plugins: [
// 打包时删除旧文件
new CleanWebpackPlugin(),
// 抽取 css 文件
new MiniCssExtractPlugin({
filename: `css/[name]_[contenthash:8].css` // 指定 css 文件的名称
})
],
optimization: {
splitChunks: {
chunks: 'all'
}
}
});
console.log('prodWebpackConfig --- ', prodWebpackConfig);
module.exports = prodWebpackConfig;
至此,生产环境的相关配置就完成了,下一篇我将给大家分享一些自己在工作和学习中用到的一些打包优化。
转载自:https://juejin.cn/post/7129892133942607902