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的细节上的功能
- css在开启模块话的时候 type 支持是 icss(Interoperable CSS)
- 更多的可能用到的环境变量配置高级配置
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快速发展