简单实现一个脚手架

194 阅读2分钟

前言

启动新项目时需要通常会根据我们的业务需求创建一些基本的公共文件和配置,这些都是繁琐的工作,每次创建都需要去修改。通过类似 vue create your-project 或者 create-react-app your-project 这样的脚手架一键创建基本目录结构和配置,从而告别 Ctrl + CCtrl + V

目的

带你简单了解下一个CLI的实现

步骤

创建 npm 项目

// 创建脚手架目录
mkdir my-scaffold

// 进入目录
cd my-scaffold

// 初始化项目
npm init

修改 package.json 文件

设置 bin 字段,此字段为 CLI 的入口文件

{
  "name": "my-scaffold",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "bin": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

在 package.json 文件的同级目录下创建 main.js 文件

#!/usr/bin/env node

// 1.第一行固定写法,必须要有,否则 node 无法识别
// 2.安装 inquirer 实现问答效果
// 3.通过 prompt 添加问题,搜集用户信息
// 4.then 中的 回调信息 answers 即为上下文
// 5.通过 fs.readdir 来读取文件夹信息
// 6.通过 ejs 来解析模板,并且设置模板中的变量
// 7.通过 fs.writeFileSync 来写入文件

const path = require('path')
const fs = require('fs')
const inquirer = require('inquirer')
const ejs = require('ejs')

inquirer
  .prompt([
    {
      type: 'input',
      name: 'name',
      message: 'Your project name?',
      default: this.appname
    },
    {
      type: 'input',
      name: 'description',
      message: 'Your project description?'
    }
  ])
  .then(answers => {
    console.log(answers)
    // 模板目录,templates 目录为我们需要的模板目录
    const tmplDir = path.join(__dirname, 'templates')
    // 目标目录
    const destDir = process.cwd()

    // 读取文件夹内容
    fs.readdir(tmplDir, (err, files) => {
      if (err) throw err
      files.forEach(file => {
        // 使用 ejs 解析模板
        ejs.renderFile(path.join(tmplDir, file), answers, (e, result) => {
          if (e) throw e
          // 创建文件
          fs.writeFileSync(path.join(destDir, file), result)
        })
      })
    })
  })

此处使用到了 inquirerejs 两个库。
inquirer: 实现和用户交互。
ejs: 动态修改模板中的相关信息。

创建 templates 模板目录

创建一个 test.txt 文件

test
<%= name %>

将当前脚手架链接到全局中去

// 使用 npm link 将脚手架链接到全局
npm link

使用脚手架

新建一个项目,直接在新项目的终端中输入 my-scaffold
这样就会把你的脚手架中的模板文件生成在新项目中。