还记得我们在写 vue 项目的时候用脚手架 vue-init 的主要作用是根据指定模板生成项目原型嘛? 那么 vue-init 怎么实现的呢? 其实就是在 vue-cli package.json 中增加下面的代码
- {
- "bin": {
- "vue": "bin/vue",
- "vue-init": "bin/vue-init", // 执行 vue-init 的时候下载项目原型
- "vue-list": "bin/vue-list",
- "vue-build": "bin/vue-build"
- }
- }
复制代码
具体实现请看下面:
本篇的主要内容是: 实现可以在命令行中, 直接运行代码 (下面的名字可以自己取).
xl-cli install (安装)
复制代码
在实现自己的命令行运行代码前, 你需要对命令行, npm(包管理器) 的基本用法有些了解. 下面进入正题:
- // 创建一个 xl-cli 文件夹 mkdir xl-cli
- // cd xl-cli
- // npm init 初始化
复制代码
完成上面几个步骤之后 我们能看到生成了一个 xl-cli 文件夹 文件中包含一个 package.json 文件.
- {
- "name": "xl-cli",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\"&& exit 1"
- },
- "author": "",
- "license": "ISC"
- }
复制代码
我们知道在 npm run xxx 的时候其实就是执行的 package.json 中的 scripts, 比如上面 你看看 npm run test 就会输出 Error: no test specified, 我们的代码用的 es6 需要编译成 es5, 先创建一个 npm run compile,(test 没用, 同时给 test 删掉)
- {
- "name": "xl-cli",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "compile": "babel src -d dist"
- },
- "author": "",
- "license": "ISC"
- }
复制代码
我们需要安装 babel 创建 (安装 babel-cli babel-env)
- src
- --main.js
复制代码
这个时候我们执行 npm run compile 其实就是相当于在命令行中输入了 babel src -d dist 然后我们看到了生成了一个这样的目录:
- dist
- --main.js
复制代码
我们经常会有这样的需求就是在更改 src 里面的内容的时候 同步更改 dist 里面的内容, 可以这样做: 在 package.json 的 scripts 增加一个 watch 命令:
- {
- "name": "xl-cli",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "compile": "babel src -d dist",
- "watch":"npm run compile -- --watch"
- },
- "author": "",
- "license": "ISC"
- }
复制代码
然后运行 npm run watch 命令 就实现了同步更新了!
下面实现 xl-cli 命令行
创建 ./bin/www 目录, 要实现在命令行中使用 类似 vue-cli 这样的命令 需要在 package.json 中增加
- "bin": {
- "xl-cli": "./bin/www"
- },
复制代码
./bin/www 中的内容:
- #! /usr/bin/env node
- require('../dist/main.js');
复制代码
第一行 最后的 node 是表示 node 环境 前面参数写死的, 第二行表示执行的代码 , 创建完成后执行 npm link, 相当于在本地添加环境变量. 至此, 你已经可以执行 xl-cli 命令了, 其实就是执行了 dist/main.js.
实现像其他命令行中的 xl-cli --help 先引入一个包 commander , 这个包可以帮助我们设置和解析命令参数. src/main.js
- //main.js
- import program from 'commander';
- import {VERSION} from './utils/constants';
- program.command('install') // 加命令
- .description('install template')
- .alias('i')
- .action(() => {
- console.log('用户 install 了')
- })
- program.version(VERSION,'-v --version').parse(process.argv); // 加 option
复制代码
我们可以看到在命令窗口输入 xl-cli install 会打印出:
用户 install 了
复制代码
好了 到现在我们就剩下执行下载模板任务了, 这样我们新建一个 install.js 来执行下载任务
- //install.js
- import ora from 'ora'; //ora 一个命令行 loading 效果
- import inquirer from 'inquirer' // 命令行交互
- import downLoadGit from 'download-git-repo'; //github api 用来下载 github 的模板
- let install = async () => {
- // 下载模板
- let loading = ora('fetching template......');
- let answer = await inquirer.prompt([
- {
- type: 'input', // 你可以输入你自己的名称
- name: 'projectName',
- message:'项目名称',
- default:'xlDemo' // 默认名
- }
- ]);
- // 项目名字
- let project = answer.projectName;
- loading.start();
- // 我在 github 上面上传了一个非常简单的模板 xlei1123/xl-cli downLoadGit(src, dest) 从哪拉 拉到那 process.cwd()+'/'+project 这是拉到了当前目录下的你刚刚命名的文件中
- downLoadGit('xlei1123/xl-cli',process.cwd()+'/'+project,(err) => {
- if(err) {
- console.log(err)
- return;
- }
- console.log(process.cwd()+'/'+project)
- loading.succeed();
- });
- }
- export default install;
复制代码
这样在上面的 action 中执行 install() 就好了!
- //main.js
- import program from 'commander';
- import {VERSION} from './utils/constants';
- import install from './install'
- program.command('install') // 加命令
- .description('install template')
- .alias('i')
- .action(() => {
- install()
- })
- program.version(VERSION,'-v --version').parse(process.argv); // 加 option
复制代码
这样我们就完成了自己 cli 了, 可以执行下面几个简单的命令看一下效果:
- xl-cli --help
- xl-cli -v
- xl-cli install
复制代码
一句话总结: 我们发布了一个 npm 包 这个包的 package.json 中有 bin 可以全局执行, 判断参数有 install, 就从 github 上面拉取模板.
当然这篇实现的是简单的命令行工具主要是理解其中大致原理, 肯定会存在很多不足的地方, 欢迎各位提出宝贵的意见或建议, 也希望能帮助到你从中获得一些知识!
来源: https://juejin.im/post/5b4168bf6fb9a04f83462f6c