React-CLI总结

504 阅读4分钟

Create React App

Create React App 是官方的集成脚手架,有很多知道借鉴和参考的地方,而是 值得高兴的是 它用的是webpack5 构建。

开始分析之前,请先通过

npx create-react-app // 创建一个react项目

eject 暴露配置

当你初始化好整个CLI的时候,打开package.json能够发现script多了一个 eject选项,

npm run eject

CLI发生了不可逆的事情,向根目录暴露了很多配置文件:

├── config # 配置文件
│   └── jest # 测试
│   └── webpack # 不用管
│   └── env.js # 加载环境变量文件配置
│   └── getHttpsConfig.js # devServer 配置https服务
│   └── modules.js # 模块配置
│   └── path.js # 路径识别
│   └── webpack.config.js # webpack配置
│   └── webpackDevServer.config.js # devServer配置
├── scripts
│   └── build # 打包
│   └── start # 本地
│   └── test # 测试

开始

查看package.json,发现script也发生变化:node xxx文件开始

"scripts": {
  "start": "node scripts/start.js",
  "build": "node scripts/build.js",
  "test": "node scripts/test.js"
}

start / build

build为生产环境,start为开发,通过不同的命令执行不同的脚本,脚本执行的时候设置不同的环境变量,创建不同的config通过 configFactory 方法。

configFactory

根据不同的环境生产不同的配置,当然在此基础上,还可以通过环境变量来控制是否启动 TS、ESLint

!disableESLintPlugin &&
  new ESLintPlugin({
    // Plugin options
    extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'],
    formatter: require.resolve('react-dev-utils/eslintFormatter'),
    eslintPath: require.resolve('eslint'),
    failOnError: !(isEnvDevelopment && emitErrorsAsWarnings),
    context: paths.appSrc,
    cache: true,
    cacheLocation: path.resolve(
      paths.appNodeModules,
      '.cache/.eslintcache'
    ),
    // ESLint class options
    cwd: paths.appPath,
    resolvePluginsRelativeTo: __dirname,
    baseConfig: {
      extends: [require.resolve('eslint-config-react-app/base')],
      rules: {
        ...(!hasJsxRuntime && {
          'react/react-in-jsx-scope': 'error',
        }),
      },
    },
  })

具体请参考 config/webpack.config.js 文件

总览

CLI 5.* 帮我们做了那些事情(特别是jsx、tsx的直接支持)

dotenv加载不同环境下的配置文件

test 就不说了,平时真的很少接触

  • .env
  • .env-development、.env-production、
  • .env-development.local、.env-production.local

这些配置文件配置的变量确实能够生效到node的process.env,但是由于CLI的过滤处理,真正ProvidePlugin的只要以 REACT_APP 开头的环境变量

CLI了内置功能

plugin

  • 支持eslint,并且默认开启eslint检测,可以通过配置环境变量 DISABLE_ESLINT_PLUGIN 关闭 检查(如果你要开启,也可以根目录下创建eslintrc文件,因为使用的是ESLintPlugin,会帮你自动加载)

  • 支持TypeScript,如果侦测到根目录下有ts.config文件,那么根据文件检测TypeScript并编译(loader已经配置好了),没有的话就不会使用plugin。CLI还自动根据 TSC_COMPILE_ON_ERROR 环境变量 为你是否需要对ts文件开启错误警告(默认不开启)。

loader

  • 对于media资源:
    • 常规的资源都是通过 webpack5 的asset module直接进行处理,当然可以通过配置 环境变量:IMAGE_INLINE_SIZE_LIMIT 改变阈值,来对那些资源处理成DataURL形式

    • svg 单独处理,为了支持 svg直接的模块化引入,使用了file-loader,再通过@svgr/webpack,处理svg。

      import { ReactComponent as Logo } from './logo.svg';
      
  • 对于css,直接的支持,sass、postcss,当然如果你希望使用Tailwind,那么只要根目录下出现 tailwind.config.js,就会自动的加载配置。
  • css 支持模块化,但是需要规定文件名为 xxx.module.css
  • jsx | tsx | ts | js 都是使用babel-loader,并添加了对应的插件来处理
  • FAST_REFRESH 环境变量能开启 react的热更新

devServer

  • HOST 环境变量 修改启动的devServer的host
  • PORT 环境变量 修改启动的devServer的port

source-map

  • GENERATE_SOURCEMAP 生产环境下是否生成sourceMap文件

runtimeChunk

  • INLINE_RUNTIME_CHUNK 生产环境下是否生成内联的 runtimeChunk

output

  • BUILD_PATH 生产环境下 输出的目录名称
  • PUBLIC_URL / package.json.homepage 根目录

CLI的细节上的功能

override webpack config

React CLI期望能有一个沉浸式的开箱即用的脚手架,将所有配置封装起来了,但是没有额外的暴露出来。修改起来很麻烦

  • 官方支持

    • react-scripts-rewired:安装之后,在根目录下,创建webpack.config.extend.js,它将被create-react-app 读取
  • 插件支持

  • npm run eject:暴露所有的启动webpack的运行文件,我不反对这么做,但是也不推荐

其实到最后发现即使使用 react-scripts-rewired、react-app-rewired依然很麻烦,我最后觉得还是使用 npm run eject:

  • 即使 它 触发之后 不可逆
  • 即使 它 触发之后 让代码变得更加臃肿

总结

CLI不错,但是Vite更香,期待Vite快速发展