文章目录
- 思路
- 一、步骤
- 1.新建项目
- 2.项目初始化
- 3.脚本映射为命令
- 3.1.配置在package.json
- 3.2.命令链接到全局
- 4.命令行工具参数设计
- 5. 使用commander 模块处理 命令行
- 5. 准备模板
- 6. 设置命令行交互
- 7. 本项目发布到npm
- 遇到的问题
- 1. 报以下信息:
思路
- 项目模板放在GitHub上面
- 用户通过命令交互的方式下载不同的模板(类似 npm install)
- 经过模板引擎渲染定制项目模板
- 模板变动,只需要更新模板即可,不需要用户更新脚手架
一、步骤
1.新建项目
一般脚手架命名格式:xxx-cli
mkdir 项目名称
其实就是新建一个文件夹,再新建一个文件,命名为index.js
.并写入以下内容:
//index.js
#!/usr/bin/env node
console.log("脚手架工具")
注意
😕 使用node开发命令行工具所执行的 JavaScript
脚本必须在顶部加入#!/usr/bin/env node
声明,为了告诉执行器使用node执行当前脚本代码
2.项目初始化
cd 项目名
npm init -y
此时 项目会新增
一个package.json
文件
3.脚本映射为命令
这一步可以让我们的项目使用命令行
就可以执行
3.1.配置在package.json
在package.json 中新增 bin 对象:
"bin": {
"abc": "index.js"
}
新增的 bin 对象,键 “abc” 是终端命令交互的时候输入的值(命令),值 index.js 是终端输入 abc 命令的时候要执行的文件
3.2.命令链接到全局
npm link
提示的warn没有关系,这时候可以执行 bin
里面配置的命令测试,即再输入 abc ,则会出现提示 ”脚手架工具“,说明已经执行了 index.js文件了
而且不用在项目目录下输入 abc 也是可以执行的
如果要修改package.json 里面bin字段的值,需要先 npm unlink 再修改bin里面的名称,保存之后再次链接:npm link
4.命令行工具参数设计
目标是设置以下命令
abc -h|--help 查看帮助
abc -v|--version 查看工具的版本号
abc list 列出所有可用的模板
abc init <template-name> <project-name> 基于指定的模板进行项目初始化
其中<>代表必填
5. 使用commander 模块处理 命令行
安装commander,官网
npm install commander
代码:
const { program } = require('commander');//加载commander
//以下每一个program 设置一个命令行参数返回
program
.version('0.1.0')//终端输入 abc -v|--version 返回 0.1.0
program
.command('init <template> <project>') //根据模板名下载对应的模板到本地并起名为projectName
.description('初始化项目模板')
.action(function(templateName, projectName){
//终端输入 “abc init webpack abc” 得到的templateName, projectName分别为 webpack abc
})
//abc init a a-name
//基于 a 模板进行初始化并重命名为 a-name
//itcast init b b-name
//基于 b 模板进行初始化重命名为 b-name
program
.command('list')//终端输入 abc list 返回以下设置的所有可用模板
.description("查看所有可用模板")
.action(() => {
模板选项
}
program.parse(process.argv);
5. 准备模板
在gitee上新建了两个仓库,地址为:https://gitee.com/zuozuomufeishi/tpl-a.git https://gitee.com/zuozuomufeishi/tpl-b.git
使 abc init 可遍历输出模板
const templates = {
'tpl-a': {
url: 'https://gitee.com/zuozuomufeishi/tpl-a',
downloadUrl: 'https://gitee.com/zuozuomufeishi/tpl-a#master',
description: 'a模板'
},
'tpl-b': {
url: 'https://github.com/soandend/tpl-b',
downloadUrl: 'https://github.com.cnpmjs.org/soandend/tpl-b.git#master',
description: 'b模板'
}
}
program
.command('list')
.description("查看所有可用模板")
.action(() => {
for(let key in templates){//遍历输出模板
console.log(`
${key} ${templates[key].description}
`);
}
})
自行下载需要用到的插件:download-git-repo
npm install download-git-repo
代码引入
const download = require('download-git-repo');//引用下载模板需要的包
使模板使用命令abc init tpl-a aaa
可以下载
program
.command('init <template> <project>')
.description('初始化项目模板')
.action(function(templateName, projectName){
//根据模板名下载对应的模板到本地并起名为projectName
//下载模板需要安装 npm install download-git-repo
// 第一个参数:仓库地址
// 第二个参数: 下载路径\
const {downloadUrl} = templates[templateName]
download(downloadUrl, projectName, {clone: true},(err) => {
if(err){
return console.log("下载失败")
}
})
})
6. 设置命令行交互
命令行交互,就是和用户一问一答的方式,对下载的项目进行自定义一些信息
给 tpl-a 添加一个package.json文件:
{
"name": "{{ name }}",
"version": "1.0.0",
"description": "{{ description }}",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "{{ author }}",
"license": "ISC",
"bin": {
"itcast": "index.js"
},
"dependencies": {
"commander": "^7.1.0"
}
}
其中三个字段用于交互:name,description,author
下载模板引擎和向导需要的包:
npm i handlebars
npm install inquirer
index.js引进模板引擎并设置交互模式:
const handlebars = require('handlebars');//引用下载引擎
const inquirer = require('inquirer');//引用向导
const fs = require("fs");//node的文件系统
program
.command('init <template> <project>')
.description('初始化项目模板')
.action(function(templateName, projectName){
//根据模板名下载对应的模板到本地并起名为projectName
//console.log(templateName);
//console.log(projectName);
//
//下载模板需要安装 npm install download-git-repo
// 第一个参数:仓库地址
// 第二个参数: 下载路径\
const {downloadUrl} = templates[templateName]
download(downloadUrl, projectName, {clone: true},(err) => {
console.log(err)
if(err){
return console.log("下载失败")
}
//把项目下的package.json 文件读取出来
//使用向导的方式采集用户输入的值
//使用模板引擎把用户输入的数据解析到package.json文件中
//解析完毕,把解析之后的结果重新写入 package.json 文件中
//使用一个插件:npm install inquirer
inquirer.prompt([
{
type: "input",
name: "name",
message: "请输入项目名称"
},{
type: "input",
name: "description",
message: "请输入项目简介"
},{
type: "input",
name: "author",
message: "请输入作者名称"
},
]).then((answers) => {
//得到用户输入的数据
//解析到package.json 文件中,readFileSync(路径,字符集)
const packageContent = fs.readFileSync(`${projectName}/package.json`, 'utf-8')
const packageResult = handlebars.compile(packageContent)(answers)
//新写入 package.json 文件中
fs.writeFileSync();
})
})
})
7. 本项目发布到npm
目标:使用npm install --g abc-cli
可以下载这个包
1、到 npm官网 注册一个账号
2、检索是否有重名的包名
3、将 package.json 中的name名修改为要发的npm包名
4、控制台登录 npm
npm login
5、登录成功以后,在项目下执行发布:
npm publish
注:npm官网更新比较慢,但是不影响下载
遇到的问题
1. 报以下信息:
internal/modules/cjs/loader.js:883 throw err;
^ Error: Cannot find module 'd
解决:删除node_modules文件夹,重新 执行 npm install