create-react-app
是大家常用的用来创建react项目的脚手架,它的设计理念和实现思路值的我们学习。我研究了一下create-react-app
源码,并把它的核心功能模块梳理出来。
下面是这篇文章的主要内容:
简单介绍create-react-app的使用
介绍create-react-app的流程,从全局上看create-react-app是怎么创建react项目的
详细的分析create-react-app的3个核心模块的实现
总结
create-react-app快速入门
使用create-react-app创建项目my-app:
1 | npx create-react-app my-app |
- 进入 my-app 文件夹,执行
npm start
启动项目
默认阅读这篇文章的同学都是接触过create-react-app的人,所以不对如何使用create-react-app进行深入介绍,如果想了解详细情况请阅读官网文档(👉 create-react-app)。
必备知识
为了更好的了解create-react-app内部的实现原理,我们需要掌握以下这几个知识点:
1. monorepo管理
概念
Monorepo 是管理项目代码的一个方案,即在一个项目仓库(repo)中管理多个模块/包(package)。Monorepo的优势在于一个仓库维护多个模块,能够统一工作流,代码共享。
create-react-app使用Monorepo方案在packages下维护了11个包。这些包互相之间有一定的联系,放在一个仓库中维护方便代码管理。此思路也值的我们在工作中学习运用。
1 | . |
使用
我们可以用lerna或yarn workspace实现Monorepo方案,此处介绍lerna构建基础Monorepo仓库过程:
- 进入项目目录,创建一个 lerna 管理的仓库
1 | lerna init |
- 增加一个 packages
1 | lerna create my-package |
- 发布包。提示输入新版本并更新所有在 github 和 npm的包。
1 | lerna publish |
- 把packages下所有包的依赖安装到根 node_modules。
1 | lerna bootstrap |
2. node必备模块
commander
commander 是一个完整的node.js命令行解决方案,封装了获取命令行指令
.version
方法可以设置版本,其默认选项为-V和–version- 通过
.arguments
可以为最顶层命令指定参数,对子命令而言,参数都包括在command调用之中了。尖括表示必填(eg. ),而方括号(eg. [optional])则代表选填。 - 通过
.usage
选项可以修改帮助信息的首行提示
如下demo表示,运行create-react-app myApp op1,其中myApp是必须要写的,op1可不写
1 | const chalk = require('chalk'); |
cross-spawn
cross-spawn是node的spawn和spawnSync的跨平台解决方案
inherit表示将相应的stdio流传给父进程或从父进程传入
1 | const spawn = require('cross-spawn'); |
create-react-app各模块介绍
create-react-app的实现过程可以用下面的流程图👇表示,最重要的是 create-react-app
,react-scripts
和cra-template
这三个模块。
梳理一下流程:
命令行输入
npx create-react-app my-app
调用
create-react-app
模块,创建
my-app
文件夹写入
package.json
安装
react
,react-dom
,cra-template
,react-scripts
这四个模块调用react-scripts的init.js
调用
react-scripts
的init.js- 根据
cra-template/template.json
和my-app/package.json
合并出新的package.json - 复制
cra-template/template
里的内容到my-app下 - 安装项目依赖
- 移除
cra-template
- 根据
得到目标文件夹 my-app。其中
package.json
的scripts脚本命令调用了react-scripts模块bin/react-scripts
文件。
下面重点介绍 create-react-app
,react-scripts
和cra-template
这三个模块的具体实现。
create-react-app核心模块实现
create-react-app
1. 主要功能
create-react-app
包是入口,用户在命令行输入npx create-react-app my-app
会执行
- 和用户交互,获取项目名 my-app
- 创建my-app文件夹,安装
react
,react-dom
,cra-template
,react-scripts
这四个模块 - 调用
react-scripts/init.js
2. 核心代码
此处根据源码整理的逻辑图,方便大家阅读,
3. 简化版实现
为了便于理解,将上述逻辑简化了一下,实现了个简易版。项目地址:
可以通过npm i min-create-react-app -g 试用此模块。
react-scripts
1. 主要功能
- 复制cra-template到目标文件夹
- 提供webpack的功能
2. 实现思路
2.1 复制cra-template到目标文件夹
2.2 提供scripts命令:
关键代码:
- package.json中bin字段指向./bin/react-scripts.js说明命令行中执行react-scripts xxx 命令会执行此文件。
- ./bin/react-scripts.js 中第27行和31行说明实际上执行的是对应的build.js、eject.js、start.js和test.js这四个文件。
- react-scripts start命令
- 设置process.env.NODE_ENV = ‘development’
- 获取webpack配置文件config/webpackDevServer.config.js
- 调用react-dev-utils/WebpackDevServerUtils/createCompiler生成compiler
- 调用/config/webpackDevServer.config.js生成serverConfig
- 启动WebpackDevServer服务
- 启动浏览器,打开项目页面
- build命令
- 设置process.env.NODE_ENV = ‘production’;
- 获取webpack配置文件
- 清空build目录
- 拷贝public目录下的文件到build目录
- 创建compiler并调用run方法进行编译
react的webpack配置文件做了很多优化配置,值的我们学习:github.com/facebook/cr…
cra-template
1. 目录结构
1 | . |
2. 主要功能
cra-template放的是react基础项目模板,会被拷贝到目标文件夹成为基础项目文件。
- public中存放静态资源
- src中存放.js和.css文件
- template.json中有此模板依赖的package,react-scripts在复制模板到目标文件夹时会将template.json和原package.json文件合并生成新的package.json
总结
至此,create-react-app的核心代码已经介绍完毕。
通过这篇文章,我们了解到以下几点:
create-react-app 采用Monorepo方案,在一个仓库里管理create-react-app,react-scripts和cra-template等多个包,实现工作流和代码共享;
create-react-app 项目中,create-react-app包是入口,实现了读取命令行中的项目名,创建项目文件夹,安装react, react-dom, cra-template, react-scripts 这四个模块,最后调用react-scripts的init.js
react-scripts提供两块功能,一是复制cra-template到目标文件夹,二是提供webpack的功能
cra-template放的是react基础项目模板,会被拷贝到目标文件夹成为基础项目文件
希望这篇文章能够对你有所帮助。