文章目录
1.概要
因为在前端工程中,可能会有:
- 相同的组织结构
- 相同的开发范式
- 相同的模块依赖
- 相同的工具配置
- 相同的基础代码
脚手架就是解决上面问题的工具,通过创建项目骨架自动的执行工作。IDE创建项目的过程就是一个脚手架的工作流程。
由于前端技术选型比较多样,又没有一个统一的标准,所以前端脚手架不会集成在某一个IDE中,一般都是以一个独立的工具存在,相对会复杂一些。
2.常用的脚手架工具
- 第一类脚手架是根据信息创建对应的项目基础结构,适用于自身所服务的框架的那个项目。
- create-react-app
- vue-cli
- Angular-cli
- 第二类是像Yeoman为代表的通用型脚手架工具,根据模板生成对应的项目结构,这种脚手架工具很灵活,很容易扩展。
- 第三类以Plop为代表的脚手架工具:在项目开发过程中,创建一些特定类型的组件,例如创建一个组件/模块所需要的文件,这些模块或组件一般都是由特定结构组成的,有相同的结构。
3.Yeoman - 简介
The web’s scaffloding tool for modern webapps
Yeoman是现代化前端项目的脚手架工具,用于生成包含指定框架结构的工程化目录结构
4.Yeoman - 基本使用
- 全局环境安装 yo
yarn global add yo
- Yeoman要搭配相应的Generator创建任务,所以要安装Generator。例如是创建node项目,则安装generator-node:安装对应的 generator ( 本次演示的是一个 node 项目)
yarn global add generator-node
- 通过 yo 运行 generator
yo node
- 目录结构
5.sub Generator
有时候我们可能不需要创建一个完成的项目结构,而是在已有项目的基础上,创建一些项目文件,如README.md,或者是创建一些特定类型的文件,如ESLint、Babel配置文件
- 运行SubGenerator的方式就是在原有Generator基础上加上:SubGenerator的名字,如:
yo node:cl
i- 本地模块link全局范围
yarn link
- yarn
- my-module --help
- 本地模块link全局范围
- 在使用SubGenerator前,要先去查看一下Generator之下有哪些SubGenerator
6.Yeoman 使用步骤总结
常规使用步骤:
- 明确你的需求
- 找到合适的 Generator
- 全局范围安装找到的 Generator
- 通过 yo 运行对应的 Generator
- 通过命令行交互填写选项
- 生成你所需要的项目结构
7.自定义 Generator
基于 Yeoman 搭建自己的脚手架
8.创建 Generator 模块
Generator 本质上就是一个 npm 模块
- Generator有特定的项目结构
- yeoman 特定的项目名称必须是: generator-
创建步骤:
- mkdir generator-sample
- cd generator-sample
- yarn init
- yarn add yeoman-generator
- 创建文件:generators/app/index.js 作为generators的核心入口
/**
* 此文件作为 generator 的核心入口
* 需要导出一个集成自 Yeman Generator 的类型
* Yeman Generator 在工作时会自动调用此类型中定义的一些生命周期方法
* 我们在这些方法中可以通过父类提供的一些工具实现一些功能, 例如文件写入
*/
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
writing(){
// yeoman 自动在生成文件阶段调用此方法
// 我们这里尝试往项目目录中写入文件
this.fs.write(
this.destinationPath('tmp.txt'),
Math.random().toString()
)
}
}
yarn link
链接成全局模块包 (包名; generator-sample)- 创建新项目文件夹
- 在新文件夹下执行
- yo sample
9.根据模板创建文件步骤
- 相对于手动创建每一个文件,模板的方式大大提高了效率
添加模板目录 templates 目录
foo.txt
这是一个模板文件
内部可以使用 EJS 模板标记输出数据
例如:<%= title %>
其他的 EJS 语法也支持
<% if (success) { %>
哈哈哈
<% }%>
在 入口文件的 writing 方法中 copyTemplate 方法
/**
* 此文件作为 generator 的核心入口
* 需要导出一个集成自 Yeman Generator 的类型
* Yeman Generator 在工作时会自动调用此类型中定义的一些生命周期方法
* 我们在这些方法中可以通过父类提供的一些工具实现一些功能, 例如文件写入
*/
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
writing(){
// yeoman 自动在生成文件阶段调用此方法
// 我们这里尝试往项目目录中写入文件
// this.fs.write(
// this.destinationPath('tmp.txt'),
// Math.random().toString()
// )
// 通过模板方式写入文件到目标目录
// 模板文件路径
const html = this.templatePath('foo.html')
// 输出目标路径
const output = this.destinationPath('foo.html')
// 模板数据上下文
const context = {title: 'hello yeoman' , success: false}
// 拷贝模板
this.fs.copyTpl(html, output, context)
}
}
10.接收用户输入数据
index.js
// 此文件作为 Generator 的核心入口
// 需要导出一个继承自 Yeoman Generator 的类型
// Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法
// 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,例如文件写入
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
prompting () {
// Yeoman 在询问用户环节会自动调用此方法
// 在此方法中可以调用父类的 prompt() 方法发出对用户的命令行询问
return this.prompt([
{
type: 'input',
name: 'name',
message: 'Your project name',
default: this.appname // appname 为项目生成目录名称
}
])
.then(answers => {
// answers => { name: 'user input value' }
this.answers = answers
})
}
writing () {
// Yeoman 自动在生成文件阶段调用此方法
// // 我们这里尝试往项目目录中写入文件
// this.fs.write(
// this.destinationPath('temp.txt'),
// Math.random().toString()
// )
// -------------------------------------------------------
// // 通过模板方式写入文件到目标目录
// // 模板文件路径
// const tmpl = this.templatePath('foo.txt')
// // 输出目标路径
// const output = this.destinationPath('foo.txt')
// // 模板数据上下文
// const context = { title: 'Hello zce~', success: false }
// this.fs.copyTpl(tmpl, output, context)
// -------------------------------------------------------
// 模板文件路径
const tmpl = this.templatePath('bar.html')
// 输出目标路径
const output = this.destinationPath('bar.html')
// 模板数据上下文
const context = this.answers
this.fs.copyTpl(tmpl, output, context)
}
}
11.vue Generator 案例
- 准备一个 generator-rjy-vue 目录
- 安装 (yarn init + yarn add yeoman-generator)
- 创建目录 /generators/app/index.js /generators/app/templates (同上一部分)
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
)
})
}
}
- 将generator-rjy-vue 导入全局
- yarn link
- 创建一个新的目录
- mkdir my-vue
- 执行 我们自定义的 generator-rjy-vue 生成模板
- yo generator-rjy-vue
- 在 my-vue 项目下 yarn install --> yarn serve 最后可以正常使用
12.发布 Generator
发布 generator 就是发布一个 npm 模块
执行: npm publish
| yarn publish
注意:不能使用 淘宝镜像
或者发布时可添加镜像yarn publish --registry=https"//registry.yarnpkg.com
13.Plop
- 一个小而美的脚手架工具
- 主要用于在项目中 创建特定类型的小工具, 类似 yeoman subGenerator,一般不会独立去使用
- 主要用于在在项目中创建同类型的文件
14.Plop基本使用
- 将 plop 模块作为项目开发依赖安装
yarn add plop --dev - 在项目根目录下创建一个plopfile.js 文件
- 在 plopfile,js 文件中定义脚手架任务
- 编写用于特定类型的文件的模板
- 通过Plop 体用的cli 运行脚手架任务
eg: (相关代码:)
- plopfile.js
// Plop 入口文件,需要导出一个函数
// 此函数接收一个 plop 对象,用于创建生成器任务
module.exports = plop => {
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'
}
]
})
}
- 根目录创建对应模板文件
- 项目根目录运行
yarn plop component(这个是自己定义的名字)
15.脚手架的工作原理
总结
代码项目地址:https://gitee.com/yingjiehanyan/fed-e-task-02-01-exec/tree/master/code/02-01-02-04-plop-sample