从0到1实现前端自定义脚手架

效果展示

  • 使用commander命令式效果

 

  • 使用inquirer交互式效果

初始化操作

使用 npm init -y 命令快速生成 package.json 文件
设置上 name 和 main 的值
需要加上bin的配置项,否则可能会执行全局命令无效,bin 字段:可以自定义脚手架工具的命令,例如下面的 mycli ,而 mycli 后面的就是命令的执行脚本。

{
  "name": "mycli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "bin": {
    "mycli": "bin/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

创建 index.js 文件,输入内容 #!/usr/bin/env node 指定以node环境运行

#!/usr/bin/env node
#!/usr/bin/env node console.log('hello mycli!')

使用 npm link 命令创建全局module,会在全局node变量下自动生成文件 /node_modules/mycli/index.js,就可以在本地对脚手架工具进行调试了

安装依赖 npm install chalk shelljs inquirer --save

  • chalk:是一个node输出log的样式库
  • shelljs:见名知义是执行shell命令的库
  • inquirer:交互式命令库

目录结构

- mycli 
    - node_modules 
    - template 
        - vue 
            - vue.html 
        - h5 
            - h5.html
        ...
    - createProject.js 
    - index.js 
    - package.json
  • node_modules:脚手架所需要依赖
  • template:该目录下存放的是cli需要的模板, 用户使用脚手架生成的最终项目就是从这里copy出去的
  • createProject.js:拉去项目的代码都在这里
  • index.js:脚手架入口文件
  • package.json:对项目及模块的描述

具体代码

index.js

    #!/usr/bin/env node
    let program = require('commander')
    let createProject = require('./createProject')

    // 设置版本号和参数,通过 mycli --help 查看
    program.version('1.0.0')
        .option('-t, --type <name>', 'project type')
        .option('-n, --type <name>', 'project type')

    // 捕获命令和参数 eg: mycli create test -t vue
    program
        .command('create <name>')
        .action(function(name) {
            createProject(name, program.type)
        })

    program.parse(process.argv)

createProject.js

  let chalk = require('chalk'); // node终端样式库
    let fs = require('fs');
    let path = require('path');
    let inquirer = require('inquirer');

    require('shelljs/global'); // 执行shell脚本

    let log = function(txt) {
        console.log(chalk.green.bold(txt))
    }

    async function createProject(name, type) {
        let p = process.cwd() // 获取当前路径
        cd(p) // shell cd

        // 检测是否存在文件夹, 如果存在,是否需要删除后安装
        if(fs.existsSync(name)) {
            log('project exists, please rename it');
            var questions = [
                {
                type: 'confirm',
                name: 'isRemoveDir',
                message: `delete ${name} ?`,
                default: false,
                }
            ]

            const answer = await inquirer.prompt(questions).then((answers) => {
                return answers
            });

            if(!answer.isRemoveDir) {
                process.exit();
            }
            rm('-rf', name); // shell rm 
            log(`delete ${name} success`)
        }

        let np = path.join(__dirname, 'template', type);
        cp('-R', np+'/', name) // shell cp
        log(`拉取 '${type}' 项目成功!`)
        
        cd(name) // shell cd
        log('设置淘宝镜像源 --- npm config set registry http://registry.npm.taobao.org')
        exec('npm config set registry http://registry.npm.taobao.org') // 执行自定义的shell命令 npm config set registry http://registry.npm.taobao.org
        log('安装模块 --- npm install')
        log('安装模块中...')
        log('安装耗时可能会很长,请耐心等待,您也可以通过 ctrl+c停止安装, 手动 npm install')
        exec('npm install') // 执行自定义的shell命令 npm install

        // 这里的逻辑是自定义的,根据需求自己完成
        if(type != 'jquery') {
            log('正在启动项目')
            exec('npm start') // 执行自定义的shell命令 npm start
        }

        log('脚手架初始化完成')
        process.exit() 

    }

    module.exports = createProject

使用方式

mycli --help: --help是commander自带的命令, 可以输出脚手架的命令
mycli create demo -t vue: 这是我们自定义的命令, 创建一个demo文件夹,以vue作为模板

项目改造

使用commander命令操作太过繁琐,并且记不住参数,我们使用inquirer改造成彻底的交互式脚手架

-   修改 index.js

  #!/usr/bin/env node
    const createProject = require('./createProject')
    const inquirer = require('inquirer');
    const fs = require('fs');
    const path = require('path');

    const promptList = [
        {
            type: 'input',
            message: '请输入项目名',
            name: 'name',
            default: 'my-project',
        },
        {
            type: 'list',
            message: '请选择项目类型',
            name: 'type',
            choices: fs.readdirSync(path.join(__dirname,'template')) // 通过fs模块读取tempate目录下的目录列表
        }
    ]

    inquirer.prompt(promptList).then((answers) => {
        createProject(answers.name, answers.type)
    });

启动命令 `mycli`, 不用记住繁琐的参数选项,直接通过提示进行操作

总结

自定义脚手架依靠node环境,通过node提供的fs模块,进行文件操作。npm上也提供了各类的命令库(commander , shelljs )和交互式的库(inquirer), 为我们提供了便利,我们主要进行操作就是提供我们自己的脚手架模板。
 

猜你喜欢

转载自blog.csdn.net/qq_45503196/article/details/121576329