使用 react-app-rewired 和 customize-cra 来重写 CRA 的配置
react-app-rewired
该工具可以在不 'eject' 也不创建额外 react-scripts 的情况下修改 create-react-app 内置的 webpack 配置,然后你将拥有 create-react-app 的一切特性,且可以根据你的需要去配置 webpack 的 plugins, loaders 等。
从 Create React App 2.0 开始,这个仓库主要由社区“轻度”维护。
使用了 react-app-rewired 之后,等于你得到了项目的配置权,但这表示你的项目将无法得到 CRA 提供的配置“保证”,希望你知道自己要做什么。
"Stuff can break" — Dan Abramov twitter.com/dan_abramov…
customize-cra
该项目提供了一套实用工具,用于利用 react-app-rewired 核心功能定制 create-react-app 2 和 3 版本的配置。
使用介绍
基本使用流程
- 安装依赖
yarn add react-app-rewired customize-cra -D - 根目录下创建
config-overrides.js文件夹 - 替换 package.json 中 scripts 执行部分
/* package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test",
+ "test": "react-app-rewired test",
"eject": "react-scripts eject"
}
config-overrides.js 配置
const {
override,
adjustStyleLoaders,
addLessLoader,
fixBabelImports,
addBundleVisualizer,
addWebpackAlias,
} = require("customize-cra");
const getCSSModuleLocalIdent = require("react-dev-utils/getCSSModuleLocalIdent");
const path = require("path");
const rmPostcss = () => (config) => {
const rules = config.module.rules.find((rule) =>
Array.isArray(rule.oneOf)
).oneOf;
rules.forEach(
(r) =>
r.use &&
r.use.forEach((u) => {
if (
u.options &&
u.options.postcssOptions &&
u.options.postcssOptions.ident === "postcss"
) {
delete u.options.postcssOptions.plugins;
delete u.options.postcssOptions.config; // this makes the loader load the default config file
}
})
);
return config;
};
module.exports = {
// 修改开发或生产编译 react 应用程序时使用的 Webpack 配置
webpack: override(
// 添加 post-css plugins
// 注意📢: react-scripts 大于等于 5.0.0 版本时 addPostcssPlugins 无效
// 解决方法:将 plugins 配置删除,使用如下 rmPostcss(),根目录添加 postcss.config.js 配置文件
// addPostcssPlugins([
// require("postcss-pxtorem")({
// rootValue: 192,
// propList: ["*"],
// exclude: /node_modules|folder_name/i,
// }),
// ]),
rmPostcss(),
// 添加less支持,需要安装 less 和 less-loader
addLessLoader({
lessOptions: {
javascriptEnabled: true,
},
}),
// 修改所有样式相关 loader 的配置
adjustStyleLoaders(({ use: [, css, postcss, resolve, processor] }) => {
// 为 .less 文件开启 css module
if (processor && processor.loader.includes("less-loader")) {
css.options.modules = {
getLocalIdent: getCSSModuleLocalIdent,
exportLocalsConvention: "camelCase",
};
}
// 解决添加 addLessLoader 后报错[PostCSS Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'plugins'. These properties are valid]
const postcssOptions = postcss.options;
postcss.options = { postcssOptions };
}),
// 如果 antd 用的4.x 版本,组件和样式动态引入,使用时,需要安装 babel-plugin-import
fixBabelImports("import", {
libraryName: "antd",
libraryDirectory: "es",
style: "css",
}),
// 添加别名配置
addWebpackAlias({
"@": path.resolve(__dirname, "src"),
}),
// 生产环境清除 console.log
function dropConsole(config) {
const TerserPlugin = config.optimization.minimizer.find(
(i) => i.constructor.name === "TerserPlugin"
);
if (TerserPlugin) {
TerserPlugin.options.minimizer.options.compress["drop_console"] = true;
}
return config;
},
// 分析 bundle, 需要确保安装 webpack-bundle-analyzer
addBundleVisualizer()
),
};
postcss.config.js
const fs = require("fs");
const path = require("path");
const useTailwind = fs.existsSync(
path.resolve(__dirname, "tailwind.config.js")
);
module.exports = {
plugins: !useTailwind
? [
"postcss-flexbugs-fixes",
[
"postcss-preset-env",
{
autoprefixer: {
flexbox: "no-2009",
},
stage: 3,
},
],
// Adds PostCSS Normalize as the reset css with default options,
// so that it honors browserslist config in package.json
// which in turn let's users customize the target behavior as per their needs.
"postcss-normalize",
require("postcss-pxtorem")({
rootValue: 192, // 表示根元素字体大小
propList: ["*"], // 可以从 px 变为 rem 的属性
exclude: /node_modules|folder_name/i, // 需要排除的文件
}),
]
: [
"tailwindcss",
"postcss-flexbugs-fixes",
[
"postcss-preset-env",
{
autoprefixer: {
flexbox: "no-2009",
},
stage: 3,
},
],
],
};