开发react、vue脚手架

前言:

公司前后端分离项目大致有七八个,技术栈包括react、vue。当初搭建项目的时候都是一个一个进行配置、复制、粘贴。
昨天想起来creat-react-app和vue-cli这些官方脚手架用起来很方便,一键生成项目配置,但是和公司项目实际开发还不是很贴切,用官方的生成后还需要进行配置。
如果自己开发一个脚手架工具,模版用公司那一套的话,生成完的项目基本达成90%。
嗯,就这么开始了~

原理

通过用户输入命令来拉取模版项目,生成实际项目
就是把之前配置好的模版项目,通过用户命令拿过来放在本地。
模版可以放在git上通过远程拉去,也可以放在脚手架项目里。
贴一个模版截图

img.jpg

项目结构

按照国际惯例,先贴目录结构图

img.jpg

下载依赖

在package.json中写入依赖,执行npm install

"dependencies": {
        "chalk": "^2.4.2",
        "co": "^4.6.0",
        "co-prompt": "^1.0.0",
        "commander": "^3.0.2",
        "which": "^2.0.1"
}
  • chalk,给终端的字体加颜色
  • co,异步流程控制工具
  • co-prompt,提供提示信息,分步接收用户的输入
  • commander,处理用户输入的命令
  • which,查找指定可执行文件的第一个实例

代码部分

  • 新建bin文件夹、创建cli文件(无后缀)
#!/usr/bin/env node --harmony
"use strict";

process.env.NODE_PATH = __dirname + "/../node_modules/";

const program = require("commander");

program.version(require("../package").version);

program.usage("<command>");
//用户输入init回车后,执行init.js
program
    .command("init")
    .description("Generate a new project")
    .action(() => {
        require("../command/init")();
    });

program.parse(process.argv);

if (!program.args.length) {
    program.help();
}

进入bin目录 cd bin,使用node执行cli文件 node cli,看到以下信息

Usage: cli <command>

Options:
  -V, --version  output the version number
  -h, --help     output usage information

Commands:
  init           Generate a new project
  • 新建command文件夹、创建init.js(处理用户输入的init)
"use strict";
const exec = require("child_process").exec;
const co = require("co");
const prompt = require("co-prompt");
const config = require("../template");
const chalk = require("chalk");
const path = require("path");

module.exports = () => {
    co(function*() {
        //提示用户输入创建的模版类型
        let tplName = yield prompt("Project type (react-p | vue-m): ");
        //提示用户输入项目名称
        let projectName = yield prompt("Project name: ");
        let projectPath = path.resolve(projectName);
        //提示用户创建完项目是否执行npm install
        let yn = yield prompt("Install Package (Y/N)?: ");
        let gitUrl;
        let branch;

        if (!config.tpl[tplName]) {
            console.log(chalk.red("\n × Template does not exit!"));
            process.exit();
        }
        gitUrl = config.tpl[tplName].url;
        branch = config.tpl[tplName].branch;

        //git远程拉取模版并重新命名
        let cmdStr = `git clone ${gitUrl} ${projectName} && cd ${projectName} && git checkout ${branch}`;

        console.log(chalk.white("\n Start..."));

        exec(cmdStr, (error, stdout, stderr) => {
            if (error) {
                console.log(error);
                process.exit();
            }
            //如果输入 y|Y,执行npm install
            if (/^[y|Y]$/.test(yn)) {
                process.chdir(projectPath);
                require("../lib/install");
            } else {
                console.log(chalk.green("\n √ successful!"));
                process.exit();
            }
        });
    });
};
  • 新建template.json(模版信息)
    这两个模版是自己创建的,并不完善,只能当测试项目
{
    "tpl": {
        "vue-m": {
            "url": "https://github.com/smilv/vue-template.git",
            "branch": "master"
        },
        "react-p": {
            "url": "https://github.com/smilv/react-template.git",
            "branch": "master"
        }
    }
}
  • 新建lib文件夹、创建install.js(执行npm install)
const which = require("which");
const chalk = require("chalk");
const childProcess = require("child_process");

function runCmd(cmd, args, fn) {
    args = args || [];
    let runner = childProcess.spawn(cmd, args, {
        stdio: "inherit"
    });

    runner.on("close", function(code) {
        if (fn) {
            fn(code);
        }
    });
}

function findNpm() {
    let npms = ["cnpm", "npm"];
    for (let i = 0; i < npms.length; i++) {
        try {
            which.sync(npms[i]);
            console.log("\n " + npms[i] + " install...");
            return npms[i];
        } catch (e) {}
    }
    throw new Error(chalk.red("please install npm"));
}

let npm = findNpm();
runCmd(which.sync(npm), ["install"], function() {
    console.log(" " + npm + " install end");
    console.log(chalk.green("\n √ successful!"));
    process.exit();
});

运行使用

在package.json中添加

"bin": {
        "smilv-cli": "bin/cli"
},

本地测试时把smilv-cli绑定到全局,在根目录下执行

npm link

另找一个空目录进行测试,执行

smilv-cli init

根据提示输入选择的模版、项目名称、是否需要执行npm install,回车

E:\personal-code>smilv-cli init
Project type (react-p | vue-m): vue-m
Project name: my-app
Install Package (Y/N)?: n

 Start...

 √ successful!

E:\personal-code>

测试完成。
如何发布到npm就不多说啦~

后记

完整代码地址 https://github.com/smilv/smilv-cli

后会有期。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352