前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >搭建自己的脚手架

搭建自己的脚手架

原创
作者头像
暂七师黑管手
发布2019-07-31 20:18:52
1.1K0
发布2019-07-31 20:18:52
举报
文章被收录于专栏:进击的全栈进击的全栈

工欲善其事,必先利其器

最近接手了一个内部配置运营平台,大概了解了代码结构之后,第一波优化就是搭建了一套脚手架。

对于多人协作开发的 SPA 项目,一个方便的脚手架能够带来很大的便利:

  1. 脚手架能够规范化项目结构,对于项目整体优化和维护有着重要的意义;
  2. 通过脚手架生成代码能够避免开发者相互拷贝,导致缺陷在代码中的扩散;
  3. 减少重复劳动,降低开发门槛。

不难发现,社区优秀的开源框架往往都会提供一套脚手架供开发者快速上手,比如create-react-appvue-cli等。接下来我们就尝试使用yeoman来快速搭建一套自己的脚手架。

安装脚手架脚手架

yeoman,是一套脚手架生成工具。首先我们全局安装一下 yeoman 的 cli。

代码语言:txt
复制
npm install -g yo

接下来,我们通过“脚手架的脚手架”来快速搭建我们自己的脚手架。

代码语言:txt
复制
# Install:
npm install -g generator-generator
# Run:
yo generator

按照提示输入一堆问题之后,我们会得到如下的一个目录结构:

代码语言:txt
复制
|- __tests__ # 测试代码
    |- app.js # app测试代码
|- generators # 脚手架目录
    |- app # 默认脚手架
        |- index.js # 入口
        |- templates # 模板文件夹
            |- ... # 各种模板文件
|- package.json

脚手架的生命周期

generators/app/index.js中,我们需要编写脚手架的主要逻辑,大概的代码结构是这样的:

代码语言:txt
复制
"use strict";
const Generator = require("yeoman-generator");
const chalk = require("chalk");
const mkdirp = require("mkdirp");
const yosay = require("yosay");
const _ = require("lodash");

module.exports = class extends Generator {
  constructor(args, opts) {
    super(args, opts);
    this.displayName = "NewPage";
    this.entry = "newPage";
  }

  initializing() {}

  async prompting() {
    const done = this.async();

    const prompts = [
      {
        type: "input",
        name: "displayName",
        message: "请输入页面名称",
        default: this.displayName
      }
    ];

    this.log(
      yosay(`Welcome to the neat ${chalk.red("generator-***")} generator!`)
    );
    const answers = await this.prompt(prompts);

    this.displayName = _.upperFirst(answers.displayName);
    this.entry = _.camelCase(answers.displayName);

    done();
  }

  writing() {
    const pagePath = "./src/app/" + this.entry + "/";
    const done = this.async();

    mkdirp(this.destinationPath(pagePath), () => {
      ["index.js"].forEach(filename => {
        this.fs.copyTpl(
          this.templatePath(filename),
          this.destinationPath(pagePath + filename),
          {
            displayName: this.displayName,
            entry: this.entry
          }
        );
      });

      this.log(chalk.green(this.entry + "已经生成!"));
      done();
    });
  }

  end() {
    this.log(chalk.green("done"));
  }
};

其中initializingpromptingwritingend就属于生命周期函数,各个生命周期函数和使用场景如下:

1. initializing

初始化方法,一些初始化操作,或者检查脚手架状态等

2. prompting

与用户交互,让用户输入配置,一般在这里运行this.prompt()

3. configuring

为项目创建配置文件

4. default

默认分组,其他自定义方法会在这一步骤依次运行

5. writing

生成代码,一般会从templates进行读取文件

6. conflicts

处理冲突

7. install

安装阶段,比如让项目执行npm install命令

8. end

结束阶段,清理并返回生成结果


脚手架中的方法会按照这个顺序执行,如果你有一些私有方法不希望被自动执行,需要采用一定的技巧,比如:

在方法前增加下划线,标识为私有方法;

代码语言:txt
复制
_privateMethod () {
    this.log('This is a private method.);
}

在构造函数中实现方法;

代码语言:txt
复制
constructor(args, opts) {
    super(args, opts);
    this.privateMethod = function () {
        this.log('This is a private method.);
    }
}

测试和发布

创建脚手架时,我们可以选择生成测试代码,这里默认会使用jest来进行测试。

简单的测试代码如下:

代码语言:txt
复制
"use strict";
const path = require("path");
const assert = require("yeoman-assert");
const helpers = require("yeoman-test");

describe("generator-***:app", () => {
  beforeAll(() => {
    return helpers.run(path.join(__dirname, "../generators/app")).withPrompts({
      displayName: "TestPage"
    });
  });

  it("creates files", () => {
    assert.file(["src/app/testPage/index.js"]);
  });
});

yeoman为我们提供了测试工具,helpers.run()就可以在沙箱中运行脚手架,并且可以通过withPrompts()方法来指定prompting阶段的各个参数。

在测试中,常用的检查方法有assert.fileassert.fileContentassert.noFileassert.noFileContent等。它们分别代表“文件应当存在”、“文件应当存在内容***”、“文件不应该存在”、“文件不应该存在内容***”。

开发好的脚手架可以上传npm,这样就可以供其他人使用,或者你也可以在目录下运行npm link命令,将本地脚手架添加到本地npm链接中。

之后就可以使用命令行来运行脚手架了:

代码语言:txt
复制
yo ***
# ***是脚手架的名字,比如generator-abc, 就可以通过 yo abc 来运行

一些小技巧

在运行脚手架时,我们希望始终使用的是最新版本的脚手架,如果你的脚手架存放在npm,可以通过以下方法进行验证:

代码语言:txt
复制
const pkg = require("../../package.json");

const remoteVersion = execSync("npm view generator-*** version")
  .toString()
  .trim();
const localVersion = pkg.version;

可以使用npm命令来进行版本升级,首先将代码的改动commit到git仓库,之后根据此次更新的程度,来使用不同的命令:

代码语言:txt
复制
npm version patch # bug修复
npm version minor # 增加了新的feature,并且是一个兼容性更新
npm version major # 增加了新的feature,并且存在不兼容问题的更新

如果希望每次修改脚手架时都能自动进行测试和发布 npm,这里就需要 CI 工具的帮忙,能够极大地提高开发效率和体验。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 安装脚手架脚手架
  • 脚手架的生命周期
    • 1. initializing
      • 2. prompting
        • 3. configuring
          • 4. default
            • 5. writing
              • 6. conflicts
                • 7. install
                  • 8. end
                  • 测试和发布
                  • 一些小技巧
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档