脚手架
2020-04-16 11:08:53 0 举报
AI智能生成
前端脚手架开发
作者其他创作
大纲/内容
必备模块
commander
参数解析
inquirer
交互式命令行工具
download-git-repo
在 git 中下载模板
chalk
命令行中画颜色
metalsmith
读取所有文件,实现模板渲染
consolidate
统一了所有的模版引擎
将命令链接到全局
创建执行文件
建立 bin 文件夹,
一般新增名为 www 的可执行文件
一般新增名为 www 的可执行文件
#! /usr/bin/env node
require('./src/main.js')
require('./src/main.js')
shebang line
Shebang line 指定脚本的解释程序
#!/usr/bin/env node is an instance of a shebang line: the very first line in an executable plain-text file on Unix-like platforms that tells the system what interpreter to pass that file to for execution, via the command line following the magic #! prefix (called shebang).
#!/usr/bin/env node is an instance of a shebang line: the very first line in an executable plain-text file on Unix-like platforms that tells the system what interpreter to pass that file to for execution, via the command line following the magic #! prefix (called shebang).
Note: Windows does not support shebang lines, so they're effectively ignored there; on Windows it is solely a given file's filename extension that determines what executable will interpret it. However, you still need them in the context of npm.
注册执行命令
package.json 中新增 bin 属性
{
...
...
"bin":{
"zhu-cli":"./bin/www"
}
}
"zhu-cli":"./bin/www"
}
}
install one or more executable files into the PATH.
A bin field is a map of command name to local file name. On install, npm will symlink that file into prefix/bin for global installs, or ./node_modules/.bin/ for local installs.
A bin field is a map of command name to local file name. On install, npm will symlink that file into prefix/bin for global installs, or ./node_modules/.bin/ for local installs.
symlink a package folder
在当前文件夹命令行中执行 npm link
npm link
用法
npm link (in package dir)
描述
npm link in a package folder will create a symlink in the global folder {prefix}/lib/node_modules/<package> that links to the package where the npm link command was executed. (see npm-config for the value of prefix). It will also link any bins in the package to {prefix}/bin/{name}.
安装 eslint 并初始化 eslint 配置文件
初始化配置文件
npx eslint --init
解析用户传递的参数
commander
src/main.js:
const program = require('commander')
program.parse(process.argv)
const program = require('commander')
program.parse(process.argv)
Reflect.ownKeys(mapActions).forEach(action => {
program
.command(action)
.alias(mapActions[action].alias)
.description(mapActions[action].description)
.action(() => {
console.log(action);
if (action === "*") {
console.log(mapActions[action].description);
} else {
console.log(action);
// zhu-cli create xxx
// => process.argv 为 [node,zhu-cli,create,xxx]
require(path.resolve(__dirname,action))(...process.argv.slice(3))
}
});
});
program.on("--help", () => {
console.log("\nExamples:");
Reflect.ownKeys(mapActions).forEach(action => {
mapActions[action].examples.forEach(example => {
console.log(` ${example}`);
});
});
});
program
.command(action)
.alias(mapActions[action].alias)
.description(mapActions[action].description)
.action(() => {
console.log(action);
if (action === "*") {
console.log(mapActions[action].description);
} else {
console.log(action);
// zhu-cli create xxx
// => process.argv 为 [node,zhu-cli,create,xxx]
require(path.resolve(__dirname,action))(...process.argv.slice(3))
}
});
});
program.on("--help", () => {
console.log("\nExamples:");
Reflect.ownKeys(mapActions).forEach(action => {
mapActions[action].examples.forEach(example => {
console.log(` ${example}`);
});
});
});
拉取 github 数据
github api 文档
请求接口时 loading 状态
ora 包
让用户选择分支
inquirer 包
const { repo } = await Inquirer.prompt({
name:'repo',
type:'list',
message:'please choose a template to create project',
choices:repos
})
name:'repo',
type:'list',
message:'please choose a template to create project',
choices:repos
})
存储模板
获取存储模板的位置
const downloadDirectory = `${process.env[process.platform === 'darwin' ? 'HOME' : 'USERPROFILE']}/.template`
下载 git 模板
download-git-repo
将回调方式转换成 promise 方式
const { promisify } = require('util')
let downloadGitRepo = require('download-git-repo');
downloadGitRepo = promisify(downloadGitRepo)
let downloadGitRepo = require('download-git-repo');
downloadGitRepo = promisify(downloadGitRepo)
把模板放在 /usr/xxx/.template 里存好,以备后期使用
const download = async (repo, tag) => {
let api = `zhu-cli/${repo}`;
if (tag) {
api += `#${tag}`;
}
const dest = `${downloadDirectory}/${repo}`;
await downloadGitRepo(api, dest);
return dest;
};
let api = `zhu-cli/${repo}`;
if (tag) {
api += `#${tag}`;
}
const dest = `${downloadDirectory}/${repo}`;
await downloadGitRepo(api, dest);
return dest;
};
将下载好的模板拷贝到当前执行命令下的目录
ncp 包
// 返回的 result 是下载的目录
const result = await waitFnloading(download, 'download template')(repo, tag);
await ncp(result, path.resolve(projectName))
const result = await waitFnloading(download, 'download template')(repo, tag);
await ncp(result, path.resolve(projectName))
path.resolve 如果在处理完所有给定的 path 片段之后还未生成绝对路径,则再加上当前工作目录。
渲染复杂的模板
根据是否有 ask.js 文件来判断是否是复杂模板
if(!fs.existsSync(path.join(result,'ask.js'))){
await ncp(result,path.resolve(projectName))
}else{
}
if(!fs.existsSync(path.join(result,'ask.js'))){
await ncp(result,path.resolve(projectName))
}else{
}
简单
复杂
const Metalsmith = require("metalsmith");
let { render } = require("consolidate").ejs;
render = promisify(render)
if(!fs.existSync(path.join(result,'ask.js'))){
await ncp(result,path.resolve(projectName))
}else{
await new Promise((resolve,reject)=>{
Metalsmith(__dirname) // 传入路径会默认遍历当前路径下的 src 文件夹
.source(result)
.destination(path.resolve(projectName))
.use((files, metal, done) => {
const args = require(path.join(result,'ask.js'))
const obj = await Inquirer.prompt(args)
const meta =metal.metadata()
Object.assign(meta,obj)
delete files['ask.js']
done();
})
.use((files, metal, done) => {
const obj= metal.metadata()
Reflect.ownKeys(files).forEach(async (file)=>{
if(file.includes('js')||file.includes('json')){
let content= files[file].contents.toString()
if(content.includes('<%')){
content=await render(content,obj)
files[file].contents=Buffer.from(content)
}
}
})
done()
})
.build((err)=>{
if(err){
reject()
}else{
resolve()
}
})
})
}
let { render } = require("consolidate").ejs;
render = promisify(render)
if(!fs.existSync(path.join(result,'ask.js'))){
await ncp(result,path.resolve(projectName))
}else{
await new Promise((resolve,reject)=>{
Metalsmith(__dirname) // 传入路径会默认遍历当前路径下的 src 文件夹
.source(result)
.destination(path.resolve(projectName))
.use((files, metal, done) => {
const args = require(path.join(result,'ask.js'))
const obj = await Inquirer.prompt(args)
const meta =metal.metadata()
Object.assign(meta,obj)
delete files['ask.js']
done();
})
.use((files, metal, done) => {
const obj= metal.metadata()
Reflect.ownKeys(files).forEach(async (file)=>{
if(file.includes('js')||file.includes('json')){
let content= files[file].contents.toString()
if(content.includes('<%')){
content=await render(content,obj)
files[file].contents=Buffer.from(content)
}
}
})
done()
})
.build((err)=>{
if(err){
reject()
}else{
resolve()
}
})
})
}
发包
nrm use npm
nrm can help you easy and fast switch between different npm registries, now include: npm, cnpm, taobao, nj(nodejitsu)
npm addUser
npm publish
npm unpublish --force
卸载包
0 条评论
下一页