node chrome-devtool 调试:
在项目根目录执行 node --inspect-brk packages/create-react-app/index.js在chrome地址栏输入 chrome://inspect/#devices
然后就可以在chrome进行断点调试了
一、判断 node 版本

如果 node 版本低于8,则控制台输出以上内容,并退出执行。
二、使用 commander 库做命令行初始化
三、判断是否有传入 projectName(项目名称)

这里的 projectName 就是上面通过 .action(name => { projectName = name})获取的。
如果没有传入的话,直接做一些信息提示,然后退出执行
四、执行 createApp 方法

createApp 主要做的事情就是一些安全性判断比如:检查项目名是否合法,检查文件是否安全,检查npm版本等,同时在这个方法中,把package.json写到了项目根目录下。
五、执行 run 方法
run 主要做的事情主要有:
一、先根据传入的版本version 和原始目录originalDirectory 去获取要安装的某个 package。
二、默认的 version 为空,获取到的 packageToInstall 值是 react-scripts, 然后将packageToInstall拼接到 allDependencies意为所有需要安装的依赖。
三、如果当前是采用yarn安装方式的话,就判断是否处于离线状态。判断完连着前面的 packageToInstall 和 allDependencies 一起丢给 install 方法,再由install方法去跑安装。
getInstallPackage(); 获取要安装的模版包 默认是 react-scripts
getTemplateInstallPackage(); 获取安装的template,也就是那些 src、public文件
install(); 传参数给install 负责安装 allDependencies
catch(); 错误处理
六、 install 方法
从run方法中跑到install方法
能看到代码里根据是否使用yarn分成两种处理方法。if (useYarn) { yarn 安装逻辑 } else { npm 安装逻辑 }
处理方法都是同个逻辑,根据传入的 dependencies 去拼接需要安装的依赖,主要有 react,react-dom,react-script 。再判断verbose和isOnline 加一些命令行的参数。
最后再用node跑命令,平台差异的话是借助cross-spawn去处理的
function install(root, useYarn, usePnp, dependencies, verbose, isOnline) {return new Promise((resolve, reject) => {let command;let args;if (useYarn) {command = 'yarnpkg';args = ['add', '--exact'];if (!isOnline) {args.push('--offline');}if (usePnp) {args.push('--enable-pnp');}[].push.apply(args, dependencies);args.push('--cwd'); // 将cwd设置为我们要安装的目录路径args.push(root);if (!isOnline) {console.log(chalk.yellow('You appear to be offline.'));console.log(chalk.yellow('Falling back to the local Yarn cache.'));console.log();}} else {command = 'npm';args = ['install','--save','--save-exact','--loglevel','error',].concat(dependencies);if (usePnp) {console.log(chalk.yellow("NPM doesn't support PnP."));console.log(chalk.yellow('Falling back to the regular installs.'));console.log();}}if (verbose) {args.push('--verbose');}const child = spawn(command, args, { stdio: 'inherit' });child.on('close', code => {if (code !== 0) {reject({command: `${command} ${args.join(' ')}`,});return;}resolve();});});}
七、 总结
1、判断node版本如果小于8就退出,否则执行 createReactApp.js 文件
2、createReactApp.js先做一些命令行的处理响应处理,然后判断是否有传入 projectName 没有就提示并退出
3、根据传入的 projectName 创建目录,并创建package.json。
4、判断是否有特殊要求指定安装某个版本的react-scripts,然后用cross-spawn去处理跨平台的命令行问题,用 yarn或npm安装react, react-dom, react-scripts,以及模板cra-template包。
5、处理完这些之后,输出提示给用户。
八、流程图

