脚手架工具
脚手架工具
脚手架工具介绍
- 脚手架的本质作用:自动创建项目基础结构 提供项目规范和约定。
脚手架不仅仅能帮我们创建文件,更重要的是可以帮我们进行一些规范的约定
- 相同的组织结构
- 相同的开发范式
- 相同的模块依赖
- 相同的工具配置
- 相同的基础代码
脚手架工具就是为了解决我们项目搭建前期需要重复的工作的。
IDE创建项目的过程就是脚手架执行的过程
前端脚手架 没有同意标准 不会继承在IDE中 都是独立存在的插件
主要学习:
脚手架的作用
常用的脚手架工具
通过脚手架工具剖析
开发一款自己的脚手架
常用的及脚手架工具
目前市面上的工具
React => create - react - app
vue => vue - cli
Angular => angular - cli
实现方式都大同小异 , 根据信息创建对应的项目基础结构, 主要服务于自身的框架,还有一些类似Yeoman这种的通用的脚手架,根据一个模板生成一个项目结构还有,另一个工具plop创建一个组件 / 模块所需要的文件。
Yeoman
-
Yeoman不同于vue - cli,Yeoman更像是脚手架的平台我们可以搭建不同的
-
Generator来创建不同的脚手架,可以通过创建自己的额Generator来搭建适合自己项目的脚手架。
-
Yeoman的优点也是缺点 :对于经常使用框架的自带的脚手架的人而言Yeoman不够专注过于通用。
-
Yeoman的使用
- 安装Yeoman 准备工作:
node -v // 确认node环境以及版本
npm-v // 确认npm版本
npm i yarn -g // 全局安装yarn命令
yarn global add yo || npm install -g yo // 安装全局安装Yeoman
- 安装对应的gennerator
Yeoman必须要配合Genarator才能帮助我们创建项目例如我们想要创建一个node-modules的模块就需要使用generator-node这个模块
使用Generator的方式也是通过全局安装的方式
yarn global add gennerator-node
C: \Users\ Apple\ Desktop\ songyi - module > yo node ?
=== === === === === === === === === === === === === === === === === === === === === === === === ==
We 're constantly looking for ways to make yo better!
May we anonymously report usage statistics to improve the tool over time ?
More info : https: //github.com/yeoman/insight & http://yeoman.io
===
=== === === === === === === === === === === === === === === === === === === === === === === == Yes
?
Module Name songyi - module // 创建的项目名称
(node: 1356)[DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated ?
Description // 项目的具体描述
?
Project homepage url https : //github.com/93songyi // github地址
?
Author 's Name songyi // 作者名字 ?
Author 's Email 840600097@qq.com // 作者邮箱 ?
Author 's Homepage https://songyi.me ?
Package keywords(comma to split) module, node // 项目关键词
?
Send coverage reports to coveralls No 是否发送代码覆盖到指定的地方 no ?
Enter Node versions(comma separated) ?
Enter Node versions(comma separated) ?
GitHub username or organization songyi ?
Which license do you want to use ? MIT 选择MIT
create package.json
force.yo - rc.json
force..\..\.yo - rc - global.json
create README.md
create.editorconfig
create.gitattributes
create.gitignore
create.travis.yml
create.eslintignore
create lib\ index.js
create LICENSE
create lib\ __tests__\ songyiModule.test.js
I 'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
npm WARN deprecated request @2 .88 .2: request has been deprecated, see https: //github.com/request/request/issues/3142
npm WARN deprecated request - promise - native @1 .0 .9: request - promise - native has been deprecated because it extends the now deprecated request package, see https: //github.com/request/request/issues/3142
npm WARN deprecated har - validator @5 .1 .5: this library is no longer supported[..........] / extract: yargs - parser: sill extract word - wrap @1 .2 .3
Sub Generator
- 作用: 有时我们不需要创建整个数据结构只需要在原有的项目结构上创建文件, 例如给已有的项目创建Readme文件。
- 可以通过Yeoman上的sub Generator这个特性来实现。
- yo node: cli //Yeoman运行node下的cli
会提醒是否重写package.json 文件因为cli模块会改变配置
conflict package.json
? Overwrite package.json? overwrite // 回答 y
force package.json
create lib\cli.js
package.json文件修改了
"bin": "lib/cli.js",
"dependencies": {
"meow": "^3.7.0"
}
还有在lib/cli.js 中提供了一些基础的代码
-
yarn link 到全局范围就可以运行刚刚加进来的模块了
-
yarn命令安装package.json中的依赖
-
就可以以项目名称书写命令运行了 这就是Generator子集的特性, 不是所有的子集都有这个特性.
需要通过官方文档来明确当前使用的子集是否有这个特性
generator-node提供的sub generator
node - boilerplate
node: cli
node: editorconfig
node: eslint
node: git
node: readme
我的运行 项目名称 --help之后报错
PS C:\Users\Apple\Desktop\songyi-module> songyi-module --help
songyi-module : 无法将“songyi-module”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路
径,请确保路径正确,然后再试一次。
所在位置 行:1 字符: 1
+ songyi-module --help
+ ~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (songyi-module:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
环境变量配置问题
常用的Yeoman使用步骤
常用步骤整理:
- 明确需求
- 查看官网找到需要使用的Generator
- 全局范围安装Generator
- 通过yo运行对应的generator
- 通过命令行交互填写选项
- 生成所需要的项目结构
例如想生成一个网页应用
- 找到官网 https://yeoman.io/generators/ 查找合适的generator
- 命令行安装 webapp yarn global add generator - webapp
- 安装完成后通过Yeoman运行 yo webapp 会有一些预设的问题会根据你的选项生成项目结构 也会自动帮你安装所需依赖
需要注意的是安装这些依赖是需要依赖c++的模块 去下载一些二进制的文件 这些文件不能通过npm镜像去加速 所以速度会慢。
自定义Generator
-
不同的Generator可以生成不同的项目,我们可以根据自己的需求创建Generator
-
创建Generator模块规则:
- Generator有特定的目录结构
- 有特定的名称 必须是以generator-的形式命名yeoman运行时候才能找到这个模块
步骤:
- mkdir generator-sample 文件夹名作为生成器目录
mkdir generator-sample
- cd generator-sample
- yarn init 生成package.json
- yarn add yeoman-generator 安装生成器的基类,基类中提供了一些工具函数可以在创建生成器的时候更加便捷
- vscode打开目录安装generator要求创建基础目录
6 generators/app/index.js 创建一个generators文件夹 下面包含一个app文件夹,下面有一个index.js - 在index.js 写入文件方法
- 把当前的sample挂载到全局 yarn link / npm link
- cd…回到桌面创建文件夹my-project
- 进入my-project 运行yo sample 项目中创建了temp.txt 内容就是Math.random()的内容
此时没有生成成功报错如下:
Error sample
primordials is not defined
解决:
- 安装node版本控制器 npm install -g n
- 运行后又报错改为 报错如下 npm install -g n --force 就可以了
npm ERR! code EBADPLATFORM (EBADPLATFORM ->古怪)
npm ERR! notsup Unsupported platform for n@6.7.0: wanted {"os":"!win32","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm ERR! notsup Vali。d OS: !win32
npm ERR! notsup Valid Arch: any
npm ERR! notsup Actual OS: win32
npm ERR! notsup Actual Arch: x64
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Apple\AppData\Roaming\npm-cache\_logs\2020-11-20T15_54_31_755Z-debug.log
根据模板生成文件
很多时候需要创建的文件有很多内容也很复杂这时候需要使用模板创建文件
- 现在generator/app 文件夹下创建一个templates的文件夹 里面有一个文件foo.txt
- yo sample yeoman会自动使用模板引擎来渲染模板,将渲染结果输出到目标文件夹中
相对于手动创建文件,模板的方式可以提升效率 特别当文件较多又很复杂的情况。
接收用户输入
模板中的一些数据是创建文件时用户自定义的需要我们动态获取的
命令行交互的方式来获取
方法如下:
- 在writing方法的同级使用prompting方法
- return 一个promise对象 this.prompt()
- this.prompt() 接收一个数组参数 里面用来配置命令行交互的配置项
- promise对象的then方法中返回了命令行交互中要获取的动态值
- 在write方法中的模板数据上下文修改为动态值
- 运行 yo sample
vue Generator
- 创建一个vue Generator案例步骤 :
- 生成一个理想的项目结构
mkdir generator-songyi-vue
- 进入目录
cd generator-songyi-vue
- 初始化package.json文件
yarn init
- 安装依赖
yarn add yeoman-generator
- vscode打开
code .
-
引入 yeoman-generator
-
导出继承generator的模块
-
在prompting的 prompt方法中写入命令行交互的问题 以及把回答的answers挂载到this上
-
创建templates目录 拷贝项目目录放进templates中作为模板
-
修改模板中可能发生变化的地方使用<%= %>的方式进行替换
-
在writing中把每一个文件通过模板转换到目标路径
-
写入模板文件的相对路径的数组,通过数组遍历的方式通过fs.copyTpl生成文件
-
yarn link 到全局
-
新生成一个目录并进入
-
在新目录下运行 yo songyi-vue 需要输入项目名称 用来替换模板中的项目名称
-
报错因为 <%= BASE_URL %> 并不是以ejs模板字符串的形式输出的, 改为<%%= BASE_URL %> 就可以转译
- 发布Generator
- 一般发布需要进行git托管
- 进入命令行 忽略 node - modules
echo node_modules - git init 初始化本地仓库
- git add . 添加所有文件夹下文件
- git commit -m “first-commit” 创建一次提交
- github创建一个新仓库
- git remote add origin 地址 添加远端仓库
- git push -u origin master
- yarn publish / npm publish 运行后会提示是否要对版本进行修改 输入用户名和密码
运行后会报错原因是 国内会用淘宝镜像取代国外镜像
方法:
修改本地镜像地址
或者运行命令 yarn publish --registry=https://registry.yarnpkg.com
就已经发送成功了 成功后可以通过去全局的方式去进行安装了 再通过yo 去使用
可以添加一个yeoman-generator的关键词 这个时候yeoman的官方会发现
Plop
1. Plop简介
用在项目中创建特定类型的小工具 类似sub generator
不会单独使用都是集成使用的
需要再命令行运行plop然后会有一些我们设置的问题询问 之后plop会根据我们给的选项自动帮我们生成重复的文件
2. Plop基本使用
- 将plop模块作为项目开发依赖进行安装
- 在项目根目录下创建一个plopfile.js文件
- 在plopfile.js文件中定义脚手架任务
- 编写用于生成特定类型文件的模板
- 通过plop 提供的cli运行脚手架任务
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'
}
]
})
}
脚手架的工作原理
- 根据一些预设问题,根据回答替换模板帮你生成一些文件
工作过程:
- 桌面进入命令行 创建文件 mkdir sample-scaffolding
- 进入文件目录 cd sample-scaffolding
- 创建package.json文件 运行yarn init
- vscode打开目录 code .
- 打开package.json 新增bin字段执行cli应用的入口文件
"bin":"cli.js"
- 文件夹下新增cli.js
- 写入固定文件头 #!usr/bin/evn node
// node cli 应用的入口文件必须要有这样固定的文件头
// 如果是linux 或者macOS系统 还需要修改此文件的读写权限修改为755
// 在文件随意写入一个、console.log()语句 为了验证后面 sample-scaffolding是否正常运行 - link到全局 yarn link
- 运行 sample-scaffolding 查看命令行是否有打印正常输出
- 脚手架工作过程:
- 通过命令行询问信息
- 通过用户回答生成文件
- node中使用inquiry模块 yarn global add inquirer
- 载入inquirer
const inquirer = require('inquirer')
- 通过inquirer的prompt方法配置命令行交互的问题
inquirer.prompt([{
type: 'input',
name: 'name',
message: 'Project name',
default: 'sample-scaffolding'
}]).then(answers => {
console.log(answers);
})
- 控制台运行sample-scaffolding 就会弹出个交互命令了 我们回答后控制台会打印我们的问题的键和回答的值
- 新建templates文件并创建模板文件
- 根据用户回答结果生成文件
const path = require('path')
const fs = require('fs')
const ejs = require('ejs')
inquirer.prompt([{
type: 'input',
name: 'name',
message: 'Project name',
default: 'sample-scaffolding'
}]).then(answers => {
console.log(answers);
})
// 8.1 拿到模板目录
const tmplDir = path.join(__dirname, 'tempaltes')
// 8.2 目标目录
const destDir = process.cwd()
// 8.3 将模板下的文件全部转换到目标目录
fs.readdir(tmplDir, (err, files) => {
// 8.4 如果有err返回出去
if (err) throw err
// 8.5 遍历查看files是什么
files.forEach(item => {
console.log(item); // 7.6 打印了文件的相对路径
// 8.7 通过模板引擎去渲染对应路径下的文件
// 8.8 命令行安装模板引擎并引入yarn add ejs
// 8.9 通过模板引擎的readFile方法来渲染模板文件到目标路径
ejs.renderFile(path.join(tmplDir, file), answers, (err, result) => {
if (err) throw err
console.log(result); //已经是模板引擎转换过的文件
// 8.10 通过目标文件目录写入转换好的模板文件
fs.writeFileSync(path.join(destDir, file), result)
})
})
})
})
- 创建新文件
- 使用新的脚手架 输入项目名称 在目标文件就生成了一个我们脚手架的文件目录了.