前端工程化在项目创建阶段主要依靠脚手架工具,可以说脚手架工具是前端工程化的发起者。脚手架可以简单的理解为,自动的创建项目基础文件的一个工具。除了创建文件,它更多的是给开发者提供一种约定和规范。所以脚手架的本质作用就是创建项目的基础结构、提供项目规范和约定。通常被用于开发相同类型项目提供相同的约定,包括相同的文件组织结构、相同的代码开发范式、相同的模块依赖甚至还有一些相同的工具配置和一些基础的代码。脚手架可以快速搭建相同类型的项目骨架,然后基于这个骨架进行后续的开发工作。IDE创建项目的过程就是一个脚手架的工作流程。
常用的前端脚手架工具:
脚手架工具分为两类,一类是特定项目类型的脚手架,像创建react项目的 creat-react-app,它会根据提供的信息创建对应的项目基础结构;一类是通用类型的脚手架,像Yeoman,他们可以根据模版一套模版生成一个对应的项目结构,这种类型的脚手架一般都很灵活而且容易扩展,这些都是在项目创建阶段用的脚手架。还有一种在项目开发过程中用到的叫Plop,用于去创建一些特定类型的文件。例如在组件化的项目当中创建新的组件或者模块化项目当中创建一个新的模块,这些组件或模块都是由特定的几个文件组成的,而且每个文件都有一些基本的代码结构。相对于手动一个一个去创建的化脚手架会提供更为便捷的、更为稳定的一种操作方式。
Yeoman简介:
The web's scaffolding tool for modern webapps。
yeoman是一款最老牌、最通用的脚手架工具,有更多值得学习和借鉴的地方。不同于 Vue-cli 这样的工具 Yeoman 更像是一个脚手架的运行平台,可以通过Yeoman搭配不同的Generator去创建任何类型的项目。也就是说可以创建自己的Generator,从而去定制属于我们自己的前端脚手架。Yeoman的优点同时也是它的缺点,在很多专注基于框架开发的人眼中Yeoman就过于通用不够专注,所以他们更愿意使用像vue-cli这类的脚手架。
Yeoman 基础使用:
Yeoman是一款基于node开发的工具模块,使用Yeoman的第一步就是通过npm在全局范围去安装它。yarn global add yo Yeoman 通过搭配特定的Generator 才能使用,使用Yeoman创建工具必须要找到对应项目的类型的Generator。Generator 也是通过npm来安装 yarn add global add generator-node
Sub Generator:
有时候我们不需要去创建完整的项目结构,而是在原来的项目基础上创建一些特定类型的文件。例如我们给一个已经存在的项目创建readme,又或是我们在一个原用的项目之上去添加某些类型的配置文件,比如说ES-lint或者Bable的配置文件,这些配置文件都有一些基础代码,如果手动去写很容易配错,我们可以通过生成器自动帮我们去生成,这样的话会提高我们的效率。如果说你需要这样的一些需求,你可以使用Yeoman所提供的 Sub Generator 这样一个特性来实现。具体来看我们通过在项目目录下去运行一个特定的Sub Generator的命令去生成对应的文件,运行Sub Generator的方式就是在原有的Generator名字后面冒号跟上Sub Generator 的名字 yo node:cli
Yeoman 使用步骤总结:
- 明确你的需求;
- 找到合适的
Generator; - 全局范围安装你找到的
Generator; - 通过
Yo运行对应的Generator; - 通过命令行交互填写选项;
- 生成你所需要的项目结构;
创建 Generator 模块:
Generator本质上就是一个NPM模块,Generator有一个特定的结构,它需要在根目录下有一个Generators的文件夹然后在这个文件夹下面再去存放一个app的文件夹。用于去存放我们生成器对应的代码,如果需要提供多个的Sub Generator可以在app的同级目录再去添加一个新的生成器目录。除了特定结构还有一个和普通npm模块不同的是,Yeoman的Generator它的模块名称必须是generator-<name>的这种格式。项目初始化之后通过 yarn add yeoman-generator安装 yeoman-generator ,这个模块它提供了生成器的基类。在这个基类当中提供了一些工具函数,在创建生成器的时候更加便捷。
// generator-sample/generators/app/index.js
// 此文件作为 Generator 的核心入口 需要导出一个继承自 Yeoman Generator 的类
// Yeoman Generator 工作时会自动调用我们在此类型中定义的一些生命周期方法
// 我们可以在这些方法当中通过调用父类提供的一些工具方法实现一些功能,例如文件写入
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
writing () { // Yeoman 在文件生成阶段自动调用这个方法
this.fs.write( // 高度封装的 file-system 模块
this.destinationPath('temp.tex'), // 写入文件的绝对路径
Math.random().toString() // 写入文件的内容
)
}
}
通过 yarn link 将组件注册到全局,然后新建一个文件夹运行 yo sample 。就可以看到生成的结果。
很多时候,我们需要自动去创建的文件很多,而且文件的内容也相对复杂。在这样的一种情况下我们就可以使用模板去创建文件,这样可以更加便捷一些。具体的操作是先在生成器的目录下添加一个 templates 目录,然后将要生成的文件都放入 templates 目录作为模版,模版中完全遵循 ejs 模版语法。
// generator-sample/generators/templates/foo.txt
<%= title %>
<% if (success) { %>
成功的状态
<% } %>
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
writing () { // 通过模版的方式写入文件到目标目录
const tmpl = this.templatePath('foo.txt') // 模版文件路径
const output = this.destinationPath('foo.txt') // 输出路径
const context = {title: 'Hello Generator ...', success: true} // 模版文件上下文
this.fs.copyTpl(tmpl, output, context)
}
}
对于模版中的一些动态数据,可以通过命令行交互的方式去询问使用者从而得到。在Generator当中想要发起一个命令行交互的询问我们可以通过实现Generator这个类型当中的prompting方法,在这个方法当中我们可以去调用父类所提供的prompt发出对用户的命令行提问,这个方法返回一个promise。
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 tmpl = this.templatePath('bar.html')
const output = this.deationationPath('bar.html')
const context = this.answers
this.fs.copyTpl(tmpl, output, context)
}
}
发布Generator:
Generator 其实就是 npm 模块,发布一个 generator 就是发布一个 npm 模块。具体在做之前一般会将这个项目的源代码托管到一个公开的源代码仓库上面,首先要创建一个本地的仓库。在创建本地仓库前。
- 创建一个
.gitignore用于去忽略node_modules目录echo node_modules > .gitignore。 - 有了
.gitignore这个文件之后,在通过git init去初始化一个本地的空仓库。 - 有了本地空仓库之后,通过
git status去检查一下本地仓库文件的状态是否被跟踪。 - 然后通过
git add .添加当前目录下所有的文件。 - 使用
git commit创建一次提交git commit -m "feat:inital commit"。 - 再创建一个远端的仓库,把本地的仓库同步到远端
github => new repository把远端仓库地址复制下来。 - 执行
git remote add origin远端地址 这样就为我们本地的仓库添加一个远端仓库的别名。 - 执行
git push -u origin master就把本地master分支的代码推送到远端的master分支。 - 执行
yarn publish发布这个模块,如果使用的是淘宝的镜像源yarn publish --registry=https://registry.yarnpkg.com