│ ├─pnpTs.js
# pnp相关配置项
│ ├─webpack.config.js
# webpack的配置
│ └─webpackDevServer.config.js
# webpack开发服务器的配置内容
├─fixtures
# 暂不清楚用途
├─lib
# TS定义
├─scripts
# 对应的启动脚本
│ ├─build.js
# run build的脚本
│ ├─eject.js
# run eject的脚本
│ ├─
init
.js
# create-react-app后的执行脚本
│ ├─start.js
# run start的脚本
│ └─utils
# 工具函数封装
├─template
# 普通的js模板文件夹
│ ├─
public
│ └─src
└─template-typescript
# typescript版的模板文件夹
复制代码
流程分析
该源代码采用lerna工具管理依赖,主要的源码均位于packages目录下。在react-scripts目录下的package.json中,bin字段内容如下:
"bin": {
"react-scripts": "./bin/react-scripts.js"
复制代码
因此我们运行该
react-scripts
命令时,实际是执行该目录下的./bin/react-scripts.js。
bin/react-scripts.js
该文件在执行时,会读取命令行参数。主要源码如下:
const args = process.argv.slice(2)
复制代码
在日常开发过程中,执行命令的主要格式是:
yarn run start
, 最终在命令行被转为换:
node react-scripts路径 start
。因此要读取有效的命令行参数,也应该是从第三个参数开始。
在读取到的参数中,查找出有效的命令
build/eject/start/test
对应的序号,如果没有查找到则取第一个参数作为默认值,但最终也会直接输出警告信息后退出程序。
查找到有效命令后,执行**../scripts**目录下对应的脚本文件,并传入除有效参数外的剩余参数。
scripts/init.js
该文件主要是在执行完create-react-app命令后,将项目模板文件复制到新建的项目目录。传入的参数列表如下:
appPath,
appName,
verbose,
originalDirectory,
template
复制代码
scripts/start.js
对应的执行命令为:
yarn run start
。主要作用:启动开发服务器,执行流程如下:
设置环境变量:BABEL_ENV、NODE_ENV=“development”;
加载自定义的环境变量配置;
必要的入口文件检测:作为入口的index.html和js;
读取ip和port;
检测是否配置browserslist。如果最终都没有browserlist则直接退出;
查找可用端口:先确认默认端口是否可用,不可用则确认是否自动查找可用端口,不查找则直接退出,查找则返回一个可用端口;
配置createCompiler的options并执行,返回一个compiler;
载入代理配置,并配置代理服务prepareProxy;
创建开发服务配置,具体的配置代码放在webpackDevServer.config.js;
运行WebpackDevServer,传入compiler和proxyConfig,返回一个devServer
启动devServer服务,如果在交互模式下清理控制台,再打开浏览器
scripts/build.js
对应的执行命令为:
yarn run build
。主要作用:源代码构建,执行流程如下:
设置环境变量:BABEL_ENV、NODE_ENV=“production”;
加载自定义的环境变量配置;
必要的入口文件检测:作为入口的index.html和js;
生成webpack配置;
检测是否配置browserslist;
检测是否配置browserslist。如果最终都没有browserlist则直接退出
在构建前,检测出所有文件大小的map
清空构建的输出目录
复制待构建目录的public目录到构建目录:静态文件夹名——paths.appPublic
开始webpack构建
构建完成后,输出相关的构建信息:警告/警告/错误、文件大小信息、后续操作的提示
scripts/eject.js
对应的执行命令为:
yarn run eject
。主要作用:暴露webpack配置到项目目录中,让用户可以自行修改构建配置,执行流程如下:
确认是否需要继续当前操作——暴露webpack等配置信息?是——继续,否——退出
如果有git源代码管理工具?否——继续;是——是否有未保存的记录?是——退出,否继续
读取react-scripts待复制的文件夹及其下的文件,分别确认所有内容在项目根目录下是否存在,有一个存在则直接退出。检测的文件夹:['config', 'config/jest', 'scripts']
生成相关的jest配置:jestConfig
在项目目录下,创建待复制的文件夹
相关文件复制:相关文件复制:在文件复制文件时,删除文件内容@remove-on-eject-begin...@remove-on-eject-end
package.json配置修改并保存:
devDependencies、dependencies中删除react-scripts
dependencies依赖添加:react-scripts的dependencies中,除了也属于optionalDependencies的所有依赖,全部添加到项目依赖中
dependencies依赖是所有字段全部按依赖名称重新排列一次
scripts字段:用react-scripts的bin字段的key去匹配项目package.json的scripts中所有的value,将匹配到的结果全部替换为node scripts/[key].js
scripts字段:删除eject项
添加其他字段:jest、babel、eslintConfig
如果类型声明的入口路径appTypeDeclarations:读取并替换react-scripts types后保存
移除node_modules/.bin/react-scripts命令
重新安装依赖
如果有git则直接提交git记录
scripts/start.js
scripts/build.js
scripts/eject.js