一、为什么需要标准化项目脚手架

每次开始一个新项目,你是不是都要重复这些操作:创建目录、拷贝配置文件、安装相同的依赖?如果团队里有10个人,可能就会产生10种不同的项目结构。这时候,一个统一的脚手架工具就能帮大忙。

想象一下,你只需要运行一个命令,就能自动生成符合公司规范的项目骨架,里面已经预置了正确的目录结构、lint规则、CI配置等。这就是Yarn的create命令配合自定义Generator能实现的效果。

二、Yarn create命令的基本用法

Yarn的create命令其实是个快捷方式,它背后做的是两件事:

  1. 临时安装一个包
  2. 运行这个包的默认执行文件

举个例子,想创建一个React项目时,你会这样用:

yarn create react-app my-project

这等同于:

yarn global add create-react-app
create-react-app my-project

三、开发自己的Generator

3.1 创建一个基础Generator

技术栈:Node.js

我们先来创建一个最简单的Generator:

// generators/app/index.js
const Generator = require('yeoman-generator');

module.exports = class extends Generator {
  // 收集用户输入
  prompting() {
    return this.prompt([{
      type: 'input',
      name: 'projectName',
      message: 'Your project name',
      default: this.appname
    }]).then(answers => {
      this.answers = answers;
    });
  }

  // 写入文件
  writing() {
    // 创建项目目录结构
    this.fs.copyTpl(
      this.templatePath('**/*'),
      this.destinationPath(this.answers.projectName),
      this.answers
    );
  }

  // 安装依赖
  install() {
    process.chdir(this.answers.projectName);
    this.yarnInstall(['lodash'], { 'save-dev': true });
  }
};

3.2 添加模板文件

在templates目录下准备你的项目模板:

templates/
├── .eslintrc.js
├── .gitignore
├── package.json
└── src/
    ├── index.js
    └── utils.js

一个典型的package.json模板可能长这样:

{
  "name": "<%= projectName %>",
  "version": "1.0.0",
  "scripts": {
    "start": "node src/index.js",
    "lint": "eslint src"
  }
}

四、发布和使用自定义Generator

4.1 发布到npm

首先确保package.json配置正确:

{
  "name": "create-my-company-app",
  "version": "1.0.0",
  "files": ["generators"],
  "dependencies": {
    "yeoman-generator": "^5.0.0"
  }
}

然后发布:

npm publish

4.2 团队使用

发布后,团队成员只需要运行:

yarn create my-company-app project-name

就能生成符合规范的项目结构了。

五、高级定制技巧

5.1 根据选项生成不同结构

我们可以在prompting阶段增加选项:

prompting() {
  return this.prompt([{
    type: 'list',
    name: 'projectType',
    message: '项目类型',
    choices: ['Web应用', 'Node服务', '工具库']
  }]).then(answers => {
    this.answers = answers;
  });
}

然后在writing阶段根据选择生成不同文件:

writing() {
  const basePath = this.destinationPath(this.answers.projectName);
  
  // 公共文件
  this.fs.copyTpl(
    this.templatePath('common/**/*'),
    basePath,
    this.answers
  );

  // 根据类型添加特定文件
  if (this.answers.projectType === 'Web应用') {
    this.fs.copyTpl(
      this.templatePath('web/**/*'),
      basePath,
      this.answers
    );
  }
}

5.2 自动配置Git

可以在install阶段后添加:

end() {
  this.spawnCommandSync('git', ['init']);
  this.spawnCommandSync('git', ['add', '.']);
  this.spawnCommandSync('git', ['commit', '-m', 'Initial commit']);
}

六、实际应用场景

  1. 新员工入职:不需要再花时间熟悉项目结构规范,直接使用脚手架生成
  2. 多项目维护:确保所有项目的基本配置保持一致
  3. 技术栈升级:只需更新Generator,所有新项目自动使用最新配置

七、技术优缺点分析

优点

  • 大幅减少重复劳动
  • 统一团队开发规范
  • 新人上手速度快
  • 方便技术栈升级

缺点

  • 初期开发Generator需要投入时间
  • 需要维护Generator版本
  • 对简单项目可能显得太重

八、注意事项

  1. 版本控制:Generator的版本要和项目技术栈版本保持同步
  2. 向后兼容:更新Generator时不要破坏已有项目
  3. 文档完善:要详细说明每个选项的作用
  4. 适度灵活:既要规范,也要给特殊情况留余地

九、总结

通过Yarn create命令配合自定义Generator,我们能够像搭积木一样快速构建符合规范的项目基础。这种方法特别适合需要维护多个相似项目的团队,它能保证项目间的一致性,减少重复劳动,让开发者更专注于业务逻辑而不是项目配置。

虽然搭建这样的工具链需要一些前期投入,但从长期来看,它能显著提高团队效率,降低维护成本。如果你的团队还没有统一的脚手架工具,现在就是开始构建的好时机。