自定义 webpack 配置4:优化配置

tech2025-09-23  20

参考 webpack教程、create-react-app(eject后)配置,自定义一个适合的、可维护的webpack配置

1. 保持版本最新

较新的版本能够建立更高效的模块树以及提高解析速度。

1.1 Node.js

1.1.1 最新版本

v14.7.0

1.1.2 查看本地版本

node -v //或者 node --version

1.1.3 下载安装最新版本

1.2 npm

1.2.1 最新版本

v6.14.7

1.2.2 查看本地版本

npm -v //或者 npm --version

1.2.3 更新版本

包含在Node.js 安装包内。Node.js 最新,npm 最新fancy-install-unixnpm install npm@latest -g

1.3 yarn

1.3.1 最新版本

v1.22.4

1.3.2 查看本地版本

yarn -v //或者 yarn --version

1.3.3 更新版本

brew install yarn 无法更新到最新版本curl -o- -L https://yarnpkg.com/install.sh | bash 更新成功

1.3 webpack

1.3.1 最新版本

v4.44.1

1.3.2 查看本地版本

package.json 查看即可

1.3.3 更新版本

使用 npm 更新使用 yarn 更新

2. 减少 loader 作用范围

以 babel-loader 为例,可以明显减少构建时间

{ test: /\.(js|mjs|jsx|ts|tsx)$/, //include: pathsUtil.appSrc, use: { loader: "babel-loader", options: { presets: [["@babel/preset-env"], "@babel/preset-react"], }, }, }, SMP ⏱ Loaders babel-loader took 3.19 secs module count = 12 mini-css-extract-plugin, and css-loader, and postcss-loader took 1.65 secs module count = 1 url-loader took 1.57 secs module count = 2 html-webpack-plugin took 1.54 secs module count = 1 css-loader, and postcss-loader took 1.49 secs module count = 1 file-loader took 0.002 secs module count = 1 { test: /\.(js|mjs|jsx|ts|tsx)$/, include: pathsUtil.appSrc, use: { loader: "babel-loader", options: { presets: [["@babel/preset-env"], "@babel/preset-react"], }, }, }, SMP ⏱ Loaders babel-loader took 0.539 secs module count = 4 mini-css-extract-plugin, and css-loader, and postcss-loader took 0.39 secs module count = 1 url-loader took 0.36 secs module count = 2 css-loader, and postcss-loader took 0.299 secs module count = 1 modules with no loaders took 0.286 secs module count = 9 html-webpack-plugin took 0.259 secs module count = 1 file-loader took 0.002 secs module count = 1

3. 自定义 CSS Module 名称

3.1 新增组件和样式文件

<!--Page1.jsx--> import React from "react"; import styles from "./Page1.css"; export default class Page1 extends React.Component { render() { return <div className={styles.color}>my-webpack-config</div>; } } <!--Page1.css--> .color { color: red; } <!--打包显示--> <div class="_3nyJKZ_2xnbZEzEA9FKoRL">my-webpack-config</div>

3.2 自定义显示

3.2.1 新增 getCssModuleName 文件处理显示名称

"use strict"; const loaderUtils = require("loader-utils"); const path = require("path"); module.exports = function getCssModuleName( context, localIdentName, localName, options ) { // Use the filename or folder name, based on some uses the index.js / index.module.(css|scss|sass) project style const fileNameOrFolder = context.resourcePath.match( /index\.module\.(css|scss|sass)$/ ) ? "[folder]" : "[name]"; // Create a hash based on a the file location and class name. Will be unique across a project, and close to globally unique. const hash = loaderUtils.getHashDigest( path.posix.relative(context.rootContext, context.resourcePath) + localName, "md5", "base64", 5 ); // Use loaderUtils to find the file or folder name const className = loaderUtils.interpolateName( context, fileNameOrFolder + "_" + localName + "__" + hash, options ); // remove the .module that appears in every classname when based on the file. return className.replace(".module_", "_"); };

3.2.2 编辑 css-loader 配置

{ test: /\.css$/, include: pathsUtil.appSrc, use: [ { loader: MiniCssExtractPlugin.loader, options: { publicPath: "../../" }, }, { loader: "css-loader", options: { importLoaders: 1, // modules: true, modules: { getLocalIdent: getCssModuleName, }, }, }, // Use it after css-loader and style-loader, but before other preprocessor loaders like e.g sass|less|stylus-loader, if you use any. { loader: "postcss-loader", options: { plugins: [require("autoprefixer")], }, }, ], }, <!--打包显示--> <div class="Page1_color__KVvDQ">my-webpack-config</div>

4. CSS Tree Shaking

移除没有使用的 CSS 使用 purgecss 来完成,针对 React+webpack+CssModule 只能使用 postcss-purgecss,不能使用 purgecss-webpack-plugin 原因查看详情中 @goldmont 的回答。

4.1 安装依赖

yarn add -D @fullhuman/postcss-purgecss glob-all

4.2 编辑 APP.jsx 和 APP.module.css 文件

import React from "react"; import styles from "./App.module.css"; import smallImage from "./image/small.png"; import bigImage from "./image/big.png"; export default class App extends React.Component { componentDidMount() { // console1.log("my-webpack-config"); } render() { return ( <div> <div className={styles.color}>my-webpack-config</div> <div className={`${styles.color} ${styles.myFirstFont}`}> my-webpack-config </div> <img src={smallImage} alt=""></img> <img src={bigImage} alt=""></img> </div> ); } } .color { color: rebeccapurple; display: flex; box-sizing: border-box; } .myFirstFont { font-family: myFirstFont; } <!--没有使用的属性--> .color2 { color: blue; }

4.3 编辑 webpack.base.js 文件

{ loader: "postcss-loader", options: { plugins: [ require("autoprefixer"), require("@fullhuman/postcss-purgecss")({ content: [ pathsUtil.appHtml, ...glob.sync( path.join(pathsUtil.appSrc, "/**/*.{js,jsx}"), { nodir: true, } ), ], }), ], }, }

4.4 重新构建对比

<!-- 处理前,多余属性 color2 存在 --> <!--重新格式化--> @font-face { font-family: myFirstFont; src: url(../../static/media/font.d55bf3f0.ttf); } .App_color__2ZKCn { color: #639; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-sizing: border-box; box-sizing: border-box; } .App_color2__2BDwS { color: #00f; } .App_myFirstFont__q9w-n { font-family: myFirstFont; } <!-- 处理前,多余属性 color2 已经被删除 --> <!--重新格式化--> @font-face { font-family: myFirstFont; src: url(../../static/media/font.d55bf3f0.ttf); } .App_color__2ZKCn { color: #639; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-sizing: border-box; box-sizing: border-box; } .App_myFirstFont__q9w-n { font-family: myFirstFont; }

代码仓库

my-webpack-config

参考链接

adding-a-css-modules-stylesheetcss-modulescss-loader#localidentnamecss-loader#getlocalidentloader-utils#interpolatename
最新回复(0)