前提:
webpack5及其对应配套内容
node16.13.2
webpack定制化 基础配置[基础、配置、初运行]
webpack定制化 高级配置[热更新、热打包、别名、调试]
webpack定制化 加载与插件[css加载器、html插件、image打包配置、babel代码兼容、vue加载器及配置]
webpack定制化 优化提速[多进程、压缩、多js打包、多css打包、gzip]
一.开发环境
解释:这里通过4个文件,配置3个环境。原因是3个环境都有共同内容(直接把这个单独写一个文件,其它三个引用),这样写一个三个都能应用,方便管理,但需要安装一个包引入
- 开发环境:使用热加载,需要代码压缩、gzip等优化的配置,大大降低最终项目打包体积,但是速度慢;
- 生产环境:去除代码压缩、gzip、体积分析等优化的配置,大大提高构建速度;生产环境只打包用到的代码,没用到的代码不打包
- 前后端半分离环境:当内容更新后,打包到文件里面,便于后端引入模板
安装:npm i webpack-merge -D #本文版本为5.8.0
配置启动命令:
pageage.json
"scripts": {
"serve": "webpack serve --config webpack.development.js --env ISHOT=true",
"watch": "webpack --watch --config webpack.half-combination.js --env ISHOT=false",
"build": "webpack --config webpack.production.js --env ISHOT=false"
},
1. 共用内容
命名:webpack.config.js
特殊:本文与其它人写的不同在于,引入了环境变量env.ISHOT,处理env需要下面这种函数式写法;里面有三处运用了三目运算符,来避免热更新的BUG
// 注意点,使用webpack-dev-server时,切记一切都要是默认路径,本配置由于不使用其的时候需要其它路径
// 故使用env.ISHOT(来自pageage.json里面serve启动项)来分辨
const path = require('path')// 路径配置
const HtmlWebpackPlugin = require('html-webpack-plugin')// html打包
const MiniCssExtractPlugin = require('mini-css-extract-plugin')// css单独打包到某个位置
const { VueLoaderPlugin } = require('vue-loader')// vue加载器
module.exports = (env) => {
return {
// 入口
entry: {
main: './src/app/main.js',
app: './src/app2/main.js'
},
// 输出
output: {
path: env.ISHOT === 'true' ? path.resolve(__dirname, './dist') : path.resolve(__dirname, './dist/static/js'),
filename: 'ch-[name].[contenthash].js',
// 每次打包前自动清除旧的dist
clean: true,
},
plugins: [
new VueLoaderPlugin(),
// 多页面配置多个该插件,把html与生成的css和js链接导入
new HtmlWebpackPlugin({
template: './public/templates/index.html',
filename: path.resolve(__dirname, './dist/templates/index.html'),
// js文件插入 body里
inject: 'body',
chunks: ['main']// 对应多入口的main对象
}),
new HtmlWebpackPlugin({
template: './public/templates/login.html',
filename: path.resolve(__dirname, './dist/templates/login.html'),
// js文件插入 body里
inject: 'body',
chunks: ['app']// 对应多入口的app对象
}),
// css插件,多个入口导入css只需像下面一样有动态参数即可
new MiniCssExtractPlugin({
filename: '../css/[name].css',// 以webpacke配置的js路径为当前路径
ignoreOrder: true, // 忽视掉打包过程中出现的冲突警告
}),
],
module: {
rules: [
{
test: /\.css$/,
include: [path.resolve(__dirname, './public'),path.resolve(__dirname, './src')],
use: env.ISHOT === 'true' ? [ 'style-loader','css-loader'] : [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.vue$/,
exclude: /node_modules/,
include: path.resolve(__dirname, './src'),
use: 'vue-loader',
},
{
test: /\.(png|jpe?g|gif|svg|webp)$/,
include: path.resolve(__dirname, './public'),
type: 'asset',
generator: {
// 打包到 指定目录 文件下 env.ISHOT来自pageage.json里面serve启动项
filename: env.ISHOT === 'true' ? 'img/[contenthash][ext][query]' : '../img/[contenthash][ext][query]',//name表示文件名字为原名(可以用[contenthash]);ext表示. ;query表示请求资源的后缀(如png) // 以webpacke配置的js路径为当前路径
},
}
]
},
resolve: {
// extensions:['.vue','.js','.json'],//引入这些文件 可以不带后缀 按顺序解析
// 路径别名
alias: {
'@': path.resolve('./public'),
},
},
}
}
2. serve
命名:webpack.development.js
解释:需要箭头函数传递env到webpack.config.js文件里面去,因为在命令里面这最先被调用;由于上面的配置所以这里的base是函数
注意:热加载环境不能使用mini-css-extract-plugin插件,再次提醒,上面配置文件已经用三目运算符解决
// 本配置启动热更新,启动代码格式检查,map文件源码与位置双定位
const { merge } = require('webpack-merge')// 合并配置文件用的
const base = require('./webpack.config.js')// 大家共用的配置文件
const ESLintPlugin = require('eslint-webpack-plugin')// 检测语法格式适配到webpack的插件
const webpack = require('webpack')
module.exports = (env) => merge(base(env), {
mode: 'development',
module: { rules: [] },
plugins: [
// 热替换插件
new webpack.HotModuleReplacementPlugin(),
],
devtool: 'eval-cheap-module-source-map',
devServer: {
host: '127.0.0.1', // 配置启动ip地址
port: 5002, // 配置端口
open: true,
hot: true
// static:'./dist',// 默认打开的是public文件夹,此处可自定
},
})
3. build
命名:webpack.production.js
解释:需要箭头函数传递env到webpack.config.js文件里面去,因为在命令里面这最先被调用;由于上面的配置所以这里的base是函数
// 本配置启动js、css压缩、gzip压缩,以及多入口多文件的分离,相同的引入node_moudules单独的分离
const path = require('path')// 路径设置
const { merge } = require('webpack-merge')// 合并配置文件用的
const base = require('./webpack.config.js')// 大家共用的配置文件
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')// 压缩css
const TerserPlugin = require('terser-webpack-plugin')// 压缩js
const CompressionPlugin = require('compression-webpack-plugin')// 压缩为gzip
module.exports = (env) => merge(base(env), {
mode: 'production',
devtool: 'nosources-source-map',
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, './src'),
use: ['thread-loader', 'babel-loader'],
},
]
},
plugins: [
// gzip压缩
new CompressionPlugin({
algorithm: 'gzip',
exclude: /\.(map|html)$/,
threshold: 10240,// 大于10kb进行压缩
})
],
optimization: {
minimizer: [
new CssMinimizerPlugin(), // 去重压缩css
new TerserPlugin({ // 压缩JS代码
terserOptions: {
compress: {
drop_console: true, // 去除console
},
},
}),
],
// 代码多入口导入相同的分离
splitChunks: {
chunks: 'all', // 可选值:all,async 和 initial。all功能最强大,所以咱们就使用all
minSize: 20000, // 引入的模块大于20kb才做代码分割,官方默认20000,这里不用修改了
// maxSize: 60000, // 若引入的模块大于60kb,则告诉webpack尝试再进行拆分
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 使用正则匹配node_modules中引入的模块
priority: -10, // 优先级值越大优先级越高,默认-10,不用修改
name:'common',
},
},
},
},
})
4. watch
命名:webpack.half-combination.js
解释:需要箭头函数传递env到webpack.config.js文件里面去,因为在命令里面这最先被调用;由于上面的配置所以这里的base是函数
// 本配置启动文件一保存,就以开发状态打包(不压缩速度快)更新内容(与热更新不同,此直接写入到文件)
//,启动代码格式检测以及代码多入口导入,相同的引入node_moudules单独的分离
const { merge } = require('webpack-merge')// 合并配置文件用的
const base = require('./webpack.config.js')// 大家共用的配置文件
const ESLintPlugin = require('eslint-webpack-plugin')// 检测语法格式适配到webpack的插件
module.exports = (env) => merge(base(env), {
mode: 'development',
module: { rules: [] },
plugins: [
new ESLintPlugin({
// 运行的时候自动帮你修复错误
fix: true,
})
],
optimization: {
// 代码多入口导入,相同的分离
splitChunks: {
chunks: 'all', // 可选值:all,async 和 initial。all功能最强大,所以咱们就使用all
minSize: 20000, // 引入的模块大于20kb才做代码分割,官方默认20000,这里不用修改了
// maxSize: 60000, // 若引入的模块大于60kb,则告诉webpack尝试再进行拆分
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 使用正则匹配node_modules中引入的模块
priority: -10, // 优先级值越大优先级越高,默认-10,不用修改
name: 'common',
},
},
},
},
})
结语:请把本系列都看完再投入开发环境,优化配置很重要