使用CRACO自定义 Webpack 配置

发布于:2025-03-20 ⋅ 阅读:(35) ⋅ 点赞:(0)

1、为什么要用 CRACO?

默认情况下,CRA 的 Webpack 配置是隐藏的,如果你需要修改 Webpack,比如:
✅ CDN配置
✅ 配置 alias(路径别名)
✅ 修改 Less/Sass 变量
✅ 添加 Babel 插件
✅ 优化 Webpack 构建(如 SplitChunks、CDN 加载)
✅ 支持 Tailwind CSS
✅ 移动端适配启用 PostCSS + px 转 rem

如果不用 CRACO,你必须运行 yarn eject / npm run eject,但这会暴露 CRA 内部所有配置,导致维护成本增加。因此,CRACO 允许在不 eject 的情况下修改 Webpack 配置。

2、craco.config.js 是什么?从哪里来的?

1️⃣ craco.config.js 是什么?
craco.config.js 是 CRACO(Create React App Configuration Override) 的配置文件。
它用于修改 Create React App(CRA)的 Webpack 配置,无需 eject(弹出)。

2️⃣ craco.config.js 从哪里来的?
它是 开发者手动创建 的,默认 CRA 项目没有,需要安装 CRACO 后才使用。

如果你看到 craco.config.js,说明这个 React 项目使用了 CRACO 来覆盖默认配置。

3、如何安装 & 创建 craco.config.js?

✅ 1. 安装 CRACO

npm install @craco/craco --save-dev

或者

yarn add @craco/craco --dev

✅ 2. 在 React 项目根目录创建 craco.config.js

touch craco.config.js

✅ 3. 修改 package.json,替换 react-scripts 为 craco

{
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test"
  }
}

在这里插入图片描述

4、项目事例

const path = require('path');
const CracoLessPlugin = require('craco-less');
const fs = require('fs');

const rewireBabelLoader = require('craco-babel-loader');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);

module.exports = {
  webpack: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
    configure: (webpackConfig, { env }) => {
       if (env === 'production') {
         webpackConfig.output.publicPath = 'https://cdn.unionlao.com/la_unionlao_ios/';
       }
      if (env === 'development' || env === 'test') {
        webpackConfig.devtool = 'eval-source-map';
        webpackConfig.output.publicPath = 'https://cdn.unionlao.com/la_unionlao_ios/';
      }
      if (env !== 'development') {

        webpackConfig.optimization.splitChunks = {
          cacheGroups: {
            commons: {
              chunks: 'all',
              name: 'commons',
              minSize: 0, // 公用模塊的大小限制 bytes
              minChunks: 2, // 公用模塊最少復用次數
              maxInitialRequests: 2,
              priority: 10,
              reuseExistingChunk: true,
            },
          },
        };
      }
      return webpackConfig;
    },
  },
  plugins: [
    {
      plugin: CracoLessPlugin,
    },
    {
      plugin: rewireBabelLoader,
      options: {
        includes: [resolveApp('../../libs')], //put things you want to include in array here
        excludes: [/(node_modules|bower_components)/], //things you want to exclude here
     
      },
    },
  ],
  style: {
    postcss: {
      mode: 'extends',
      loaderOptions: {
        postcssOptions: {
          ident: 'postcss',
          plugins: [
            [
              'postcss-pxtorem',
              {
                rootValue: 37.5,
                unitPrecision: 2,
                // propList: ['*', '!font-size', '!*font-size*'],
                propList: ['*'],
                selectorBlackList: [],
                replace: true,
                mediaQuery: false,
                minPixelValue: 0,
                // exclude: /node_modules/i
              },
            ],
          ],
        },
      },
    },
  },
};