脚手架核心流程开发

标准

绘制 imooc-cli 脚手架架构设计图

实现 imooc-cli 脚手架准备过程代码

try {
    checkPkgVersion()
    checkNodeVersion()
    checkRoot()
    checkUserHome()
    checkInputArgs()
    checkEnv()
    await checkGlobalUpdate()
} catch(error) {
    log.error(error.message)
}

// 检查是否需要全局更新
async function checkGlobalUpdate() {
    const currentVersion = pkg.version
    const npmName = pkg.name
    const lastVersions = await getNpmSemverVersions(npmName, currentVersion)
    if(lastVersions && semver.gt(lastVersions, currentVersion)) {
        log.warn('更新提示', colors.yellow(
            dedent`
                请更新 ${npmName}
                当前版本: ${currentVersion}
                最新版本: ${lastVersions}
                更新命令: npm install -g ${npmName}@${lastVersions}
            `))
    }
}

// 环境变量检查
function checkEnv() {
    const dotenv = require('dotenv')
    const dotenvPath = path.resolve(userHome, '.env')
    if(pathExists(dotenvPath)) {
        config = dotenv.config({
            path: dotenvPath
        })
    }

    createDefaultConfig()

    log.verbose('环境变量:', process.env.CLI_HOME_PATH)
}

// 创建默认的环境变量配置
function createDefaultConfig() {
    const cliConfig = {
        home: userHome
    }

    process.env.CLI_HOME_PATH = cliConfig['cliHome'] = process.env.CLI_HOME
        ? path.join(userHome, process.env.CLI_HOME)
        : path.join(userHome, constant.DEFAULT_CLI_HOME)
}

// 入参检查
function checkInputArgs() {
    args = require('minimist')(process.argv.slice(2))
    checkArgs(args)
}

// debug 模式判断
function checkArgs(args) {
    log.level = process.env.LOG_LEVEL = args.debug
        ? 'verbose'
        : 'info'
}

// 检查 用户主目录
function checkUserHome() {
    if(!userHome || !pathExists(userHome)) {
        throw new Error(colors.red('当前登陆用户主目录不存在'))
    }
}

// 检查登陆帐号的级别 以及 降级
function checkRoot() {
    require('root-check')()
}

// 检查 node 的版本
function checkNodeVersion() {
    const currentNodeVersion = process.version
    const lowestNodeVersion = constant.LOWEST_NODE_VERSION
    if(!semver.gte(currentNodeVersion, lowestNodeVersion)) {
        throw new Error(colors.red(`weilai-cli 需要安装 v${lowestNodeVersion} 以上版本的 Node.js`))
    }
    log.notice('node', process.version)
}

// 检查 package 的版本
function checkPkgVersion() {
    log.notice('cli', pkg.version)
}

通过 commander 框架实现一个脚手架,包含自定义 option 和 command 功能

#! /usr/bin/env node

const commander = require('commander')

const pkg = require('../package.json')

// 获取 commander 的单例
// const { program } = commander

// 手动实例化一个 commander 实例
const program = new commander.Command()

program
    .name(Object.keys(pkg.bin)[0])
    .usage('<command> [options]')
    .version(pkg.version)
    .option('-d, --debug', '是否开启调试模式', false)
    .option('-e, --env <envName>', '获取环境变量名称', false)

// command 注册命令
program
    .command('clone <source> [destination]')
    .description('clone a repository')
    .option('-f, --force', '是否强制拷贝')
    .action((source, destination, cmdObj) => {
        console.log('do clone', source, destination, cmdObj.force)
    })


// addCommand 注册子命令
const service = new commander.Command('service')
service
    .command('start [port]')
    .description('start service at some port')
    .action((prot, cmdObj) => {
        console.log('do server start', prot)
    })
service
    .command('stop')
    .description('stop service')
    .action(() => {
        console.log('do server stop')
    })


program.addCommand(service)

// program
//     .command('install [name]', 'install package', {
//         executableFile: 'weilai-cli',
//         // isDefault: true,
//         // hidden: true
//     })
//     .alias('i')


// 高级定制:自定义help信息
// console.log(program.outputHelp())
// console.log(program.helpInformation())
program.helpInformation = () => ''
program.on('--help', () => {
    console.log('your help information')
})

program.on('option:debug', () => {
    console.log('debug')
})

program.on('command:*', (obj) => {
    console.log('未知的命令', obj)
    const availableCommands = program.commands.map(cmd => cmd.name())
    console.log('可用的命令', availableCommands)
})


// program
//     .arguments('<cmd> [options]')
//     .description('test command', {
//         cmd: 'command to run',
//         options: 'options for command'
//     })
//     .action((cmd, options) => {
//         console.log(cmd, 'arguments')
//     })

program    
    .parse(process.argv)

// console.log(program.debug)
// console.log(program.env)
// console.log(program.opts())

进阶

通过 webpack 和 原生两种方式实现 node 对 ES Module 的支持

  1. 通过配置 webpack 来实现模块化(ES Module),并且 使用 babel 进行编译,来兼容低版本的 node
  2. 设置文件后缀名为 xxx.mjs , node 版本小于 14 需要加上 --experimental-modules 来对 mjs 进行支持
Copyright © imooc-lego (2020 - present) all right reserved,powered by GitbookFile Modify: 2021-06-27 08:04:57

results matching ""

    No results matching ""