脚手架的本质作用
创建项目基础结构、提供项目规范和约定
- 相同的组织结构
- 相同的开发范式
- 相同的模块依赖
- 相同的工具配置
- 相同的基础代码
内容概要:
- 脚手架的作用
- 常用的脚手架工具
- 通用脚手架工具剖析
- 开发一款脚手架
常见的脚手架工具
- React → create-react-app
- Vue.js项目 → vue-cli
- Angular项目→ angular-cli
根据信息创建对应的项目基础结构
Yeoman:通用型脚手架工具
Plop:用于项目开发过程当中创建特定类型的文件
例如创建一个组件/模块所需要的文件
Yeoman
The web’s scaffolding tool for modern webapps
不同于vue-cli工具Yeoman更像是一个脚手架运行平台,我们可以通过Yeoman搭配不同的generator去创建任何类型的项目,也就是说我们可以通过创建自己的generator去定制属于我们自己的前端脚手架。
Yeoman基础使用
在全局范围安装yo
$ npm install yo --global
安装对应的generator
$ npm install generator-node --global
通过yo运行generator
$ cd path/to/project-dir
$ mkdir my-module
$ yo node
Sub Generator
yo node:cli
yarn link
yarn
my-module --help
Yeoman使用步骤总结
- 明确你的需求
- 找到合适的Generator
- 全局范围安装找到的Generator
- 通过Yo运行对应的Generator
- 通过命令行交互填写选项
- 生成你所需要的项目结构
自定义Generator
基于Yeoman搭建自己的脚手架
创建Generator模块
Generator本质上就是一个NPM模块
Plop的基本使用
- 将plop模块作为项目开发依赖安装
- 在项目根目录下创建一个plopfile.js文件
- 在plofile.js文件中定义脚手架任务
- 编写用于生成特定类型文件的模板
- 通过Plop提供的CLI运行脚手架任务
脚手架工具的工作原理
启动脚手架工具过后,会自动的去询问预设的问题,根据回答的结果结合模板文件生成对应的项目结构
脚手架实际上就是一个cli应用
// 首先通过命令行mkdir创建一个项目目录
$ mkdir sample-scaffolding
// 进入创建的目录
$ cd sample-scaffolding\
// 初始化package.json
$ yarn init
// 使用vscode打开项目目录
code .
在package.json当中添加bin字段,用于指定cli的入口文件
{
"name": "sample-scaffolding",
"version": "0.1.0",
"main": "index.js",
"bin": "cli.js",
"author": "zce <w@zce.me> (https://zce.me)",
"license": "MIT",
"dependencies": {
"ejs": "^2.6.2",
"inquirer": "^7.0.0"
}
}
接下来再创建指定的入口文件
#!/usr/bin/env node
// Node CLI 应用入口文件必须要有这样的文件头
// 如果是 Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755
// 具体就是通过 chmod 755 cli.js 实现修改
// 脚手架的工作过程:
// 1. 通过命令行交互询问用户问题
// 2. 根据用户回答的结果生成文件
const fs = require('fs')
const path = require('path')
const inquirer = require('inquirer')
// 载入询问模块
const ejs = require('ejs')
// 发起命令行的询问,接受的是数组参数,数组当中每一个成员就是我们发起的命令行问题
// 通过type指定输入方式,name指定问题返回值的键,message指定屏幕上给用户的提示
inquirer.prompt([
{
type: 'input',
name: 'name',
message: 'Project name?'
}
])
.then(anwsers => {
// 在then中可以接收到用户的答案
// console.log(anwsers)
// 根据用户回答的结果生成文件,即动态的生成项目文件,生成项目文件一般根据模板去生成文件
// 明确模板目录和目标目录
// 模板目录
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), anwsers, (err, result) => {
if (err) throw err
// 将结果写入目标文件路径
fs.writeFileSync(path.join(destDir, file), result)
})
})
})
})
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title><%= name %></title>
</head>
<body>
</body>
</html>
// style.css
body {
margin: 0;
background-color: #f8f9fb;
}
接着进入终端
// 将模块link到全局
$ yarn link
// 通过这个命令,对应的模块就会运行
$ sample-scaffolding
// 安装inquirer模块对用户发起询问
$ yarn add inquirer