createReactApp函数解读
在create-react-app脚手架的目录为/packages/create-react-app/createReactApp.js
函数定义:创建react app
源码如下:
function createApp(name, verbose, version, template, useYarn, usePnp) {
const unsupportedNodeVersion = !semver.satisfies(
// Coerce strings with metadata (i.e. `15.0.0-nightly`).
semver.coerce(process.version),
'>=14'
);
if (unsupportedNodeVersion) {
console.log(
chalk.yellow(
`You are using Node ${process.version} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
`Please update to Node 14 or higher for a better, fully supported experience.\n`
)
);
// Fall back to latest supported react-scripts on Node 4
version = 'react-scripts@0.9.x';
}
const root = path.resolve(name);
const appName = path.basename(root);
checkAppName(appName);
fs.ensureDirSync(name);
if (!isSafeToCreateProjectIn(root, name)) {
process.exit(1);
}
console.log();
console.log(`Creating a new React app in ${chalk.green(root)}.`);
console.log();
const packageJson = {
name: appName,
version: '0.1.0',
private: true,
};
fs.writeFileSync(
path.join(root, 'package.json'),
JSON.stringify(packageJson, null, 2) + os.EOL
);
const originalDirectory = process.cwd();
process.chdir(root);
if (!useYarn && !checkThatNpmCanReadCwd()) {
process.exit(1);
}
if (!useYarn) {
const npmInfo = checkNpmVersion();
if (!npmInfo.hasMinNpm) {
if (npmInfo.npmVersion) {
console.log(
chalk.yellow(
`You are using npm ${npmInfo.npmVersion} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
`Please update to npm 6 or higher for a better, fully supported experience.\n`
)
);
}
// Fall back to latest supported react-scripts for npm 3
version = 'react-scripts@0.9.x';
}
} else if (usePnp) {
const yarnInfo = checkYarnVersion();
if (yarnInfo.yarnVersion) {
if (!yarnInfo.hasMinYarnPnp) {
console.log(
chalk.yellow(
`You are using Yarn ${yarnInfo.yarnVersion} together with the --use-pnp flag, but Plug'n'Play is only supported starting from the 1.12 release.\n\n` +
`Please update to Yarn 1.12 or higher for a better, fully supported experience.\n`
)
);
// 1.11 had an issue with webpack-dev-middleware, so better not use PnP with it (never reached stable, but still)
usePnp = false;
}
if (!yarnInfo.hasMaxYarnPnp) {
console.log(
chalk.yellow(
'The --use-pnp flag is no longer necessary with yarn 2 and will be deprecated and removed in a future release.\n'
)
);
// 2 supports PnP by default and breaks when trying to use the flag
usePnp = false;
}
}
}
run(
root,
appName,
version,
verbose,
originalDirectory,
template,
useYarn,
usePnp
);
}
函数解析
debug代码显示:unsupportedNodeVersion判断当前运行Node版本是否大于v14如果小于,则打印提示信息
1. checkAppName(appName)
function checkAppName(appName) {
const validationResult = validateProjectName(appName);
if (!validationResult.validForNewPackages) { // true取反,为false,不进入
console.error(
chalk.red(
`Cannot create a project named ${chalk.green(
`"${appName}"`
)} because of npm naming restrictions:\n`
)
);
[
...(validationResult.errors || []),
...(validationResult.warnings || []),
].forEach(error => {
console.error(chalk.red(` * ${error}`));
});
console.error(chalk.red('\nPlease choose a different project name.'));
process.exit(1);
}
// TODO: there should be a single place that holds the dependencies
const dependencies = ['react', 'react-dom', 'react-scripts'].sort();
if (dependencies.includes(appName)) {
console.error(
chalk.red(
`Cannot create a project named ${chalk.green(
`"${appName}"`
)} because a dependency with the same name exists.\n` +
`Due to the way npm works, the following names are not allowed:\n\n`
) +
chalk.cyan(dependencies.map(depName => ` ${depName}`).join('\n')) +
chalk.red('\n\nPlease choose a different project name.')
);
process.exit(1);
}
}
if (!validationResult.validForNewPackages)// true取反,为false,不进入if (dependencies.includes(appName)) {// false- 执行完检查app名字;
2. 创建项目根目录
- 继续执行
fs.ensureDirSync(fs为三方库fs-extra)表示异步创建目录, 至此,当前根目录下就可以看到目录my-app - 判断
isSafeToCreateProjectIn(root,name)冲突文件conflicts.length为0,移除log文件,返回true
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X1wZlxaq-1658397798504)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b65c93ecc10248b98db7b1bbc5c7da2a~tplv-k3u1fbpfcp-watermark.image?)]](https://i-blog.csdnimg.cn/blog_migrate/078ea52c36f36af76391b6780db6a830.png)
控制台打印如下:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZxCiOOW-1658397798505)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/91c8566f9dcd4e47a05a4584ee9c742a~tplv-k3u1fbpfcp-watermark.image?)]](https://i-blog.csdnimg.cn/blog_migrate/f7c63a5b0e076e3794b6edd551989cd0.png)
3. 写入package.json
为初始化项目写入package.json配置
const packageJson = {
name: appName,
version: '0.1.0',
private: true,
};
fs.writeFileSync(
path.join(root, 'package.json'),
JSON.stringify(packageJson, null, 2) + os.EOL
);
去刚刚新建的项目目录下查看,可以看到
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AbCd0wQg-1658397798506)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/50977e37aa4d43508b5178b7ed40c26c~tplv-k3u1fbpfcp-watermark.image?)]](https://i-blog.csdnimg.cn/blog_migrate/6351ece5acc6d91426dbea91fa3c5b8a.png)
4. 执行checkThatNpmCanReadCwd
// 不使用用yarn 而且npm执行有问题,报错,异常退出
if (!useYarn && !checkThatNpmCanReadCwd()) {
process.exit(1);
}
process.chdir()方法是过程模块的内置应用程序编程接口,用于更改当前工作目录。
继续执行,执行函数checkThatNpmCanReadCwd,具体含义查看【create-react-app脚手架核心源码解读(二)】
返回true
5. useYarn
if (!useYarn) {
const npmInfo = checkNpmVersion();
if (!npmInfo.hasMinNpm) {
if (npmInfo.npmVersion) {
console.log(
chalk.yellow(
`You are using npm ${npmInfo.npmVersion} so the project will be bootstrapped with an old unsupported version of tools.\n\n` +
`Please update to npm 6 or higher for a better, fully supported experience.\n`
)
);
}
// Fall back to latest supported react-scripts for npm 3
version = 'react-scripts@0.9.x';
}
} else if (usePnp) {
const yarnInfo = checkYarnVersion();
if (yarnInfo.yarnVersion) {
if (!yarnInfo.hasMinYarnPnp) {
console.log(
chalk.yellow(
`You are using Yarn ${yarnInfo.yarnVersion} together with the --use-pnp flag, but Plug'n'Play is only supported starting from the 1.12 release.\n\n` +
`Please update to Yarn 1.12 or higher for a better, fully supported experience.\n`
)
);
// 1.11 had an issue with webpack-dev-middleware, so better not use PnP with it (never reached stable, but still)
usePnp = false;
}
if (!yarnInfo.hasMaxYarnPnp) {
console.log(
chalk.yellow(
'The --use-pnp flag is no longer necessary with yarn 2 and will be deprecated and removed in a future release.\n'
)
);
// 2 supports PnP by default and breaks when trying to use the flag
usePnp = false;
}
}
}
如果不使用yarn,使用的是npm,需要检查npm的版本,执行的npmInfo
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oAu2zVsb-1658397798506)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ce8d0a6afe1f48f2912cbd3ac9fd1b49~tplv-k3u1fbpfcp-watermark.image?)]](https://i-blog.csdnimg.cn/blog_migrate/fffc3ea185cf2d8a25982749851f2c6d.png)
6. 执行run
run(
root,
appName,
version,
verbose,
originalDirectory,
template,
useYarn,
usePnp
);
至此,创建app函数主要源码完成解读

本文解析了create-react-app创建React应用的核心函数,重点讲解了Node版本检查、项目名称验证和package.json的生成过程。了解如何确保项目在正确环境中搭建并遵循最佳实践。
567

被折叠的 条评论
为什么被折叠?



