脚手架的工作原理

143 阅读3分钟

脚手架的工作原理

脚手架工具实际上就是一个 node cli 应用,去创建脚手架工具,实际上就是创建一个 cli 应用。

初始化项目

mkdir sample-scaffolding

cd sample-scaffolding

yarn init

指定 cli 应用入口文件

  • package.json 文件中添加 bin 字段,用于指定 cli 应用的入口文件;
{
    "name": "sample-scaffolding",
    "version": "1.0.0",
    "main": "index.js",
    "bin": "cli.js",
    "license": "MIT",
    "author": "syc"
}

编写 cli 入口文件(cli.js)

cli 入口文件必须要有一个特殊的文件头 #!/usr/bin/env node

  • cli 应用的初始化工作
#!/usr/bin/env node

// Node CLI 应用入口文件必须要有这样的文件头
// 如果是 Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755
// 具体就是通过 chmod 755 cli.js 实现修改

console.log('cli working!')
  • 脚手架的工作过程
  1. 通过命令行交互询问用户问题(使用 inquirer 模块):

    • 添加 inquirer 模块
    yarn add inquirer
    
    • 载入 inquirer 模块,然后使用 prompt() 发起命令行询问,并获取用户输入 answers
    #!/usr/bin/env node
    
    // Node CLI 应用入口文件必须要有这样的文件头
    // 如果是 Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755
    // 具体就是通过 chmod 755 cli.js 实现修改
    
    console.log('cli working!')
    
    // 脚手架的工作过程:
    
    // 1. 通过命令行交互询问用户问题(使用 inquirer 模块):
    
    // 1.1. 载入 inquirer 模块;
    const inquirer = require('inquirer')
    
    // 1.1. 使用 prompt() ,发起命令行询问;(prompt() 接收一个问题数组对象)
    inquirer.prompt([{
        type: 'input',
        name: 'name',
        message: 'Project name?'
    }, {
        type: 'input',
        name: 'author',
        message: 'Project author?',
        default: 'syc'
    }]).then(anwsers => { // anwsers 为用户输入的答案的对象:{ name: 'xxx', author: 'xxx' }
        console.log("anwsers: ", anwsers)
    })
    
    • 使用演示

image.png

  1. 根据用户回答的结果生成文件(一般通过模板去生成):

    • 添加模板文件 image.png

    • 编写模板文件

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>
            <%= name %>
        </title>
    </head>
    
    <body>
        <h2>author is:
            <%= author %>
        </h2>
    </body>
    
    </html>
    
    • 获取模板目录
    // 2.1. 载入 path 模块;
    const path = require('path')
    
    // 2.2. 获取模板目录
    const tmplDir = path.join(__dirname, 'templates')
    
    • 获取目标目录
    // 2.3. 获取目标目录
    const destDir = process.cwd()
    
    • 将模板目录下的文件全部转换到目标目录
    // 2.4. 载入 fs 模块;
    const fs = require('fs')
    
    // 2.5 将模板目录下的文件全部转换到目标目录
    fs.readdir(tmplDir, (err, files) => {
        if (err) throw err
    
        // 2.6. 遍历 templates 目录下的文件获取每个 file 其实就是相对于 templates 目录的相对路径
        files.forEach(file => {
            // console.log(file)
        })
    })
    
    • 安装模板引擎
    yarn add ejs
    
    • 通过模板引擎去渲染这个路径所对应的文件
    // 2.7. 载入 ejs 模板引擎;
    const ejs = require('ejs')
    
    // 2.5 将模板目录下的文件全部转换到目标目录
    fs.readdir(tmplDir, (err, files) => {
        if (err) throw err
    
        // 2.6. 遍历 templates 目录下的文件获取每个 file 其实就是相对于 templates 目录的相对路径
        files.forEach(file => {
            // console.log(file)
    
            // 2.8. 通过模板引擎去渲染这个路径所对应的文件
            ejs.renderFile(path.join(tmplDir, file), anwsers, (err, result) => {
                if (err) throw err
    
                // 2.9. 打印出 result 查看,可知结果为渲染成功后的文件的内容
                // console.log(result)
    
                // 2.10. 将结果写入目标目录
                fs.writeFileSync(path.join(destDir, file), result)
            })
        })
    })
    

总结

  • 脚手架工具在创建项目环节大大的提高了效率;