create-react-app脚手架核心源码之/packages/create-react-app解读(四)

16 篇文章 0 订阅

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?)]

控制台打印如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZxCiOOW-1658397798505)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/91c8566f9dcd4e47a05a4584ee9c742a~tplv-k3u1fbpfcp-watermark.image?)]

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?)]

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?)]

6. 执行run


  run(
    root,
    appName,
    version,
    verbose,
    originalDirectory,
    template,
    useYarn,
    usePnp
  );

至此,创建app函数主要源码完成解读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值