css
style-loader
: 创建style标签将css注入页面css-loader
: 处理css资源,对@import 和 url()等进行处理,处理css-module
{
test: /\.css$/,
loader: "style-loader!css-loader?modules" // ?后面跟配置参数,这里表示配置modules为true
options: {}
},
css-module
http://www.ruanyifeng.com/blog/2016/06/css_modules.html
会将类名编译成哈希字符串:global(.title) { color: green; }
: 不会编译成哈希字符串
组合:使用composes属性,让一个选择器继承另一个,
.className {
background-color: blue;
}
.title {
composes: className;
color: red;
}
输入其它模块
composes: className from './another.css';
支持变量,不过需要安装postcss-loader, @value blue: #0c77f8;
{
test: /\.css$/,
loader: "style-loader!css-loader?modules!postcss-loader"
},
处理图片
Webpack4:file-loader 和 url-loader
Webpack5:内置到 Webpack 配置即可
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
//,减少请求数量,但体积变得更大
}
}
},
自动清空上次打包资源
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js",
clean: true, // 自动将上次打包目录资源清空
},
处理字体图标
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
type: “asset/resource”和type: “asset”的区别:
- type: “asset/resource” 相当于file-loader, 将文件转化成 Webpack 能识别的资源,其他不做处理
- type: “asset” 相当于url-loader, 将文件转化成 Webpack 能识别的资源,同时小于某个大小的资源会处理成 data URI 形式
eslint
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
],
Babel处理兼容性
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
处理html
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "public/index.html"),
}),
开发服务器
使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。
// 开发服务器
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
},
提取css成单独文件
Css 文件打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式,闪屏
解决方案:利用插件提取成单独的css文件,通过link标签加载
npm i mini-css-extract-plugin -D
// 配置
use: [MiniCssExtractPlugin.loader, "css-loader"],
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
处理css兼容性
npm i postcss-loader postcss postcss-preset-env -D
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
],
},
控制兼容性,在package.json
配置
{
// 其他省略
"browserslist": ["ie >= 8"]
}
合并配置
// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
};
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: getStyleLoaders(),
},
css压缩
npm i css-minimizer-webpack-plugin -D
// css压缩
new CssMinimizerPlugin(),
html与js压缩
默认生产模式已经开启了:html 压缩和 js 压缩j
开启热更新
module.exports = {
// 其他省略
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
hot: true, // 开启HMR功能(只能用于开发环境,生产环境不需要了)
},
};
oneOf
打包时每个文件都会经过所有loader处理,虽然正则没匹配上的没有处理,但都要过一遍比较费时间
rules: [
{
oneOf: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
]
}
]
include/exclude
{
test: /\.js$/,
// exclude: /node_modules/, // 排除node_modules代码不编译
include: path.resolve(__dirname, "../src"), // 也可以用包含
loader: "babel-loader",
},
Cache
对 Eslint 检查 和 Babel 编译结果进行缓存。
{
test: /\.js$/,
// exclude: /node_modules/, // 排除node_modules代码不编译
include: path.resolve(__dirname, "../src"), // 也可以用包含
loader: "babel-loader",
options: {
cacheDirectory: true, // 开启babel编译缓存
cacheCompression: false, // 缓存文件不要压缩
},
},
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
exclude: "node_modules", // 默认值
cache: true, // 开启缓存
// 缓存目录
cacheLocation: path.resolve(
__dirname,
"../node_modules/.cache/.eslintcache"
),
}),
多进程打包
主要是打包js文件
仅在特别耗时的操作中使用,因为每个进程启动就有大约为 600ms 左右开销。
npm i thread-loader -D
const os = require("os");
const TerserPlugin = require("terser-webpack-plugin");
// cpu核数
const threads = os.cpus().length;
// js
{
test: /\.js$/,
// exclude: /node_modules/, // 排除node_modules代码不编译
include: path.resolve(__dirname, "../src"), // 也可以用包含
use: [
{
loader: "thread-loader", // 开启多进程
options: {
workers: threads, // 数量
},
},
{
loader: "babel-loader",
options: {
cacheDirectory: true, // 开启babel编译缓存
},
},
],
},
// eslint
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
exclude: "node_modules", // 默认值
cache: true, // 开启缓存
// 缓存目录
cacheLocation: path.resolve(
__dirname,
"../node_modules/.cache/.eslintcache"
),
threads, // 开启多进程
}),
optimization: {
minimize: true,
minimizer: [
// css压缩也可以写到optimization.minimizer里面,效果一样的
new CssMinimizerPlugin(),
// 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了
new TerserPlugin({
parallel: threads // 开启多进程
})
],
},
减少Babel转换后代码体积
Babel给每个模块都引入了辅助代码,将这些辅助代码作为一个独立模块,来避免重复引入。
{
loader: "babel-loader",
options: {
cacheDirectory: true, // 开启babel编译缓存
cacheCompression: false, // 缓存文件不要压缩
plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
},
},
压缩图片
npm i image-minimizer-webpack-plugin imagemin -D
// 无损模式
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D
// 有损压缩
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D
提取重复代码
optimization: {
// 代码分割配置
splitChunks: {
chunks: "all", // 对所有模块都进行分割
// 以下是默认值
// minSize: 20000, // 分割代码最小的大小
// minRemainingSize: 0, // 类似于minSize,最后确保提取的文件大小不能为0
// minChunks: 1, // 至少被引用的次数,满足条件才会代码分割
// maxAsyncRequests: 30, // 按需加载时并行加载的文件的最大数量
// maxInitialRequests: 30, // 入口js文件最大并行请求数量
// enforceSizeThreshold: 50000, // 超过50kb一定会单独打包(此时会忽略minRemainingSize、maxAsyncRequests、maxInitialRequests)
// cacheGroups: { // 组,哪些模块要打包到一个组
// defaultVendors: { // 组名
// test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
// priority: -10, // 权重(越大越高)
// reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
// },
// default: { // 其他没有写的配置会使用上面的默认值
// minChunks: 2, // 这里的minChunks权重更大
// priority: -20,
// reuseExistingChunk: true,
// },
// },
// 修改配置
cacheGroups: {
// 组,哪些模块要打包到一个组
// defaultVendors: { // 组名
// test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
// priority: -10, // 权重(越大越高)
// reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
// },
default: {
// 其他没有写的配置会使用上面的默认值
minSize: 0, // 我们定义的文件体积太小了,所以要改打包的最小文件体积
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},