使用node脚本封装
使用yeoman-generator封装自己的脚手架
一些详细的参数:https://www.kancloud.cn/cyyspring/webpack/1992161
yo --generators 查看所有的generators
注意:文件名称一定要和命令行名字一样:例如:mkdir generator-ai-cli,在package.json中的name也要为: generator-ai-cli,不然会报错误:没有这个包
-
下载安装yeoman: npm install -g yo
-
mkdir generator-ai-cli
-
npm init -y
-
npm install yeoman-generator --save
-
目录结构
-
mkdir generators/app/index.js
// generators/app/index.js
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
prompting () {
// 命令行交互模式
return this.prompt([
{
type: 'input',
name: 'name',
message: 'Your project name',
default: this.appname
}
])
.then(answers => {
this.answers = answers
})
}
writing () {
// 把每一个文件都通过模板转换到目标路径
/*
const templates = [
'.browserslistrc',
'.editorconfig',
'.env.development',
'.env.production',
'.eslintrc.js',
'.gitignore',
'babel.config.js',
'package.json',
'postcss.config.js',
'README.md',
'public/favicon.ico',
'public/index.html',
'src/App.vue',
'src/main.js',
'src/router.js',
'src/assets/logo.png',
'src/components/HelloWorld.vue',
'src/store/actions.js',
'src/store/getters.js',
'src/store/index.js',
'src/store/mutations.js',
'src/store/state.js',
'src/utils/request.js',
'src/views/About.vue',
'src/views/Home.vue'
]
templates.forEach(item => {
// item => 每个文件路径
this.fs.copyTpl(
this.templatePath(item),
this.destinationPath(item),
this.answers
)
})
*/
// 把每一个文件都通过模板转换到目标路径
const tmplDir = path.join(__dirname, 'templates')
fs.readdir(tmplDir, (err, templates) => {
if (err) throw err
templates.forEach(item => {
// item => 每个文件路径
this.fs.copyTpl(
this.templatePath(item),
this.destinationPath(item),
this.answers
)
})
})
}
}
我们要导出一个模块,这个模块是一个继承自Generator 的类。yeoman-generator会自动调用我们在此类中定义的一些生命周期方法,如:prompting,writing。
这个类中你可以实现prompting方法,作用是在其它用户拉下来这个模板的时候,可以根据自己的需求做一些初始化。比如你在使用vue-cli初始化一个vue项目的时候,一开始总是问你很多问题,比如项目名称,要不要使用vuex,要不要使用vue-router,要不要使用单元测试等等。那么prompting方法同理,可以根据用户的不同需求,来初始化项目。在这个方法中必须返回this.prompt(),它接收一个对象数组,数组中每个对象就是一个问题,你可以设置这个问题询问的方式,这里type:'input’的意思就是要求用户手动输入答案;name就是这个问题以及答案的标识,后续可以根据设置的name属性对应的值,来获得这个问题的答案;message就是询问的问题;default:this.appname,为项目生成目录名称。
根据模板创建文件,在这个类中,还要实现writing方法,把模板写入对应的文件夹中。上面代码中列举了一个数组,这个数组里面的值就是模板中没有给文件的相对路径,那么我们遍历这个数组,使用this.fs.copyTpl()方法来拉取模板内容,创建新项目。这个this.fs.copyTpl()方法接收两个参数,第一个就是templates目录下的文件,第二个就是创建新文件后这个文件的名字,第三个就是刚刚用户根据问题输入的答案,这个稍后会作更详细解释。ckage.json
{
"name": "generator-ai-cli",
"version": "0.1.0",
"main": "index.js",
"author": "",
"license": "MIT",
"dependencies": {
"yeoman-generator": "^4.0.1"
}
}
- 准备模版文件,模版文件的存放路径:generators/app/templates
generators/app/templates
文件
- npm link
个人建议:可以使用yarn link,也可以使用npm link,更建议使用npm link,因为使用npm link可以成功之后会显示当前的的link地址,但是使用yarn link就不会显示
- yo ai-cli
plop:使用plop创建代码模块
1.场景:使用plop创建代码模块
必须是用yarn,使用npm好像生成不成功。
- yarn install plop --save
- touch plopfile.js
plop的入口文件:
// Plop 入口文件,需要导出一个函数
// 此函数接收一个 plop 对象,用于创建生成器任务
module.exports = plop => {
/**
setGenerator参数:
component: 生成器的名字
{}: 生成器的配置
*/
plop.setGenerator('component', {
description: 'create a component',
prompts: [
{
type: 'input', // // 输入方式
name: 'name', // 问题返回值的键
message: 'component name', // 屏幕上给出的提示
default: 'MyComponent', // 问题的默认答案
}
],
actions: [
{
type: 'add', // 代表添加文件
path: 'src/components/{{name}}/{{name}}.js', // 添加文件的具体路径
templateFile: 'plop-templates/component.hbs' // 添加文件的模版文件路径
},
{
type: 'add', // 代表添加文件
path: 'src/components/{{name}}/{{name}}.css',
templateFile: 'plop-templates/component.css.hbs'
},
{
type: 'add', // 代表添加文件
path: 'src/components/{{name}}/{{name}}.test.js',
templateFile: 'plop-templates/component.test.hbs'
}
]
})
}
模版文件:
// plop-templates/component.css.hbs
import React from 'react';
export default () => (
<div className="{{name}}">
<h1>{{name}} Component</h1>
</div>
)
// plop-templates/component.css.hbs
.{{name}} {
}
// plop-templates/component.test.hbs
import React from 'react';
import ReactDOM from 'react-dom';
import {{name}} from './{{name}}';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<{{name}} />, div);
ReactDOM.unmountComponentAtNode(div);
});
yarn plop component (生成器的名字)
执行命令:yarn plop component
效果: