Webpack 基础教程
- [1. 基础概念](#1. 基础概念)
-
- [1.1 核心概念](#1.1 核心概念)
- [2. 开发环境配置](#2. 开发环境配置)
-
- [2.1 打包资源(样式,html,图片,其他)](#2.1 打包资源(样式,html,图片,其他))
-
- [2.1.1 样式处理](#2.1.1 样式处理)
- [2.1.2 HTML处理](#2.1.2 HTML处理)
- [2.1.3 图片处理](#2.1.3 图片处理)
- [2.1.4 其他资源处理](#2.1.4 其他资源处理)
- [2.2 devServer](#2.2 devServer)
-
- [2.2.1 Webpack5 重要更新](#2.2.1 Webpack5 重要更新)
- [2.2.2 旧版配置](#2.2.2 旧版配置)
- [2.3 CSS处理](#2.3 CSS处理)
-
- [2.3.1 处理成单独文件](#2.3.1 处理成单独文件)
- [2.3.2 CSS兼容性处理](#2.3.2 CSS兼容性处理)
- [2.3.3 压缩CSS](#2.3.3 压缩CSS)
- [2.4 ESLint](#2.4 ESLint)
- [2.5 JS兼容性处理](#2.5 JS兼容性处理)
- [2.6 压缩HTML和JS代码](#2.6 压缩HTML和JS代码)
- [3. 生产环境配置](#3. 生产环境配置)
-
- [3.1 性能优化](#3.1 性能优化)
- [3.2 HMR(热模块替换)](#3.2 HMR(热模块替换))
-
- [3.2.1 开启热更新](#3.2.1 开启热更新)
- [3.2.2 不同文件类型的HMR支持](#3.2.2 不同文件类型的HMR支持)
- [3.3 source-map](#3.3 source-map)
-
- [3.3.1 属性说明](#3.3.1 属性说明)
- [3.3.2 各类型区别](#3.3.2 各类型区别)
- [3.3.3 内联和外部区别](#3.3.3 内联和外部区别)
- [3.3.4 选择建议](#3.3.4 选择建议)
- [3.4 OneOf](#3.4 OneOf)
- [3.5 缓存](#3.5 缓存)
-
- [3.5.1 Babel缓存](#3.5.1 Babel缓存)
- [3.5.2 文件资源缓存](#3.5.2 文件资源缓存)
- [3.5.3 文件资源缓存hash值说明](#3.5.3 文件资源缓存hash值说明)
- [3.6 tree shaking](#3.6 tree shaking)
- [3.7 code split](#3.7 code split)
-
- [3.7.1 单入口和多入口](#3.7.1 单入口和多入口)
- [3.7.2 依赖单独打包](#3.7.2 依赖单独打包)
- [3.7.3 通过js代码将某个文件单独打包成一个chunk](#3.7.3 通过js代码将某个文件单独打包成一个chunk)
- [3.8 懒加载和预加载](#3.8 懒加载和预加载)
- [3.9 PWA](#3.9 PWA)
-
- [3.9.1 注册serviceworker](#3.9.1 注册serviceworker)
- [3.9.2 注意事项](#3.9.2 注意事项)
- [3.10 多进程打包](#3.10 多进程打包)
-
- [3.10.1 设置多线程打包数量](#3.10.1 设置多线程打包数量)
- [3.11 externals](#3.11 externals)
-
- [3.11.1 函数形式](#3.11.1 函数形式)
- [3.12 dll](#3.12 dll)
-
- [3.12.1 webpack.dll.js配置](#3.12.1 webpack.dll.js配置)
- [3.12.2 webpack.config.js中使用](#3.12.2 webpack.config.js中使用)
- [4. 优化环境配置](#4. 优化环境配置)
-
- [4.1 性能优化总结](#4.1 性能优化总结)
-
- [4.1.1 开发环境性能优化](#4.1.1 开发环境性能优化)
- [4.1.2 生产环境性能优化](#4.1.2 生产环境性能优化)
- [5. Webpack配置详解](#5. Webpack配置详解)
-
- [5.1 entry](#5.1 entry)
-
- [5.1.1 Webpack Entry 入口起点配置说明](#5.1.1 Webpack Entry 入口起点配置说明)
-
- [5.1.1.1 String 字符串形式](#5.1.1.1 String 字符串形式)
- [5.1.1.2 Array 数组形式](#5.1.1.2 Array 数组形式)
- [5.1.1.3 Object 对象形式](#5.1.1.3 Object 对象形式)
- [5.1.1.4 特殊用法说明](#5.1.1.4 特殊用法说明)
- [5.2 output](#5.2 output)
- [5.3 module](#5.3 module)
- [5.4 resolve](#5.4 resolve)
- [5.5 devserver](#5.5 devserver)
- [5.6 optimization](#5.6 optimization)
-
- [5.6.1 splitChunks](#5.6.1 splitChunks)
- [5.6.2 runtimeChunk](#5.6.2 runtimeChunk)
- [5.6.3 minimizer](#5.6.3 minimizer)
1. 基础概念
1.1 核心概念
- Entry
- 以哪个文件为起点
- Output
- 打包的资源输出到哪,以及命名
- Loader
- 处理非JavaScript文件
- Plugins
- 用于执行范围更广的任务。包括打包优化,压缩,一直到重新定义环境变量等
- Mode
- 两个值:development/production,对应本地和生产环境
- 区别:
- process.NODE_ENV的值不同,为设置的mode值
- 设置不同:production会启用一些生产环境的插件
2. 开发环境配置
2.1 打包资源(样式,html,图片,其他)
2.1.1 样式处理
javascript
module: {
rules: [
{
test: /\.css$/,
// loader 从右到左执行
// style-loader 创建style标签,将js中的样式插入到style标签中,添加到head中
// css-loader 将css文件变成commonjs模块加载到js中,里面内容是css字符串
use: ['style-loader', 'css-loader'],
},
{
// less-loader 将less文件编译为css文件
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
}
]
}
2.1.2 HTML处理
javascript
const HTMLWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HTMLWebpackPlugin({
template: './src/index.html',
}),
],
2.1.3 图片处理
javascript
module: {
rules: [
// 处理图片资源
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
// url-loader和file-loader功能类似,url-loader会调用file-loader
loader: 'url-loader',
options: {
// 当图片小于8192字节时,将图片转换为base64编码,否则会转换为文件
// 好处:减少请求数量
// 坏处:图片体积会变大,因为base64编码的图片体积会变大
limit: 8192,
// 解决图片引入问题
// 默认是true,表示是commonjs模块,会通过require方式引入
// 如果设置为false,表示是es模块,会通过import方式引入
esModule: false,
// 输出文件名
// [hash:8]:8位hash值
// [ext]:文件扩展名
name: '[hash:8].[ext]',
},
},
{
// 处理html文件中的图片
test: /\.html$/,
loader: 'html-loader',
}
]
},
2.1.4 其他资源处理
javascript
module: {
rules: [
// 打包其他资源
{
exclude: /\.(js|css|html|less)$/,
loader: 'file-loader',
options: {
name: '[hash:8].[ext]',
},
}
]
},
2.2 devServer
2.2.1 Webpack5 重要更新
webpack5的devServer的contentBase属性改为了static/directory。示例:
javascript
devServer: {
static: { // 服务器所加载文件的目录
directory: path.join(__dirname, 'dist'),
},
compress: true,
port: 8080,
// 热更新
hot: true,
},
2.2.2 旧版配置
javascript
// 只会在内存中编译,不会生成文件
// 启动命令: npx webpack-dev-server
devServer: {
// 打包后的资源目录
contentBase: resolve(__dirname, 'dist'),
// 压缩
compress: true,
// 端口
port: 3000,
// 自动打开浏览器
open: true,
},
2.3 CSS处理
2.3.1 处理成单独文件
javascript
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
import HTMLWebpackPlugin from 'html-webpack-plugin';
module: {
rules: [
{
test: /\.css$/,
use: [
// MiniCssExtractPlugin.loader取代style-loader。作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css整合到js文件中
'css-loader'
],
},
],
},
plugins: [
new HTMLWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
}),
new MiniCssExtractPlugin({
filename: 'css/main.css',
}),
],
2.3.2 CSS兼容性处理
通过postcss-loader和postcss-preset-env
javascript
// package.json中
"browserslist": {
"production": [
"> 0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
// webpack.config.js中
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: ["postcss-preset-env"],
},
},
},
],
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html",
}),
new MiniCssExtractPlugin({
filename: "css/index.css",
}),
],
mode: "development",
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
port: 8080,
},
};
2.3.3 压缩CSS
javascript
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
plugins: [
new OptimizeCssAssetsPlugin(),
],
2.4 ESLint
安装eslint eslint-loader eslint-config-airbnb-base eslint-plugin-import
javascript
// package.json中
"eslintConfig": {
"extends": "airbnb-base"
}
// webpack.config.js中
module: {
rules: [
{
test: /\.js$/,
loader: "eslint-loader",
exclude: /node_modules/,
options: {
// 自动修复eslint的错误
fix: true,
},
}
],
},
2.5 JS兼容性处理
安装插件:babel-loader @babel/core @babel/preset-env
-
基本 JS 兼容性处理 → @babel/preset-env
问题:只能转换基本语法(如 Promise 无法转换)。
-
全部 JS 兼容性处理 → @babel/polyfill
问题:会引入所有兼容性代码,体积过大,但实际只需要部分兼容性处理。
-
按需加载兼容性处理 → core-js
实现:仅对需要做兼容性处理的内容进行按需加载。
javascript
// 配置示例
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {
version: 3
},
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
}
2.6 压缩HTML和JS代码
- 设置mode为production,js代码会自动压缩
- 压缩html
javascript
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
// 压缩html代码
minify: {
// 移除注释
removeComments: true,
// 移除空格
collapseWhitespace: true,
},
}),
],
3. 生产环境配置
3.1 性能优化
开发环境性能优化
- 优化打包构建速度
- 优化代码调试
生产环境性能优化
- 优化打包构建速度
- 优化代码运行的性能
3.2 HMR(热模块替换)
HMR:热模块替换,简称热替换
作用:一个模块发生变化时,只会重新打包这一个模块,而不是重新打包所有模块,极大提升构建速度
3.2.1 开启热更新
javascript
// webpack.config.js
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
port: 8080,
// 开启热更新
hot: true,
},
3.2.2 不同文件类型的HMR支持
样式文件:可以使用HMR功能,style-loader内置。
JS文件 :默认不能使用HMR功能,需要修改js代码添加支持HMR功能的代码。注意:HMR功能只能处理非入口js文件。
javascript
// 入口js文件中
if(module.hot){
// 添加需要热更新的模块
module.hot.accept('./other.js');
}
HTML文件:默认不能使用HMR功能,同时会导致问题:html文件不能热更新了。(一般来说html文件只会有一个,所以不用HMR功能)。解决办法:修改entry入口,将html文件引入
javascript
// webpack.config.js
entry: ["./src/index.js", "./src/index.html"],
3.3 source-map
一种提供构建后代码映射到源代码的技术。构建后代码报错,可以通过映射追踪到源代码。
3.3.1 属性说明
【inline-|hidden-|eval-】【nosources-】【cheap-【module-】】source-map
3.3.2 各类型区别
- inline-source-map :内联只生成一个内联source-map
- 错误代码准确信息 和 源代码的错误位置
- hidden-source-map :外部
- 错误代码错误原因,但是没有错误位置
- 不能追踪源代码错误,只能提示到构建后代码的错误位置
- eval-source-map :内联
- 每一个文件都生成对应的source-map,都在eval
- 错误代码准确信息 和 源代码的错误位置
- nosources-source-map :外部
- 错误代码准确信息,但是没有任何源代码信息
- cheap-source-map :外部
- 错误代码准确信息 和 源代码的错误位置
- 只能精确的行
- cheap-module-source-map :外部
- 错误代码准确信息 和 源代码的错误位置
3.3.3 内联和外部区别
- 外部生成了文件,内联没有
- 内联构建速度更快
3.3.4 选择建议
开发环境:速度快,调试更友好
- 速度快(eval>inline>cheap>...)
- eval-cheap-source-map | eval-source-map
- 调试更友好
- source-map
- cheap-module-source-map cheap-source-map
- 推荐:eval-source-map / eval-cheap-module-source-map
生产环境:源代码要不要隐藏?调试要不要更友好
- 内联会让代码体积变大,所以在生产环境不用内联
- nosources-source-map 全部隐藏
- hidden-source-map 只隐藏源代码,会提示构建后代码错误信息
- 推荐:source-map / cheap-module-source-map
3.4 OneOf
默认情况下,所有文件都会经过 rules 中的每一个 loader 进行匹配,效率低下。而 oneOf 的优化在于:文件只要被列表中的任一 loader 成功匹配,就会停止后续匹配,有效加快了构建速度。
注意:
- oneOf中,一个文件只能被一个loader处理
- 当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序
- 例如:先执行eslint在执行babel
3.5 缓存
3.5.1 Babel缓存
cacheDirectory: true
--> 让第二次打包构建速度更快
javascript
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [...],
},
// 开启babel缓存
// 第二次构建时,会读取之前的缓存
cacheDirectory: true
}
3.5.2 文件资源缓存
在需要缓存的文件中设置后缀
javascript
// js
output: {
filename: 'js/built.[contenthash:10].js'
}
// css
plugins: [
new MiniCssExtractPlugin({
filename: 'css/built.[contenthash:10].css'
})
]
3.5.3 文件资源缓存hash值说明
- hash :每次webpack构建时会生成一个唯一的hash值
- 问题:因为js和css同时使用一个hash值。如果重新打包,会导致所有缓存失效。(可能我只改动一个文件)
- chunkhash :根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
- 问题:js和css的hash值还是一样的,因为css是在js中被引入的,所以同属于一个chunk
- contenthash:根据文件的内容生成hash值。不同文件hash值一定不一样
3.6 tree shaking
tree shaking:去除无用代码
前提:
- 必须使用ES6模块化
- 开启production环境
作用:减少代码体积
配置 :
在package.json中配置
json
"sideEffects": false // 所有代码都没有副作用(都可以进行tree shaking)
问题:可能会把css / @babel/polyfill(副作用)文件干掉
解决方案:
json
"sideEffects": ["*.css", "*.less"]
3.7 code split
3.7.1 单入口和多入口
javascript
module.exports = {
// 单入口
// entry: './src/js/index.js'
entry: {
// 多入口:有一个入口,最终输出就有一个bundle
index: '/src/js/index.js',
test: './src/js/test.js'
},
output: {
// [name]:取文件名
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build')
}
}
3.7.2 依赖单独打包
- 可以将node_modules中代码单独打包一个chunk最终输出
- 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
javascript
optimization: {
splitChunks: {
chunks: 'all'
},
}
3.7.3 通过js代码将某个文件单独打包成一个chunk
通过js代码,让某个文件被单独打包成一个chunk
import动态导入语法:能将某个文件单独打包
javascript
import(/* webpackChunkName: 'test' */'./test')
.then(({ mul }) => {
// 文件加载成功~
// eslint-disable-next-line
console.log(mul(2, 5));
}).catch(() => {
// eslint-disable-next-line
console.log('文件加载失败~');
});
3.8 懒加载和预加载
- 懒加载:只有在特定条件下才加载文件
- 预加载 :
/* webpackPrefetch: true */
,在其他文件加载完毕后,才加载此文件(有可能有兼容性问题,在caniuse网站可以查看能否使用)
javascript
document.getElementById('btn').onclick = function(){
import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(({ mul }) => {
console.log(mul(4, 5));
})
}
3.9 PWA
PWA技术,离线可访问,使用workbox-webpack-plugin插件
javascript
new WorkboxWebpackPlugin.GenerateSW({
// 1.帮助servicework快速启动
// 2.删除旧的serviceworker
// 最终生成一个servicework配置文件
clientsClaim: true,
skipWaiting: true,
})
3.9.1 注册serviceworker
javascript
// 注册serviceworker
// 处理兼容性问题
if('serviceworker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceworker
.register('/service-worker.js')
.then(() => {
console.log('sw注册成功了')
})
.catch(() => {
console.log('sw注册失败了');
});
});
}
3.9.2 注意事项
-
eslint不认识 window、navigator全局变量
解决:需要修改package.json中eslintConfig配置
javascript"env": { "browser": true // 支持浏览器端全局变量 }
-
sw代码必须运行在服务器上
bash// nodejs npm i serve -g serve -s build // 启动服务器,将build目录下所有资源作为静态资源暴露出去
3.10 多进程打包
使用thread-loader开启多线程打包
开启多进程打包。
- 进程启动大概为680ms,进程通信也有开销
- 只有工作消耗时间比较长,才需要多进程打包
javascript
{
test: /\.js$/,
exclude: /node_modules/,
use: [
/*
开启多进程打包。
进程启动大概为680ms,进程通信也有开销。
只有工作消耗时间比较长,才需要多进程打包
*/
'thread-loader',
{
loader: 'babel-loader',
options: {
presets: [...]
}
}
]
}
3.10.1 设置多线程打包数量
javascript
{
loader: 'thread-loader',
options: {
workers: 2 // 进程2个
}
}
3.11 externals
排除掉不需要加到最终包里的内容,由我们自己选择引入的方式,如CDN或本地资源
KEY通过import引入的名称
javascript
externals: {
// 拒绝jQuery被打包进来
jquery: 'jquery'
// [KEY]: [VALUE]
}
3.11.1 函数形式
通过函数动态决定是否排除某个模块:
javascript
externals: [
function ({ request }, callback) {
if (/^yourregex$/.test(request)) {
return callback(null, 'commonjs ' + request);
}
callback();
}
]
3.12 dll
作用:对某些库(第三方库:jquery、react、vue等)单独打包
步骤:
- 首先定义webpack.dll.js文件
- 进行单独打包当你运行 webpack 时,默认查找 webpack.config.js 配置文件,所以我们需要修改打包命令为webpack --config webpack.dll.js
3.12.1 webpack.dll.js配置
其中webpack插件DLLPlugin的manifest用来提供映射关系
javascript
// webpack.dll.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
// 最终打包生成的[name] --> jquery
// ['jquery'] --> 要打包的库是jquery
jquery: ['jquery']
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dll'),
library: '[name]_[hash]', // 打包的库里面向外暴露出去的内容叫什么名字
},
plugins: [
// 打包生成一个 manifest.json --> 提供和jquery映射
new webpack.DllPlugin({
name: '[name]_[hash]', // 映射库的暴露的内容名称
path: path.resolve(__dirname, 'dll/manifest.json') // 输出文件路径
})
],
mode: 'production'
};
3.12.2 webpack.config.js中使用
在webpack.config.js中:
- 使用插件add-asset-html-webpack-plugin将某个文件打包输出去,并在html中自动引入该资源
- 使用插件DllReferencePlugin告诉webpack哪些库不参与打包,同时使用时的名称也得变
javascript
// webpack.config.js
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
// 告诉webpack哪些库不参与打包,同时使用时的名称也得变~
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dll/manifest.json')
}),
// 将某个文件打包输出去,并在html中自动引入该资源
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, 'dll/jquery.js')
})
],
4. 优化环境配置
4.1 性能优化总结
4.1.1 开发环境性能优化
- 优化打包构建速度
- HMR
- 优化代码调试
- source-map
4.1.2 生产环境性能优化
- 优化打包构建速度
- oneOf
- babel缓存
- 多进程打包
- externals
- dll
- 优化代码运行的性能
- 缓存(hash-chunkhash-contenthash)
- tree shaking
- code split
- 懒加载/预加载
- pwa
5. Webpack配置详解
5.1 entry
具体可以去webpack官网看
5.1.1 Webpack Entry 入口起点配置说明
5.1.1.1 String 字符串形式
javascript
entry: './src/index.js'
- 单入口:打包形成一个chunk,输出一个bundle文件
- 此时chunk的名称默认是
main
5.1.1.2 Array 数组形式
javascript
entry: ['./src/index.js', './src/add.js']
- 多入口:所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件
- 只有在HMR功能中让html热更新生效
5.1.1.3 Object 对象形式
javascript
entry: {
index: ['./src/index.js', './src/count.js'],
add: './src/add.js'
}
- 多入口:有几个入口文件就形成几个chunk,输出几个bundle文件
- 此时chunk的名称是key
5.1.1.4 特殊用法说明
index: ['./src/index.js', './src/count.js']
- 所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件add: './src/add.js'
- 形成一个chunk,输出一个bundle文件
5.2 output
具体可以去webpack官网看
javascript
module.exports = {
entry: './src/index.js',
output: {
filename: 'js/[name].js', // 文件名称(指定名称+目录)
path: resolve(__dirname, 'build'), // 输出文件目录(将来所有资源输出的公共目录)
publicPath: '/', // 所有资源引入公共路径前缀 --> 'imgs/a.jpg' --> '/imgs/a.jpg'
chunkFilename: 'js/[name]_chunk.js', // 非入口chunk的名称
// library: '[name]', // 整个库向外暴露的变量名
// libraryTarget: 'window' // 变量名添加到哪个上 browser
// libraryTarget: 'global' // 变量名添加到哪个上 node
// libraryTarget: 'commonjs'
},
plugins: [
new HtmlWebpackPlugin()
],
mode: 'development'
}
library向外暴露的变量名在最终打包的js文件中
5.3 module
具体可以去webpack官网看
javascript
rules: [
// loader的配置
{
test: /\.css$/,
// 多个loader用use
use: ['style-loader', 'css-loader']
},
{
test: /\.js$/,
// 排除node_modules下的js文件
exclude: /node_modules/,
// 只检查 src下的js文件
include: resolve(__dirname, 'src'),
// 优先执行
enforce: 'pre',
// 延后执行
// enforce: 'post',
// 单个loader用loader
loader: 'eslint-loader',
options: {}
},
{
// 以下配置只会生效一个
oneOf: []
}
]
5.4 resolve
具体可以去webpack官网看
javascript
// 解析模块的规则
resolve: {
// 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
alias: {
$css: resolve(__dirname, 'src/css')
},
// 配置省略文件路径的后缀名
extensions: ['.js', '.json', '.jsx', '.css'],
// 告诉 webpack 解析模块是去找哪个目录
modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
}
5.5 devserver
具体可以去webpack官网看
javascript
devServer: {
static: {
directory: path.join(__dirname, 'build'),
},
// 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
watchFiles: ['build/**/*'],
watchOptions: {
// 忽略文件
ignored: /node_modules/
},
// 启动gzip压缩
compress: true,
// 端口号
port: 5000,
// 域名
host: 'localhost',
// 自动打开浏览器
open: true,
// 开启HMR功能
hot: true,
// 不要显示启动服务器日志信息
clientLogLevel: 'none',
// 除了一些基本启动信息以外,其他内容都不要显示
quiet: true,
// 如果出错了,不要全屏提示~
overlay: false,
// 服务器代理 --> 解决开发环境跨域问题
proxy: {
//一旦devServer(5000)服务器接受到/api/xxx的请求,就会把请求转发到另外一个服务器(3000)
'/api': {
target: 'http://localhost:3000',
// 发送请求时,请求路径重写:将/api/xxx --> /xxx (去掉/api)
pathRewrite: {
'^/api': ''
}
}
}
}
5.6 optimization
5.6.1 splitChunks
javascript
optimization: {
splitChunks: {
chunks: 'all', // 分割的chunk最小为30kb
minSize: 30 * 1024, // 分割的chunk最小为30kb
maxSiza: 0, // 最大没有限制
minChunks: 1, // 要提取的chunk最少被引用1次
maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量
maxInitialRequests: 3, // 入口js文件最大并行请求数量
automaticNameDelimiter: '~', // 名称连接符
name: true, // 可以使用命名规则
cacheGroups: { // 分割chunk的组
// node_modules文件会被打包到 vendors 组的chunk中。--> vendors~xxx.js
// 满足上面的公共规则,如:大小超过30kb,至少被引用一次。
vendors: {
test: /[\\/]node_modules[\\/]/, // 优先级
priority: -10
},
default: {
// 要提取的chunk最少被引用2次
minChunks: 2,
// 优先级
priority: -20,
// 如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块
reuseExistingChunk: true
}
}
}
}
5.6.2 runtimeChunk
5.6.3 minimizer
javascript
optimization: {
// 将当前模块的记录其他模块的hash单独打包为一个文件 runtime
// 解决:修改a文件导致b文件的contenthash变化
runtimeChunk: {
name: entrypoint => `runtime-${entrypoint.name}`
},
minimizer: [
// 配置生产环境的压缩方案:js和css
new TerserWebpackPlugin({
// 开启缓存
cache: true,
// 开启多进程打包
parallel: true,
// 启动source-map
sourceMap: true
})
]
}