工程化概述
所有以提高效率、降低成本、质量保证为目标的伎俩都属于工程化
-
创立我的项目
- 通过脚手架工具创立我的项目构造
-
编码
- 格式化代码
- 编译、构建、打包
-
预览 / 测试
- Web Server/Mock
- HMR
- Source Map
-
提交
- Git Hooks
- 继续集成
-
部署
- CI/CD
- 主动公布
脚手架工具
实质 :创立我的项目根底构造、提供我的项目标准和约定
Yeoman(通用型脚手架工具)
根本应用
装置 yeoman
npm install -g yo
而后装置所需的 generator
,Generators
是名为 generator-XYZ
的 npm
包。这里装置 node generator
npm install -g generator-node
执行脚手架搭建新我的项目
yo node
Sub Generator
须要依据对应的
Generator
文档判断是否存在Sub Generator
装置对应 sub Generator
yo node:cli
链接以后模块到全局
npm link
执行查看后果
my-module --help
// 输入
testing
Usage
$ my-module [input]
Options
--foo Lorem ipsum. [Default: false]
Examples
$ my-module
unicorns
$ my-module rainbows
unicorns & rainbows
应用步骤总结
- 明确需要,找到适合的 Generator
- 全局范畴装置找到的 Generator
- 通过 yo 运行对应的 Generator
- 通过命令行交互填写选项
- 生成所须要的我的项目构造
自定义 Generator
装置 generator 基类
yarn add yeoman-generator
创立 generators/app/index.js
为 Generator 的外围入口
// 此文件作为 Generator 的外围入口
// 须要导出一个继承自 Yeoman Generator 的类型
// Yeoman Generator 在工作时会主动调用咱们在此类型中定义的一些生命周期办法
// 咱们在这些办法中能够通过调用父类提供的一些工具办法实现一些性能,例如文件写入
const Generator = require("yeoman-generator");
module.exports = class extends Generator {writing() {
// Yeoman 主动在生成文件阶段调用此办法
this.fs.write(this.destinationPath("temp.txt"), Math.random().toString());
}
};
执行 npm link
后,创立新模块并执行
yo sample
依据模板创立文件
// 模板
module.exports = class extends Generator {writing() {
// 模板文件门路
const tmpl = this.templatePath("foo.txt");
// 输入文件门路
const output = this.destinationPath("foo.txt");
// 模板数据上下文
const context = {title: "hello", success: true};
this.fs.copyTpl(tmpl, output, context);
}
};
接管用户输出
module.exports = class extends Generator {prompting() {
// Yeoman 在询问用户环节会主动调用此办法
// 在此办法中能够调用父类的 prompt() 办法收回对用户的命令行询问
return this.prompt([
{
type: "input", // 用户输出类
name: "title", // 接管参数的键
message: "message title", // 提醒
default: "hello", // 默认值
},
{
type: "input", // 用户输出类
name: "success", // 接管参数的键
message: "message status", // 提醒
default: false, // 默认值
},
]).then((answer) => {this.answer = answer;});
}
writing() {
// 模板文件门路
const tmpl = this.templatePath("foo.txt");
// 输入文件门路
const output = this.destinationPath("input.txt");
// // 模板数据上下文
// const context = {title: "hello", success: true};
this.fs.copyTpl(tmpl, output, this.answer);
}
};
Plop(创立特定类型文件)
根本应用
- 将 plop 模块作为我的项目开发依赖装置
- 在我的项目根目录下创立一个 plopfile.js 文件
- 在 plopfile.js 文件中定义脚手架工作
- 编写用于生成特定类型文件的模板
- 通过 plop 提供的 cli 运行脚手架工作
装置 plop
扩大模块
yarn add plop --dev
在我的项目根目录下创立 plopfile.js
入口文件
// plop 入口文件,须要导出一个函数
// 此函数接管一个 plop 对象,用户创立生成器工作
module.exports = (plop) => {
plop.setGenerator("component", {
description: "create component",
prompts: [
{
type: "input",
name: "name",
message: "component name",
default: "myComponent",
},
],
actions: [
{
type: "add",
path: "src/components/{{name}}/index.js",
templateFile: "templates/component.js.hbs",
},
{
type: "add",
path: "src/components/{{name}}/index.css",
templateFile: "templates/component.css.hbs",
},
{
type: "add",
path: "src/components/{{name}}/index.html",
templateFile: "templates/component.html.hbs",
},
],
});
};
编写用于生成特定类型文件的模板 component.html.hbs
console.log("{{name}}")
运行
yarn plop component
脚手架工具原理
- 通过命令行交互询问用户问题
- 依据用户答复的后果生成文件
Node CLI 的入口配置是 package.json
文件中的 bin
,利用入口文件必须要有这样的文件头。如果是 Linux 或者 macOS 零碎下还须要批改此文件的读写权限为 755
#!/usr/bin/env node
文件配置
#!/usr/bin/env node
console.log("start......");
const inquirer = require("inquirer");
const fs = require("fs");
const path = require("path");
const ejs = require("ejs");
inquirer
.prompt([
{
type: "input",
name: "name",
message: "project name",
},
])
.then((answer) => {console.log(answer);
// 模板目录
const tmplDir = path.join(__dirname, "templates");
// 目标目录
const destDir = process.cwd();
// 将模板下的文件全副转换到目标目录
fs.readdir(tmplDir, (err, files) => {if (err) throw err;
files.forEach((file) => {
// 通过模板引擎渲染文件
ejs.renderFile(path.join(tmplDir, file), answer, (err, result) => {if (err) throw err;
// 将后果写入指标文件门路
fs.writeFileSync(path.join(destDir, file), result);
});
});
});
});