工程化
工程化概念
工程化主要解决的问题
- 传统语言或语法的弊端
- 无法使用模块化、组件化
- 重复的机械式工作
- 代码风格统一、质量保证
- 以来后端服务接口支持
- 整体依赖后端项目
一切重复的工作都应该被自动化
- 创建项目
- 创建项目结构
- 创建特定类型文件
- 编码
- 格式化代码
- 校验代码风格
- 编译、构建、打包
- 预览、测试
- web server/mack
- live reloading \hmr
- source map
- 提交
- git hooks
- lint-staged
- 持续集成
- 部署
- CI\CD
- 自动部署
Yeoman(脚手架工具)
zhuanlan.zhihu.com/p/340935487
- 全局范围安装yo
npm install yo --global
- 安装对应的generator
npm install generator-node --global
- 通过yo运行generator
cd path/dir
mkdir my-module
yo node
使用yeoman的几个步骤
- 需要明确你自己的需求,你到底是要做一个什么样类型的项目
- 根据你的需求去找到合适的Generator
- 通过全局范围安装你所找到的Generator
- 通过Yo这个命令去运行对应的Generator
- 通过命令行交互的方式去填写这个Generator里面对应的一些配置选项
- 得到了我们所需要的项目结构。
自定义Generator
除了特定的结构,还有个与普通npm不同的是,Yeoman的generator的模块的名称必须是generator-这样的一种格式,如果说你在具体开发的时候没有去使用这样一个格式的名称,Yeoman在后续工作的时候就没有办法找到你所提供的这个生成器模块。
- 创建文件夹generator-simple作为生成器模块的目录。
mkdir generator-simple
- 在目录下通过yo init的方式创建一个package.json
yo init
- 我们还需要安装一个yeoman-generator的模块,这个模块提供了我们生成器的一个基类,这个基类当中提供了一些工具函数,让我们可以在创建生成器的时候更加便捷。
yarn add yeoman-generator
- 安装完工具过后,我们通过编辑器打开目录,然后我们在目录下按照项目结构要求,去创建一个generators的文件夹,在这个目录下创建app目录,在目录中创建index.js, 作为generator的核心入口文件。
generator-simple -> generators -> app -> index.js
- index,js需要导出一个继承自 Yeoman Generator的类型 Yeoman Generator在工作时会自动调用我们在此类型中定义的一些生命周期方法 我们可以在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,例如文件写入。
const Generator = require('yeoman-generator');
module.exports = class extends Generator {
writing() {
// Yeoman自动生成文件阶段调用此方法
// 我们尝试往项目目录中写入文件
this.fs.write(this.destinationPath('temp.txt'), '123');
// 这里的fs模块与node中的fs不同,是高度封装的模块功能更强大一些,
}
}
- 这时,我们一个简单的generator就已经完成了,我们通过npm link 的方式把这个模块连接到全局范围, 使之成为一个全局模块包,这样的话,Yeoman在工作的时候就可以找到我们自己写的这个generator-simple模块
yarn link
- 准备就绪,我们可以通过Yeoman去运行这个生成器,具体的操作方式就是yo simple
yo simple
根据模板创建文件
// 模板文件路径
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)
接收用户输入数据
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
})
}
Vue Generator 案例
- 首先按照原始的方式去创建一个理想的项目结构(你意向的项目结构),把需要使用的基础代码全部包含在里面,然后再去封装一个全新的generator用于去生成我们这样一个理想的项目结构。
首先打开命令行窗口,然后通过mkdir去创建一个全新的gengerator目录。
mkdir generator-vue
cd generator-vue
- 通过 yarn init 初始化一个package.json, 然后安装Yeoman的依赖
yarn init
yarn add yeoman-generator
- 新建一个generator的主入口文件,
generators/app/index.js
const Generator = require('yeoman-generator');
module.exports = class extends Generator {
prompting() {
return this.promit([
{
type: 'input',
name: 'name',
message: 'Your project name',
default: this.appname
}
]).then(answer => { // 获取到用户输入的数据
this.answer = answer;
})
}
writing() {
}
}
- 定义的writing方法不再像之前一样写入单个文件,批量的把我们刚刚准备好的那些结构批量生成,所以我们先去创建一个templates目录, 把我们项目的结构copy到我们的templates当中作为模板,有了模板过后需要把项目结构里面一些可能发生变化的地方通过模板引擎的方式去挖坑(文件后缀名不一定非要写成ejs)
我们只定义了项目名称,所以我们把所有的名称替换掉。
我们把每一个文件通过模板转换,生成到对应的路径,我们通过数组循环的方式批量去生成每一个文件。把对应的模板生成到对应的位置当中。
writing() {
const templates = [
'.browserslistrc',
'src/views/Home.vue'
]
templayes.forEach(item => {
this.copyTpl(this.templatePath(item),
this.destinationPath(item),
this.answer);
})
}
- 将我们的generator-vue通过link的方式定义到全局
yarn link
- 然后我们在一个全新的目录使用该generator
yo vue;
plop
安装
- 安装plop
npm install --save-dev plop
yarn add plop --dev
- 项目根目录下新建一个plopfile.js文件
// Plop入口文件,需要导出一个函数
// 此函数接收一个Plop对象,用于创建生成器任务
// setGenerator需要两个参数,第一个参数是项目名字,第二个参数是项目配置
module.exports = plop => {
plop.setGenerator('component',{
description:'create a component',
prompots:[
{
type:'input',
name:'name',
message:'component name',
default:'MyCompontent',
}
],
// 添加多个模板,就在actions中添加多个数组
actions:[
{
type:'add',
path:'src/components/{{name}}/{{name}}.js',
templateFile:'plop-templates/component.hbs'
},
{
type:'add',
path:'src/components/{{name}}/{{name}}.js',
templateFile:'plop-templates/component.test.hbs'
}
]
})
}
- 新建plop-templates文件夹,在此文件夹下新建components.hbs文件,写入模板
import React from 'React';
export default() => (
<div className="{{name}}">
<h1>{{name}}Component</h1>
</div>
)
plop总结
- 将plop模块作为项目开发依赖安装
- 在项目根目录下创建一个plopfile.js文件
- 在plopfile.js文件中定义脚手架任务
- 编写用于生产特定类型文件的模板
- 通过plop提供的CLI运行脚手架任务
脚手架的工作原理
脚手架的工作过程:
- 通过命令行交互询问用户问题
- 根据用户回答的结果生成文件