前言
经常写 vue 项目的小伙伴应该都有这种经历:
vue create hello-world
选择各种
preset
cd hello-world
npm install
npm run serve
安装各种周边
npm i vuex
npm i vue-router
npm i ...
...
每新开一个项目就得按照这些步骤跑一遍,还要经常因为版本的问题,导致一些奇奇怪怪的 bugs 出现。
so,能不能把基本都会使用的周边给弄成一个模板,然后每次新开项目的时候直接采用类似 copy 的形式来开发呢?
正文
认识 vue-cli
找到 vue-cli
核心的代码:
vue-cli/packages/@vue/cli/bin/vue.js
可以发现,其实就是根据命令行交互得到的参数,然后生成对应的项目。
以 create
命令为例:
program
.command("create <app-name>")
.description("create a new project powered by vue-cli-service")
.option(
"-p, --preset <presetName>",
"Skip prompts and use saved or remote preset"
)
.option("-d, --default", "Skip prompts and use default preset")
.option(
"-i, --inlinePreset <json>",
"Skip prompts and use inline JSON string as preset"
)
.option(
"-m, --packageManager <command>",
"Use specified npm client when installing dependencies"
)
.option(
"-r, --registry <url>",
"Use specified npm registry when installing dependencies (only for npm)"
)
.option(
"-g, --git [message]",
"Force git initialization with initial commit message"
)
.option("-n, --no-git", "Skip git initialization")
.option("-f, --force", "Overwrite target directory if it exists")
.option("--merge", "Merge target directory if it exists")
.option("-c, --clone", "Use git clone when fetching remote preset")
.option("-x, --proxy <proxyUrl>", "Use specified proxy when creating project")
.option("-b, --bare", "Scaffold project without beginner instructions")
.option("--skipGetStarted", 'Skip displaying "Get started" instructions')
.action((name, options) => {
if (minimist(process.argv.slice(3))._.length > 1) {
console.log(
chalk.yellow(
"\n Info: You provided more than one argument. The first one will be used as the app's name, the rest are ignored."
)
);
}
// --git makes commander to default git to true
if (process.argv.includes("-g") || process.argv.includes("--git")) {
options.forceGit = true;
}
require("../lib/create")(name, options);
});
其实就是输入完 project name 之后 执行 require('../lib/create')(name, options)
里面的方法:
vue-cli/packages/@vue/cli/lib/Creator.js
思路
参考 vue-cli
的实现方式,我们可以实现一个适用于自己的 cli,提前编写好项目模板,只需要输入简单的交互指令,就可以生成属于我们自己的项目内容。
具体实现
准备好项目模板
const TPLS = {
v3: {
url: "github:Realzzz1874/v3-tpl#fvue-tpl/v3",
desc: "v3-tpl",
repo: "https://github.com/Realzzz1874/v3-tpl/tree/fvue-tpl/v3",
},
};
安装脚手架所需要的依赖包
"dependencies": {
"chalk": "^5.0.1",
"commander": "^9.4.0",
"download-git-repo": "^3.0.2",
"handlebars": "^4.7.7",
"inquirer": "^9.1.0",
"log-symbols": "^5.1.0",
"ora": "^6.1.2"
}
开始干吧!
#!/usr/bin/env node
import fs from "fs";
import { program } from "commander";
import download from "download-git-repo";
import inquirer from "inquirer";
import handlebars from "handlebars";
import ora from "ora";
import chalk from "chalk";
import logSymbols from "log-symbols";
const log = chalk.hex("##1DBD21");
console.log(log("fvue: A fast vue project cli!"));
const TPLS = {
v3: {
url: "github:Realzzz1874/v3-tpl#fvue-tpl/v3",
desc: "v3-tpl",
repo: "https://github.com/Realzzz1874/v3-tpl/tree/fvue-tpl/v3",
},
};
program.version("1.0.0");
program
.command("init <tpl> <proj>")
.description("init tpl")
.action((tpl_name, proj_name) => {
const { url, repo } = TPLS[tpl_name];
console.log(`github repo: ${repo}`);
const tpl_loading = ora("tpl downloading...");
tpl_loading.start();
download(
url,
proj_name,
{
clone: true,
},
(err) => {
if (err) {
tpl_loading.fail();
console.log(logSymbols.error, chalk.red("tpl download fail."));
} else {
tpl_loading.succeed("tpl download success.");
const log = chalk.hex("#FFA500");
console.log(logSymbols.success, log("tpl init success."));
inquirer
.prompt([
{
type: "input",
name: "name",
message: "please input proj name:",
},
{
type: "input",
name: "description",
message: "please input proj description:",
},
{
type: "input",
name: "author",
message: "please input proj author:",
},
])
.then(async (answers) => {
const package_path = `${proj_name}/package.json`;
const package_content = fs.readFileSync(package_path, "utf-8");
const package_result = await handlebars.compile(package_content)(
answers
);
fs.writeFileSync(package_path, package_result);
const log = chalk.hex("#FFA500");
console.log(logSymbols.success, log("proj init success."));
});
}
}
);
});
program
.command("list")
.description("tpl list")
.action(() => {
for (let key in TPLS) {
console.log(` - ${key} (${TPLS[key].desc})`);
}
});
program.parse(process.argv);
使用方法
list
fvue list
fvue: A fast vue project cli!
- v3 (v3-tpl)
init
fvue init <tpl> <proj>
just like:
fvue init v3 myVueProject
fvue: A fast vue project cli!
github repo: https://github.com/Realzzz1874/v3-tpl/tree/fvue-tpl/v3
✔ tpl download success.
✔ tpl init success.
? please input proj name: myVueProject
? please input proj description: my fast vue project
? please input proj author: realzzz
✔ proj init success.
结语
文中的脚手架工具已经发布到 npm,可以直接安装使用
npm i vuefast -g
# OR
yarn add vuefast -g
安装之后,可以直接使用 fvue
命令:
# list
fvue list
#init
fvue init <tpl> <proj>