前言
前面几章已经记录了一些webpack的基础配置,一般我们使用cli的时候,其实cli已经帮我们配置了webpack的一些设置并且隐藏起来了。以vue为例,我们可以手动新建vue.config.js,在里面添加新的配置,一般项目也是这么做。
但是,随着项目的增大,建议根据webpack公共配置,dev配置、prod配置去做文件拆分,这样我们可以根据环境的不同情况去做配置优化。
例如:
- prod环境:webpack配置的重点在于打包后的大小。
- dev环境:webpack配置的重点在于打包速度和热更新体验。
文件结构
首先需要在工程根目录中创建专门的配置文件夹,并在里面建立好对应的配置文件:
webpack-config
- path.js 负责写入常用文件夹路径
- webpack.common.js 负责dev和prod共有的配置
- webpack.dev.js 负责写入dev配置
- webpack.prod.js 负责写入prod配置
以下配置来源与慕课网源码
path.js
const path = require('path')
const srcPath = path.join(__dirname, '..', 'src') // 工程src地址
const distPath = path.join(__dirname, '..', 'dist') // 打包输出路径
module.exports = {
srcPath,
distPath
}
webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath, distPath } = require('./paths')
module.exports = {
entry: path.join(srcPath, 'index'),
module: {
rules: [
{
test: /\.js$/,
loader: ['babel-loader'],
include: srcPath,
exclude: /node_modules/ // 表示不包括
},
// {
// test: /\.vue$/,
// loader: ['vue-loader'],
// include: srcPath
// },
// {
// test: /\.css$/,
// // loader 的执行顺序是:从后往前(知识点)
// loader: ['style-loader', 'css-loader']
// },
{
test: /\.css$/,
// loader 的执行顺序是:从后往前
loader: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.less$/,
// 增加 'less-loader' ,注意顺序
loader: ['style-loader', 'css-loader', 'less-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html'
})
]
}
webpack.dev.js
const path = require('path')
const webpack = require('webpack')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths')
module.exports = smart(webpackCommonConf, {
mode: 'development',
module: {
rules: [
// 直接引入图片 url
{
test: /\.(png|jpg|jpeg|gif)$/,
use: 'file-loader'
}
]
},
plugins: [
new webpack.DefinePlugin({
// window.ENV = 'development'
ENV: JSON.stringify('development')
})
],
devServer: {
port: 8080,
progress: true, // 显示打包的进度条
contentBase: distPath, // 根目录
open: true, // 自动打开浏览器
compress: true, // 启动 gzip 压缩
// 设置代理
proxy: {
// 将本地 /api/xxx 代理到 localhost:3000/api/xxx
'/api': 'http://localhost:3000',
// 将本地 /api2/xxx 代理到 localhost:3000/xxx
'/api2': {
target: 'http://localhost:3000',
pathRewrite: {
'/api2': ''
}
}
}
}
})
merge概念:当把webpack配置文件拆分成好几个文件时,利用它把拆分的文件进行合并。
webpack.prod.js
const path = require('path')
const webpack = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths')
module.exports = smart(webpackCommonConf, {
mode: 'production',
output: {
filename: 'bundle.[contentHash:8].js', // 打包代码时,加上 hash 戳
path: distPath,
// publicPath: 'http://cdn.abc.com' // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
},
module: {
rules: [
// 图片 - 考虑 base64 编码的情况
{
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loader: 'url-loader',
options: {
// 小于 5kb 的图片用 base64 格式产出
// 否则,依然延用 file-loader 的形式,产出 url 格式
limit: 5 * 1024,
// 打包到 img 目录下
outputPath: '/img1/',
// 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源)
// publicPath: 'http://cdn.abc.com'
}
}
},
]
},
plugins: [
new CleanWebpackPlugin(), // 会默认清空 output.path 文件夹,每次打包到dist之前默认先把内部文件清空
new webpack.DefinePlugin({
// window.ENV = 'production'
ENV: JSON.stringify('production')
})
]
})
package.json
最后在package.json记得要修改脚本指令:
"scripts": {
"dev": "webpack-dev-server --config webpack-config/webpack.dev.js",
"build": "webpack --config webpack-config/webpack.prod.js"
}
多入口怎么配置
在公共配置文件中:
entry: {
index: path.join(srcPath, 'index.js'),
other: path.join(srcPath, 'other.js')
},
plugins: [
// new HtmlWebpackPlugin({
// template: path.join(srcPath, 'index.html'),
// filename: 'index.html'
// })
// 多入口 - 生成 index.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html',
// chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
chunks: ['index'] // 只引用 index.js
}),
// 多入口 - 生成 other.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'other.html'),
filename: 'other.html',
chunks: ['other'] // 只引用 other.js
})
]
然后在生产配置中:
output: {
// filename: 'bundle.[contentHash:8].js', // 打包代码时,加上 hash 戳
filename: '[name].[contentHash:8].js', // name 即多入口时 entry 的 key
path: distPath,
// publicPath: 'http://cdn.abc.com' // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
},
5和4的区别
这里直接引用慕课上的总结
5比4在内部效率上有优化,周边插件也有变化。
升级 webpack5 以及周边插件后,代码不一样的调整有:
- package.json 的 dev-server 命令改了
"dev": "webpack serve --config build/webpack.dev.js",
- 升级新版本
const { merge } = require('webpack-merge')
- 升级新版本
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.rules
中loader: ['xxx-loader']
换成use: ['xxx-loader']
filename: 'bundle.[contenthash:8].js'
其中h
小写,不能大写
最后
之后的配置记录都基于这种拆分的形式了。