开发react、vue脚手架

前言:

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

原理

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

开发react、vue脚手架_第1张图片
img.jpg

项目结构

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

开发react、vue脚手架_第2张图片
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("");
//用户输入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 

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

后会有期。

你可能感兴趣的:(开发react、vue脚手架)