自己动手做一个React脚手架(一)

1,916 阅读3分钟

前言

最近和室友商量着想写一个自己的开源项目,想到了自己在工作中惯用的项目结构,惯用的库,在新开项目的时候总是要修改配置一番,挺麻烦的。于是觉得自己做个脚手架玩一玩。

已实现的功能

目前第一版实现的功能非常简单。仅仅是输入项目名称,生成固定的项目结构,安装依赖可以运行起来。欢迎大家试玩。 项目名: henri-create-app
项目git地址
npm包地址

实现原理

概括一下说,就是将一个编写好的完整的项目目录复制到新建项目目录里面,然后就可以安装依赖并运行了。下面为大家讲解一下主要实现步骤,带领大家做一个自己的脚手架。当然还是更希望大家能加入我的项目,一起完善henri-create-app。

package.json

包中通过bin字段指定命令名称要执行的代码入口
依赖的包和用处:
glob: 匹配查找指定的文件或目录 path: 处理路径 yargs-parser: 获取命令行输入参数
yeomen-generator: 生成器

获取用户输入的项目名

进入./bin/index.js,通过以下代码获取用户输入的项目名参数

const args = yParser(process.argv.slice(2));
const name = args._[0];

node中使用process.argv接收用户输入的参数,这里稍加处理,获取到项目名。即henri-create-app后面输入的字符串。

创建项目的根目录

mkdirp.sync(name);
let cwd = process.cwd();
cwd = path.join(cwd, name);

上述代码,创建了一个名为name的目录。然后通过process.cwd()获取当前工作目录,再通过path获取到刚创建的项目目录。

复制模板文件

通过yeoman-generator复制文件到项目目录。这是一个专门的用来创建项目的库。这里只是简单地用来复制文件,其他更多强大功能等待你去探索。

const generator = new Generator({
  name,
  env: { cwd },
  resolved: require.resolve('../lib/generators'),
  args
});
generator.run(() => {
  console.log(chalk.green('创建成功!'));
});

创建了一个生成器对象,并执行它。
再来到../lib/generators,看看生成器是如何定义的。

class extends Generator {
  constructor(opts) {
    super(opts);
    this.name = basename(opts.env.cwd);
  }

  writing() {
    glob
      .sync('**/*', {
        cwd: this.templatePath(),
        dot: true
      })
      .forEach(file => {
        const filePath = this.templatePath(file);
        if (statSync(filePath).isFile()) {
          this.fs.copyTpl(
            this.templatePath(filePath),
            this.destinationPath(file.replace(/^_/, '.')),
            { name: this.name }
          );
        }
      });
  }
};

这里通过继承yeoman的Generator对象,实现一个自己的生成器。 构造函数中定义了一个项目名变量。 重写了writing方法,这是执行run时会调用到的。
writing中只做了一件事,读取templates文件夹下的所有文件或文件夹,输出到项目目录中。
注意到{ name: this.name }代码,这是fs.copyTpl方法传入的context对象,模板中通过<%= name %>引用到此变量。大家可以自己去查看一下templates里面的源码。

结语

粗略地描述了一下实现过程,大家有什么不明白的地方,欢迎提问。我有什么表述错误或不准确的也欢迎指正哦。后期还计划实现更多有趣功能,感兴趣的小伙伴欢迎加入~