close
  • 简体中文
  • Create React App

    本章节介绍如何将 Create React App(简称 CRA)或 CRACO 项目迁移到 Rsbuild。

    CRA eject

    如果你的项目已经执行了 CRA 的 eject 命令,那么本文档的大部分内容将不再适用。

    CRA 项目在 eject 后,更近似于直接使用 webpack 的项目,因此可参考 webpack 迁移指南

    使用 Agent Skills

    使用支持 Skills 的 coding agent 时,可安装 migrate-to-rsbuild 技能来辅助完成迁移流程。

    npx skills add rstackjs/agent-skills --skill migrate-to-rsbuild

    安装后,让 coding agent 协助完成迁移即可。

    安装依赖

    首先,将 CRA 的 npm 依赖替换为 Rsbuild 的依赖。

    • 移除 CRA 的依赖:
    npm
    yarn
    pnpm
    bun
    deno
    npm remove react-scripts

    对于使用 CRACO 的项目,你还可以移除 @craco/craco 依赖。

    • 安装 Rsbuild 的依赖:
    npm
    yarn
    pnpm
    bun
    deno
    npm add @rsbuild/core @rsbuild/plugin-react -D

    更新 npm scripts

    下一步,将 package.json 中的 npm scripts 更新为 Rsbuild 的 CLI 命令。

    package.json
    {
      "scripts": {
        "start": "react-scripts start",
        "build": "react-scripts build",
        "eject": "react-scripts eject",
        "start": "rsbuild",
        "build": "rsbuild build",
        "preview": "rsbuild preview"
      }
    }
    Tip

    Rsbuild 没有内置测试框架,因此没有提供用于替换 react-scripts test 的命令,可直接使用 Rstest、Jest 或 Vitest 等测试框架。查看 测试 了解更多。

    创建配置文件

    在 package.json 的同级目录下创建 Rsbuild 的配置文件 rsbuild.config.ts,并添加以下内容:

    rsbuild.config.ts
    import { defineConfig } from '@rsbuild/core';
    import { pluginReact } from '@rsbuild/plugin-react';
    
    export default defineConfig({
      plugins: [pluginReact()],
    });

    HTML 模板

    CRA 默认使用 public/index.html 文件作为 HTML 模板。在 Rsbuild 中,通过 html.template 指定 HTML 模板:

    rsbuild.config.ts
    export default defineConfig({
      html: {
        template: './public/index.html',
      },
    });

    在 HTML 模板中,如果使用了 CRA 的 %PUBLIC_URL% 变量,请替换为 Rsbuild 的 assetPrefix 变量,并使用斜杠进行连接:

    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <link rel="icon" href="<%= assetPrefix %>/favicon.ico" />

    这样就完成了从 CRA 到 Rsbuild 的基本迁移,此时你可以执行 npm run start 命令来尝试启动开发服务器。

    构建产物目录

    CRA 默认会将构建产物输出到 build 目录,而 Rsbuild 的默认构建产物目录为 dist

    配置 Rsbuild 的 output.distPath.root 选项,将目录修改为 build,与 CRA 保持一致:

    rsbuild.config.ts
    export default {
      output: {
        distPath: {
          root: 'build',
        },
      },
    };

    更多细节请参考构建产物章节。

    使用 CSS 预处理器

    Rsbuild 通过插件来支持 Sass 和 Less 等 CSS 预处理器,使用方式请参考:

    使用 SVGR

    如果 CRA 项目使用了 "SVG 转 React 组件" 功能(即 SVGR),还需安装 Rsbuild 的 SVGR 插件。

    比如使用了以下用法:

    import { ReactComponent as Logo } from './logo.svg';
    
    const App = () => (
      <div>
        <Logo />
      </div>
    );

    只需要安装和注册 @rsbuild/plugin-svgr 即可:

    rsbuild.config.ts
    import { pluginSvgr } from '@rsbuild/plugin-svgr';
    
    export default {
      plugins: [pluginSvgr({ mixedImport: true })],
    };

    请参考 SVGR 插件 文档了解如何在 Rsbuild 中使用 SVGR。

    配置迁移

    以下是 CRA 配置对应的 Rsbuild 配置:

    CRARsbuild
    HOSTserver.host
    PORTserver.port
    HTTPSserver.https
    WDS_SOCKET_HOSTdev.client.host
    WDS_SOCKET_PATHdev.client.path
    WDS_SOCKET_PORTdev.client.port
    PUBLIC_URLdev.assetPrefix / output.assetPrefix
    BUILD_PATHoutput.distPath
    GENERATE_SOURCEMAPoutput.sourceMap
    IMAGE_INLINE_SIZE_LIMIToutput.dataUriLimit
    FAST_REFRESHdev.hmr
    TSC_COMPILE_ON_ERROR@rsbuild/plugin-type-check

    说明:

    • 上述表格尚未覆盖到 CRA 的所有配置,欢迎补充。

    编译 node_modules

    CRA 默认会使用 Babel 编译 node_modules 中的依赖,但 Rsbuild 则不会,这是为了避免二次编译带来的性能损耗和潜在的编译错误。

    如果你需要处理 node_modules 中依赖引起的语法兼容性问题,可以使用 source.include 配置项来编译 node_modules。

    rsbuild.config.ts
    export default {
      source: {
        // 编译所有 JS 文件并排除 core-js
        include: [{ not: /[\\/]core-js[\\/]/ }],
      },
    };

    环境变量

    CRA 默认会将 REACT_APP_ 开头的环境变量注入到 client 代码中,而 Rsbuild 默认会注入 PUBLIC_ 开头的环境变量(参考 public 变量)。

    为了兼容 CRA 的行为,可手动调用 Rsbuild 提供的 loadEnv 方法来读取 REACT_APP_ 开头的环境变量,并通过 source.define 配置项注入到 client 代码中。

    rsbuild.config.ts
    import { defineConfig, loadEnv } from '@rsbuild/core';
    
    const { publicVars } = loadEnv({ prefixes: ['REACT_APP_'] });
    
    export default defineConfig({
      source: {
        define: publicVars,
      },
    });

    值得注意的是,CRA 允许在代码中访问完整的 process.env 对象,也允许对 process.env 进行解构。而 Rsbuild 出于包体积和安全的考虑,并没有注入完整的 process.env 对象。

    src/index.js
    // CRA 中可以这样访问
    const { PUBLIC_URL } = process.env;
    console.log(PUBLIC_URL);
    console.log(process.env);

    在 Rsbuild 中,可通过 source.define 配置项设置 process.env,读取 loadEnv 方法返回的 rawPublicVars,来允许以上用法:

    rsbuild.config.ts
    import { defineConfig, loadEnv } from '@rsbuild/core';
    
    const { publicVars, rawPublicVars } = loadEnv({ prefixes: ['REACT_APP_'] });
    
    export default defineConfig({
      source: {
        define: {
          ...publicVars,
          'process.env': JSON.stringify(rawPublicVars),
        },
      },
    });

    引用未知资源

    在 CRA 中,如果你引用了一个构建工具无法识别的资源,CRA 默认会将该文件输出到 build/static/media 目录下,比如 model.gltf 文件:

    index.js
    import model from './model.gltf';

    在 Rsbuild 中,遇到无法识别的资源时,Rsbuild 会输出报错日志,类似于:

    You may need an appropriate loader to handle this file type.

    为了解决该错误,可采用以下方法:

    比如,可添加以下 asset modules 配置,来保持与 CRA 相同的输出结果:

    rsbuild.config.ts
    export default {
      tools: {
        rspack: {
          module: {
            rules: [
              {
                // 匹配 .png 文件
                // 你可以调整该正则表达式,以匹配不同类型的文件
                test: /\.png$/,
                type: 'asset/resource',
                generator: {
                  filename: 'static/media/[name].[hash][ext]',
                },
              },
            ],
          },
        },
      },
    };

    移除 react-app-polyfill

    CRA 提供了 react-app-polyfill 来手动注入 polyfill 代码。

    在 Rsbuild 项目中,可移除 react-app-polyfill 相关的依赖和代码,因为 Rsbuild 会自动读取 browserslist 配置,并允许通过 output.polyfill 配置项启用 polyfill 注入。

    1. 移除 react-app-polyfill 引用:
    src/index.js
    import 'react-app-polyfill/ie11'; 
    import 'react-app-polyfill/stable'; 
    1. 安装 core-js
    npm
    yarn
    pnpm
    bun
    deno
    npm add core-js
    1. 配置 output.polyfill
    rsbuild.config.ts
    export default {
      output: {
        polyfill: 'usage',
      },
    };

    参考 浏览器兼容性 来了解 Rsbuild 是如何处理 polyfill 的。

    配置 ESLint

    CRA 默认使用 ESLint 检查代码质量。Rsbuild 默认不包含代码检查功能,但可在 package.json 中添加单独的 npm script 来运行 ESLint。

    首先安装 eslinteslint-config-react-app。使用 ESLint v8 以保持与 CRA 一致:

    npm
    yarn
    pnpm
    bun
    deno
    npm add eslint@8 eslint-config-react-app -D

    然后在 package.json 中添加 lint 命令,并确认项目中包含 eslintConfig 配置或独立的 ESLint 配置文件:

    package.json
    {
      "scripts": {
        "lint": "eslint src"
      },
      "eslintConfig": {
        "extends": ["react-app", "react-app/jest"]
      }
    }

    然后运行 npm run lint 执行 ESLint 检查。

    在构建中运行 ESLint

    除了在 package.json 中添加 lint 命令,也可添加 @rsbuild/plugin-eslint 插件来保持与 CRA 相同的行为。

    @rsbuild/plugin-eslint 插件允许你在构建过程中执行 ESLint 检查。

    rsbuild.config.ts
    import { pluginEslint } from '@rsbuild/plugin-eslint';
    
    export default {
      plugins: [pluginEslint()],
    };

    注册后,在开发 (npm run dev) 和生产构建 (npm run build) 过程中,ESLint 会自动运行。插件会在控制台输出 ESLint 警告和错误。

    Warning

    我们并不推荐使用 @rsbuild/plugin-eslint,因为在构建过程中运行 ESLint 检查会显著增加构建时间。更推荐的做法是使用单独的 lint 命令来执行 ESLint 检查。

    读取 jsconfig.json

    在非 TypeScript 项目中,CRA 支持读取 jsconfig.json 中的 paths 字段作为路径别名。

    如果你需要在 Rsbuild 中使用该特性,可以参考 路径别名 - jsconfig.json

    CRACO 迁移

    如果你的项目使用了 CRACO 来覆盖 CRA 的配置,可以参考下表来迁移:

    示例

    下面是一个从 webpack.configure 迁移到 tools.rspack 的例子:

    • 迁移前:
    craco.config.js
    const { whenDev } = require('@craco/craco');
    
    module.exports = {
      webpack: {
        configure: {
          resolve: {
            mainFields: ['browser', 'module', 'main'],
          },
        },
        plugins: [...whenDev(() => [new MyWebpackPlugin()], [])],
      },
    };
    • 迁移后:
    rsbuild.config.ts
    export default {
      tools: {
        rspack: {
          resolve: {
            mainFields: ['browser', 'module', 'main'],
          },
          plugins: process.env.NODE_ENV === 'development' ? [new MyWebpackPlugin()] : [],
        },
      },
    };

    内容补充

    当前文档只涵盖了迁移过程的部分事项,如果你发现有合适的内容可以补充,欢迎通过 pull request 来完善文档 🤝。

    Rsbuild 的文档位于 rsbuild/website 目录。