css
style-loader: 创建style标签将css注入页面css-loader: 处理css资源,对@import 和 url()等进行处理,处理css-module
{test: /\.css$/,loader: "style-loader!css-loader?modules" // ?后面跟配置参数,这里表示配置modules为trueoptions: {}},
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"]}
合并配置
// 获取处理样式的Loadersconst 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 -Dconst 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编译缓存},},],},// eslintnew 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,},},},
