前几天看了一篇文章大受启发:我理想中的前端工做流,如今工做中一直在使用gulp和webpack作自动化,在单独项目中效果很不错。可是随着项目逐渐怎多,是须要使用一个工具来帮你快速建立和规范项目。javascript
Yeoman是一个脚手架,能够快速生成一个项目的骨架。官网上有不少你们已经写好的脚手架,也能够本身写一个适合本身的,接下来我会翻译下官网的教程,学习的同时把经验分享给你们。css
Yeoman只是帮咱们生成项目的骨架是远远不够的,官网上介绍,Yeoman是由三部分组成的:脚手架工具 - Yo、构建工具 - Grunt or Gulp、包管理工具 - Bower or npm。html
翻译yeoman官网Creating a generator流程(一)Getting started 快速开始
(二)Running Context 生命周期
(三)User Interactions 和使用者互动
(四)composability 组合
(五)Managing Dependencies 依赖管理
(六)Interacting with the file system 文件操做前端
原文地址:http://yeoman.io/authoring/index.htmlvue
1.首先要创建一个文件夹,在这个文件夹内写你的generator,这个文件夹的名字 必须 被命名为generator-name
,name为你generator的名字,假如我想写一个vue的脚手架,我能够命名为:generator-vue
,这个很关键,Yeoman文件系统只会信任这种规范的generator。java
mkdir generator-vue
2.创建node模块,首先要必备文件 package.json
,这个文件能够经过执行 npm init
指令来生成,前提是须要安装 node 及 npm。node
{ "name": "generator-vue", "version": "0.1.0", "description": "", "files": [ "app", "router" ], "keywords": ["yeoman-generator"], "dependencies": { "yeoman-generator": "^0.20.2" } }
几点要求:webpack
1. name:必须格式为 `generator-你项目的名字`。 2. keywords:数组中必须有 `yeoman-generator`,这样你的项目才会被[Yeoman官方的generators列表](http://yeoman.io/generators/)所收录。 3. 若是须要添加其余的属性能够去[npm官网文档](https://docs.npmjs.com/files/package.json#files)中查看。
经过1.1步骤已经有了package.json,下一步在新建两个文件夹分别叫app和router,结构以下。git
├───package.json ├───app/ │ └───index.js └───router/ └───index.js
当你执行Yeoman指令 yo vue
(上面你已经创建的项目名字)的时候,他会默认执行你根目录下app/index.js的内容,因此一个新项目,app/
目录是必须的。github
router/
做为子项目,能够经过 yo vue:router
来执行。
├───package.json └───generators/ ├───app/ │ └───index.js └───router/ └───index.js
若是不喜欢把全部项目都放在根目录下,Yeoman还容许把项目放在 generators/
下面,改写上面的例子:
├───package.json └───generators/ ├───app/ │ └───index.js └───router/ └───index.js
若是更改了文件目录,要同步修改 package.json
中对应文件的目录结构:
{ "files": [ "generators/app", "generators/router" ] }
module.exports = generators.Base.extend({ // The name `constructor` is important here constructor: function () { // Calling the super constructor is important so our generator is correctly set up generators.Base.apply(this, arguments); // Next, add your custom code this.option('coffee'); // This method adds support for a `--coffee` flag } });
module.exports = generators.Base.extend({ method1: function () { console.log('method 1 just ran'); }, method2: function () { console.log('method 2 just ran'); } });
下一步的时候当你运行generator的时候,会看到这两句console输出在控制台。
在项目跟路径下 generator-name(vue)/
执行指令:
npm link
过程当中,将会安装node模块依赖,和建立软链接指向你当前项目。
//1.到本地全局node模块路径下 cd /usr/local/lib/node_modules //2.查看列表 ll //3.会看到已经安装了一个全局的geneator-vue模块 npm geneator-vue -> /Users/lvjinlong/generator-vue gulp .. //4.此时在任意新建的项目文件夹中yo项目的名字,会看到上面实例中的console打印出来的结果。 yo vue
安装geneator的时候,Yeoman会搜索你的文件夹,会把包含 .yo-rc.json
文件的文件夹做为你的根目录来初始化项目。
问:那么,.yo-rc.json
是个什么东西呢?
答:当你 第一次 调用this.config.save()
的时候,系统会生成这个文件。问:那么,
this.config.save()
这个方法的做用是什么呢?
答:官网 这篇文章会有讲解,大致意思是会利用.yo-rc.json
来存储或是读取用户相关信息。
因此当你初始化一个项目的时候,别忘记清除掉以前系统生成的.yo-rc.json
。
原文地址:http://yeoman.io/authoring/running-context.html
每一个方法会直接附加在generator原型上做为一个action,每一个action按照必定的循序执行在Yeoman的生命周期中。
这些方法至关于直接执行了 Object.getPrototypeOf(generator)
,
全部方法都会 自动执行 。若是不想都自动执行,请往下看。
只有私有方法在Yeoman中才不会自动执行,下面有三种办法帮你建立一个私有方法。
_method
)generators.Base.extend({ init: function () { this.helperMethod = function () { console.log('won\'t be called automatically'); }; }; });
var MyBase = generators.Base.extend({ helper: function () { console.log('won\'t be called automatically'); } }); module.exports = MyBase.extend({ exec: function () { this.helper(); } });
Yeoman中的定义了生命周期钩子,和这些钩子命名相同的会按照顺序执行,若是和这些钩子名称不同则默认为 default
这些生命周期钩子 按顺 序为:
原文地址:http://yeoman.io/authoring/user-interactions.html
Yeoman默认在终端中执行,可是也支持在多种不一样工具中执行。这时候咱们使用 console.log()
或是 process.stdout.write()
用户就可能看不到,Yeoman中使用 generator.log()
来统一打印输出结果。
提示框是Yeoman主要和用户交流的手段,是经过Inquirer模块来实现的,全部的API及参数能够看这里,执行如下实例看下效果:
module.exports = generators.Base.extend({ prompting: function () { var done = this.async(); this.prompt({ type : 'input', name : 'name', message : 'Your project name', default : this.appname // Default to current folder name }, function (answers) { this.log(answers.name); done(); }.bind(this)); } })
一个肯定的答案,好比账号,用户可能屡次提交同一个答案,这时候能够用Yeoman提供 store
来存储这些答案。
this.prompt({ type : 'input', name : 'username', message : 'What\'s your Github username', store : true }, callback);
这时候会在跟路径下生成一个.yo-rc.json
文件,里面会存储name信息。能够参考官网storage这一节
参数直接经过命令行传递,例如:
yo webapp my-project
这个例子中,my-project 是第一个参数。
通知系统咱们须要参数,咱们使用 generator.argument()
方法,这个方法接受两种形式:
hash(key-value) -- 哈希值的形式,接受如下参数做为key值
var _ = require('lodash'); //须要提早安装lodash模块,提供一些经常使用方法 module.exports = generators.Base.extend({ //注: arguments和options必须在constructor中定义. constructor: function () { generators.Base.apply(this, arguments); //appname为一个必须的参数 this.argument('appname', { type: String, required: true }); //用驼峰式把这个参数保存起来 this.appname = _.camelCase(this.appname); } });
Options(选项)看起来像是Arguments(参数),可是他们是在命令行中的标志。
实例:举一个官网团队的脚手架demo - webapp - 15行
module.exports = generators.Base.extend({ constructor: function () { generators.Base.apply(this, arguments); this.option('skip-welcome-message', { desc: 'Skips the welcome message', type: Boolean }); } })
yo webapp --skip-install
输出信息使用 generator.log
模块,和js的 console.log()
基本一致。
module.exports = generators.Base.extend({ myAction: function () { this.log('Something has gone wrong!'); } });
传值的方式同Arguments(参数),字符串或hash。区别是参数:
* desc:描述 * alias:简写(--version 简写为 -v) * type:[ Boolean | String | Number ] * defaults:默认值 * hide :[ Boolean ] 是否隐藏帮助信息
原文地址:http://yeoman.io/authoring/composability.html
颇有趣的是,官网的第一个demo居然是一个变形金刚组合的gif,可见他们是多么想表达各个小功能组合起来后的yeoman是有多强大。
能够经过如下两种方式开始组合:
generator-backbone
使用 generator-mocha
)。sass
或者 less
来搭配 webpack
或是 gulp
)generator.composeWith()
composeWith
方法容许你的generator来组合别人的generator,可是一旦组合成功,不要忘记第二章的内容 <(二)Running Context 生命周期>,全部被组合的generator都遵循Yeoman的生命周期规则来顺序执行,不一样的generator执行顺序,取决于composeWith
调用他们的顺序,看下面的API及执行顺序实例。
composeWith
接收三个参数:
namespace
:声明generator和谁组合。[ String ]options
:调用generator的时候须要接收的参数。[ Object | Array ]settings
:你的generator用这些配置来决定若是运行其余的generators。[ Object ]
settings.local
:须要在 dependencies
中配置,使用dependencies安装的模块至关于本地模块,这里使用 require.resolve
来返回一个本地模块的路径,如:node_modules/generator-name
[ String ]settings.link
:weak
or strong
[ String ]
week
link:在初始化的时候不运行,好比后端运行的,frameworks或css的预处理。strong
link:一直运行。当须要用 peerDependencies
来组合generator
this.composeWith('backbone:route', { options: { rjs: true }});
当须要用 dependencies
来组合generator
this.composeWith('backbone:route', {}, { local: require.resolve('generator-bootstrap') }); //注:require.resolve()将返回node.js须要的模块路径。
接下来4.2中会解释 peerDependencies
和 dependencies
的区别。
// In my-generator/generators/turbo/index.js module.exports = require('yeoman-generator').Base.extend({ 'prompting' : function () { console.log('prompting - turbo'); }, 'writing' : function () { console.log('writing - turbo'); } }); // In my-generator/generators/electric/index.js module.exports = require('yeoman-generator').Base.extend({ 'prompting' : function () { console.log('prompting - zap'); }, 'writing' : function () { console.log('writing - zap'); } }); // In my-generator/generators/app/index.js module.exports = require('yeoman-generator').Base.extend({ 'initializing' : function () { this.composeWith('my-generator:turbo'); this.composeWith('my-generator:electric'); } });
来分析下上面这段脚本:
composeWith
方法 turbo 和 electric。因此执行后的结果以下:
prompting - turbo prompting - zap writing - turbo writing - zap
peerDependencies
和 dependencies
的区别npm容许如下三种dependencies(依赖):
dependencies
:使用依赖,本身或是别人使用你的generator所必备的依赖模块。这些模块被generator视为本地模块。peerDependencies
:看下面的 注: npm@3后,peerDependencies不会再被自动安装,须要手动。devDependencies
:开发依赖,做为开发或者是测试须要用的模块,若是别人安装你的generator,这些模块不该该被安装。当使用 peerDependencies
别的模块也要依赖当前这个模块,当心不要建立版本致使冲突,Yeoman推荐使用(>=) 或 (*) 来安装可用的版本,如:
{ "peerDependencies": { "generator-gruntfile": "*", "generator-bootstrap": ">=1.0.0" } }
注:npm@3之后,peerDependencies
不会再被自动安装,安装他们必须执行以下:
npm install generator-yourgenerator generator-gruntfile generator-bootstrap@">=1.0.0"
原文地址:http://yeoman.io/authoring/dependencies.html
Yeoman提供如下几种形式来安装依赖。
使用 generator.npmInstall()
来安装npm包,若是你在多个generators调用了 npm install
Yeoman保证只会执行一次。
例如:你须要安装 lodash 这个模块做为发开依赖。
generators.Base.extend({ installingLodash: function() { this.npmInstall(['lodash'], { 'saveDev': true }); } });
效果等同于直接在终端输入:
npm install lodash --save-dev
使用 generator.bowerInstall()
来安装依赖。实例:同npm。
使用 generator.installDependencies()
来同时安装npm 和 bower。实例:同npm。
可使用 spawnCommand
来安装其余工具。好比:PHP的composer。
原文地址:http://yeoman.io/authoring/file-system.html
Yeoman会在这个根路径中建立你项目的脚手架。
根路径会以如下两种方式定义:
.yo-rc.json
的路径你能够经过Yeoman提供的 generator.destinationRoot()
方法来获取根路径,这个方法接收一个参数 generator.destinationPath('sub/path')
来获取子目录的路径。
例如:
查看当前路径
$ pwd ~/projects
//跟路径是 ~/projects generators.Base.extend({ paths: function () { this.destinationRoot(); // returns '~/projects' this.destinationPath('/sub/index.js'); // returns '~/projects/sub/index.js' } });
原文是Template context,其实我感受直译不太好,换作叫经常使用工做路径会更好。
这个路径的默认取你当前目录 ./templates/
, 能够手动覆盖这个路径 generator.sourceRoot('new/template/path')
例如:
generators.Base.extend({ paths: function () { this.sourceRoot(); //设置经常使用工做路径 // returns './templates' this.templatePath('index.js'); //读取经常使用工做路径 // returns './templates/index.js' } });
全部文件相关的方法都会经过 this.fs
暴露出来。这里有全部文件操做相关方法,包括下面的copyTpl
方法。
实例: 把一个 经常使用工做路径
的文件复制到 根路径
下,并传一个参数。
./templates/index.html
内容是:<html> <head> <title><%= title %></title> </head> </html>
copyTpl
方法把来复制文件,该方法使用ejs模板语法 generators.Base.extend({ writing: function () { this.fs.copyTpl( this.templatePath('index.html'),//第一个参数:from this.destinationPath('public/index.html'),//第二个参数:to { title: 'Templating with Yeoman' }//第三个参数:options ); } });
public/index.html
<html> <head> <title>Templating with Yeoman</title> </head> </html>
Yeoman提供 registerTransformStream()
方法,使用gulp的来操做文件。
例如:
var beautify = require('gulp-beautify'); this.registerTransformStream(beautify({indentSize: 2 }));
Yeoman介绍了几个比较流行的解析器:
var cheerio = require('cheerio'), $ = cheerio.load('<h2 class="title">Hello world</h2>'); $('h2.title').text('Hello there!'); $('h2').addClass('welcome'); $.html(); //=> <h2 class="title welcome">Hello there!</h2>
本次只翻译了前六章,后续会翻译后六章、本身若是写一个generator以及遇到的坑和问题。都会更新在个人github的Yeoman-article中。