从零开始搭建 Vue 脚手架工具(一)

2,564 阅读3分钟

前言

在实际的开发过程中,从零开始建立项目的结构是一件让人头疼的事情,所以各种各样的脚手架工具应运而生。它们功能丰富,但最核心的功能都是能够快速搭建一个完整的项目的结构,开发者只需要在生成的项目结构的基础上进行开发即可,非常简单高效。

接下来就让我们一来看看一个脚手架是如何从0开始搭建的吧。

整体架构

整体架构如下图:

一个模板就是一个项目的样板,包含项目的完整结构和信息。 我们把模板信息都存放在一个文件中scaffold-config-dev.json。 用户通过选择不同模板,通过 axios 下载远程仓库模板到本地,完成项目的搭建

最终整个脚手架的文件结构如下:

=================
├── bin
│   └── ivue-material-cli.js
├── node_modules
├── package.json
└── packages
    └── src
        ├── commander
        │   └── index.js
        ├── lib
        │   └── utils
        │       └── log.js
        └── locals
            ├── index.js
            └── zh_CN
                └── index.js

相关插件

包名称 功能
commander 能够更好地组织和处理命令行的输入
chalk 输出有颜色的命令行
mz 在node中使用 es6

命令行构建

我们先从最简单的步骤开始,-v 输出版本号。

内容文件

首先我们需要知道,-v后命令需要输出什么内容,所以我们在locals目录对输出的内容进行国际化内容的管理,在这里我们一切从简,使用中文内容。

zh_CN->index.js

module.exports = {
    LANG: 'zh_CN',
    SHOW_VERSION: '查看当前版本',
    NO_COMMAND: '命令不存在'
};

然后在locals文件下对内容文件进行管理。

locals->index.js

module.exports = function () {
    let lang = process.env.LANG || 'zh_CN';

    if (/zh/g.test(lang)) {
        return require('./zh_CN');
    }
};

有颜色的命令行

我们知道一个好看的命令好必须要有颜色,接下来我们需要使用chalk来对命令行进行上色。我们在 lib->utils 文件夹下对其进行管理。

/**
 * @file logger
 */

'use strict';

/* eslint-disable */
const chalk = require('chalk');
const util = require('util');

let log = {};

// 管理命令 log 颜色
let logTypes = [
    {
        name: 'info',
        color: chalk.green,
        level: 2
    },
    {
        name: 'error',
        color: chalk.red,
        level: 4
    }
];


logTypes.forEach(function (item) {

    /**
     * 定义打印日志格式
     *
     * @param {string} format 要输出的内容.
     * @param {...*} varArgs 变长参数.
     */
    log[item.name] = function (format, varArgs) {
        // 格式化输出字符串
        let msg = util.format.apply(null, arguments);

        if (msg) {
            console.log((log.prefix || 'IVUE') + ' ' + item.color(item.name.toUpperCase()) + ' ' + msg);
        }
        else {
            console.log();
        }
    };
});

log.chalk = chalk;

module.exports = log;

编写 -v 命令

接下来我们来编写 -v 命令,我们在 commander 文件夹下对命令行进行管理,我们使用 ```commander`` 插件输出命令行因为其能够更好地组织和处理命令行的输入

index.js

// 能够更好地组织和处理命令行的输入
const program = require('commander');
// 内容文件
const locals = require('../locals')();
// 命令行颜色
const log = require('../lib/utils/log');

// 版本号
let version = process.env.VERSION || require('../../../package.json').version;

// 获取输入的命令行
let argv = process.argv[2];

if (argv === '-v' || argv === '--version') {
    log.info('ivue version: ', version);
}

// 定义命令
program
    // 设置/获取命令用法str
    .usage('[commands] [options]')
    // 定义顶级命令的参数语法。
    .arguments('<cmd> [env]')
    // 当使用 --help 时,all 将以这种方式输出。
    // 查看当前版本
    .option('-v, --version', locals.SHOW_VERSION)
    // 注册命令的回调
    .action((cmd, env) => {
        // 输出错误
        if (env) {
            log.error(`\`ivue ${cmd} ${env}\` ${locals.NO_COMMAND}`);
        }
        else {
            log.error('`ivue ' + cmd + '` ' + locals.NO_COMMAND);
        }
    });

// 处理参数
program.parse(process.argv);

执行 -v 后输出如下:

帮助命令 -h

接下来我们来继续构建 -h 帮助命令,修改 commander->index.js 文件

····
// 在node 中使用 es6 语法
const exec = require('mz/child_process').exec;


// 如果后序没有输入命令,执行帮助指令
if (!process.argv[2]) {
    let output = exec('ivue -h');
    console.log(output[0]);
}
// 获取版本号
else {
    let argv = process.argv[2];

    if (argv === '-v' || argv === '--version') {
        log.info('ivue version: ', version);
    }
}

····

最终输出如下:

以上也正是 ivue-cli 脚手架的一部分的源码。

下一篇我们将继续讲解最复杂的功能 init 命令

本文章将一直持续更新到脚手架全部源码的讲解~~~~

如有不对欢迎提出您宝贵的意见

欢迎各位提出 issues 或者 star

github仓库地址:

ivue-cli

webpack模板配置