在讲解脚手架之前,我们先来看看目录结构吧:
=================
|__ bin
|__ index.js
|__ command
|__ add.js
|__ delete.js
|__ init.js
|__ list.js
|__ node_modules
|__ package.json
|__ templates.json
首先,新建pakage.json文件,写入依赖并且执行npm install
{
"dependencies": {//必须依赖
"chalk": "^1.1.3",
"co": "^4.6.0",
"co-prompt": "^1.0.0",
"commander": "^2.9.0"
},
"name": "templates_wct",//模板名称,用于npm install name
"version": "1.0.1",//发布时填写的版本号
"description": "a tool service for react-ssr",//描述
"main": "index.js",//入口文件名称
"bin": {
"snowcat": "bin/index.js"//执行名称,配置后只需:snowcat init 便可初始化。
},
"author": "wct",
"license": "ISC",
"repository": {
"type": "git",
"url": "git+https://github.com/Windseek/react-ssr-cli.git"
},
"keywords": [
"react",
"react-ssr",
"wind-ssr",
"react-ssr-cli"
],
"bugs": {
"url": "https://github.com/Windseek/react-ssr-cli/issues"
},
"homepage": "https://github.com/Windseek/react-ssr-cli#readme"
}
入口文件
在根目录下建立\bin
文件夹,在里面建立一个index.js文件。这个bin\index.js
文件是整个脚手架的入口文件,所以我们首先对它进行编写。
首先是一些初始化的代码:
#!/usr/bin/env node
const { resolve } = require('path')
const program = require('commander')
process.env.NODE_PATH = resolve(__dirname, '../node_modules/')
const { version } = require(resolve(__dirname, '../package.json'))
// const version = require('../package');
// process.env.NODE_PATH = __dirname + '/../node_modules/';
program
.version(version)
program
.usage('<commands>')
program
.command('add')
.description('Add a new template')
.alias('a')
.action(() => {
require('../commands/add')()
})
program
.command('list')
.description('List all templates')
.alias('l')
.action(() => {
require('../commands/list')()
})
program
.command('delete')
.description('Delete a template')
.alias('d')
.action(() => {
require('../commands/delete')()
})
program
.command('init')
.description('Generate a new project')
.alias('i')
.action(() => {
require('../commands/init')()
})
program.parse(process.argv)
if(!program.args.length){
program.help()
}
从前文的架构图中我们可以看到,在根目录下创建一个/commands文件,其下有四个js文件,init,list,add,delete
在根目录下新建一个模板templates.json,用于存放模板信息;
{"tpl":{
"react":{"url":"https://github.com/Windseek/reactssr.git","branch":"master"},
}
}
模板初始化:init
'use strict'
const exec = require('child_process').exec;//可运行复杂的命令
const co = require('co');//异步控制流程模块,和es6标准Promise类似,基于 ES6 的 generator 和 yield,属于node圈
const prompt = require('co-prompt')
const config = require('../templates')
const chalk = require('chalk');//为了使输出不再单调,添加文字背景什么的,改变字体颜色什么的
module.exports = () => {
co(function *() {
// 处理用户输入
let tplName = yield prompt('Template name (you can input one like react, vue, angular): ')
let projectName = yield prompt('Project name: ')
let gitUrl,branch;
console.log(config.tpl);
if (!config.tpl[tplName]) {
console.log(chalk.red('\n × Template does not support!'))
process.exit()
}
gitUrl = config.tpl[tplName].url
branch = config.tpl[tplName].branch
// git命令,远程拉取项目并自定义项目名
let cmdStr = `git clone ${gitUrl} ${projectName} && cd ${projectName} && git checkout ${branch}`
exec(cmdStr, (error, stdout, stderr) => {
if (error) {
console.log(error)
process.exit()
}
console.log(chalk.green('\n √ Generation completed!'))
console.log(`\n cd ${projectName} && npm install \n`)
process.exit()
})
})
}
模板新增:add——->模板信息写进templates.json
'use strict'
const co = require('co')
const prompt = require('co-prompt')
const config = require('../templates')
const chalk = require('chalk')
const fs = require('fs')
module.exports = () => {
co(function *() {
// 分步接收用户输入的参数
let tplName = yield prompt('Template name: ')
let gitUrl = yield prompt('Git https link: ')
let branch = yield prompt('Branch: ')
// 避免重复添加
if (!config.tpl[tplName]) {
let objConfig = {};
objConfig.url = gitUrl.replace(/[\u0000-\u0019]/g, '') // 过滤unicode字符
objConfig.branch = branch
config.tpl[tplName] = objConfig
} else {
console.log(chalk.red('Template has already existed!'))
process.exit()
}
// 把模板信息写入templates.json
fs.writeFile(__dirname + '/../templates.json', JSON.stringify(config), 'utf-8', (err) => {
if (err) console.log(err)
console.log(chalk.green('New template added!\n'))
console.log(chalk.grey('The last template list is: \n'))
console.log(config)
console.log('\n')
process.exit()
})
})
}
模板删除:delete
'use strict'
const co = require('co')
const prompt = require('co-prompt')
const config = require('../templates')
const chalk = require('chalk')
const fs = require('fs')
module.exports = () => {
co(function *() {
// 接收用户输入的参数
let tplName = yield prompt('Template name: ')
// 删除对应的模板
if (config.tpl[tplName]) {
config.tpl[tplName] = undefined
} else {
console.log(chalk.red('Template does not exist!'))
process.exit()
}
// 写入template.json
fs.writeFile(__dirname + '/../templates.json', JSON.stringify(config), 'utf-8', (err) => {
if (err) console.log(err)
console.log(chalk.green('Template deleted!'))
console.log(chalk.grey('The last template list is: \n'))
console.log(config)
console.log('\n')
process.exit()
})
})
}
查看模板列表:list
'use strict'
const config = require('../templates')
module.exports = () => {
console.log(config.tpl)
process.exit()
}
全局使用,在根目录下:
确认设置 package.json下的bin为:
"bin": {
"snowcat": "bin/index.js"
},
执行:npm link
执行snowcat 测试结果:
Usage: scion <command>
Options:
-h, --help output usage information
-V, --version output the version number
Commands:
add|a Add a new template
list|l List all the templates
init|i Generate a new project
delete|d Delete a template
写好了需要发布一下喽:npm账号注册(https://www.npmjs.com/)
1、npm login,填写用户名,密码
2、修改package.json里version
3、npm publish
4、去https://www.npmjs.com/上看看成功没有
相关说明:
1、package.json里定义bin的位置
2、index里定义bin命令指定执行的代码
3、init里执行shell,去git上拿代码模板
安装和初始化:
1、npm install templates_wct -g
2、snowcat init
3、选择要使用的模板,react,angular和vue
注: 原址请参考CSDN:(https://blog.csdn.net/fengyinchao/article/details/52168619)