Yeoman使用踩坑记

官网传送门:https://yeoman.io/authoring/index.html


1.npm link 后,yo name 报错:

Error: EACCES: permission denied, open '/Users/sherry/Library/Preferences/insight-nodejs/insight-yo.json.1293917385'

    at Object.openSync (fs.js:443:3)

    at Function.writeFileSync [as sync] (/Users/sherry/.nvm/versions/node/v10.16.3/lib/node_modules/yo/node_modules/write-file-atomic/index.js:212:13)

    at Conf.set store [as store] (/Users/sherry/.nvm/versions/node/v10.16.3/lib/node_modules/yo/node_modules/conf/index.js:142:19)

    at Conf.set (/Users/sherry/.nvm/versions/node/v10.16.3/lib/node_modules/yo/node_modules/conf/index.js:64:14)

    at Insight.set optOut [as optOut] (/Users/sherry/.nvm/versions/node/v10.16.3/lib/node_modules/yo/node_modules/insight/lib/index.js:56:15)

    at Object. (/Users/sherry/.nvm/versions/node/v10.16.3/lib/node_modules/yo/lib/cli.js:206:18)

    at Module._compile (internal/modules/cjs/loader.js:778:30)

    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)

    at Module.load (internal/modules/cjs/loader.js:653:32)

    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)

【解决方式】

sudo chown -R Sherry /Users/sherry/Library/Preferences/insight-nodejs


2.yeoman工程的基础目录结构设计(个人设计,仅供参考)

【各文件夹分工】

generators:存放各种 generator,其中,app/index.js 用于脚手架创建的全流程控制逻辑。可以使用 this.composeWiith('../generator1') 引入其他 generator 的功能。

projects:存放待生成给用户使用的,完整脚手架(这里,脚手架也可以选择不存放到 yeoman 工程本地,放到独立的 git 仓库,进行远程引用)

根目录下的 package.json:服务于 yeoman 工程

projects/vue、projects/react等目录下的package.json:服务于业务。留给用户去手动 install


3.Managing Dependencies(npm包管理)

生命周期 install(),专门用来执行 npm 包的安装。用法如下:

install() {

   this.yarnInstall();

   // 使用yarn/npm,自选 

   // this.npmInstall();

}

【解析】

这里,相当于在命令行执行 yarn / npm。

直接安装 根目录 下的package.json。

!!注意!! 无论在哪个子generator 中的 install 调用 this.yarnInstall,都只会安装 根目录 下的 package.json。如果子 generator 文件夹中有定义 package.json,它定义的包不会被安装。

当你需要安装指定的包时:

this.npmInstall(['lodash'], { 'save-dev': true });

相当于在根目录执行:

npm install lodash --save-dev

当你需要向现有的 package.json 中动态添加些依赖,或者,不想创建 package.json 文件时,你可以这样:

这里的 this.destinationPath('package.json'),是在创建 package.json 文件。默认在根目录下创建。

如果根目录下已经存在 package.json,yeoman 会提示用户,存在文件冲突,根据用户的选择,决定是否在已有的 package.json 文件中写入 pkgJson 内容。

【注】

截图中的代码,无论写在 app/index.js 中,还是形如 generator1/index.js 中,this.destinationPath('package.json') 都只是在根目录下创建 package.json,而不是在当前 generator 文件夹下创建。


那么,如果想改变其他目录下的 package.json(如动态改变某个工程的package.json),怎么办?

假如自定义 generator 的目录结构如下(generators和node_modules同级,都是根目录下的一级文件夹):

当期望向 vue/package.json 中动态写入一些 dependencies 定义:

    writing() {

        const pkgJson = {

            dependencies: {

                vue: '^2.0.0'

            }

        };

        this.fs.extendJSON(this.destinationPath('projects/vue/package.json'), pkgJson);

    }

【个人思考】

动态写入 dependencies,尤其适用于用户选择是否使用某种功能(某个模块)的情况。

例如:

用户交互时,选择使用 redux,则可以这样动态写入 redux 包引用。否则,脚手架的 package.json 中,默认不写入 redux 引用。


但要时刻注意,这里仅仅只是进行 package.json 的写入,并不会执行安装。

任何地方的 install() 中调用 this.yarnInstall(),都只会执行根目录下 package.json 的包安装。

这个也很好理解。因为我们开发的是自定义的 generator,因此,执行包安装,理应服务于这个 yeoman 工程,而不是它内部的其他子工程(脚手架)。

而脚手架中的 package.json,也理应由用户创建项目后,自行手动安装。


4.Interacting with the file system(文件系统交互)

(1)各种路径的获取方式、自定义方式


· destinationRoot:生成文件的存放目录(目标文件夹)

【获取】this.destinationRoot() 

***默认值***

如果当前执行 yo name 的目录下包含.yo-rc.json,则为当前文件夹。

否则,则为最近的、包含.yo-rc.json的父文件夹。

如果当前文件夹、及所有父文件夹,都不包含.yo-rc.json,则在当前目录下创建.yo-rc.json,并以当前目录作为生成文件存放的默认目录。

【自定义】this.destinationRoot('new/folder')

【生成文件的路径定义】this.destinationPath('index.js') —— 在 this.destinationRoot() 目录下,生成 index.js

· contextRoot:用户当前执行 yo 指令的目录

【获取】this.contextRoot


·sourceRoot:(用于复制的)模板文件的存放目录

【获取】this.sourceRoot() 

***默认值***

与当前调用 this.sourceRoot() 的 generator 的 index.js 同级的 templates 文件夹。

例如,在 app/index.js 调用 this.sourceRoot(),sourceRoot 默认指向如图:

【自定义】this.sourceRoot('new/folder') —— 根目录下的 new/folder 文件夹

【注意】

自定义为:this.sourceRoot('./new/folder') ,指向同上。依然指向根目录下的 new/folder 文件夹,而不是在当前文件所在目录下寻找 new/folder

【模板文件的路径指定】this.templatePath('tpl.html') —— 去 this.sourceRoot() 下,找 tpl.html 文件

(2)格式化生成的文件

例如:

使用这个包,会把生成的文件(也就是写入到this.destinationPath的那个文件),按照图中指定的规则格式化。


5. .yo-rc.json 文件

作用:用来存放所有 generators 的配置对象。

可通过 this.config.xxx api 进行配置的设置、获取等操作。详见官网:https://yeoman.io/authoring/storage.html

形如:

【注】

每一个 generator 一个命名空间。不能通过 this.config.xxx 进行配置信息的共享。

可以通过 options 和 arguments 在多个 generator 间分享数据。(具体使用方式及意义待测试)


6.在任意文件夹下,执行 yo name 创建项目,逻辑流程运行过程中的各种 permission denied 错误(mkdir / rm -rf / this.fs.copyTpl)

网上大家都说设置chmod +w filename,试了,无效。mac系统。

实测,假如在 test 目录下执行 yo name,报 permission denied 错误,请尝试!!👇

sudo chown -R userName test


7.this.fs.copyTpl 的回调问题

首先明确一点,this.fs.copyTpl 是同步方法,并不是异步的,因此,没有提供回调函数。

可能你也遇到了和我一样的问题:

使用 this.fs.copyTpl 生成了一些文件夹,并在 this.fs.copyTpl 调用后面,执行删除操作,期望删掉某些/某个文件夹。但是发现,并删不掉。

于是,很自然的觉得,这是异步问题,我只要在 this.fs.copyTpl 的回调里面去删,就 ok 了。

但是,如前所述,this.fs.copyTpl 其实是同步方法。

那么,是什么原因造成了无法删除的问题呢?

【答案是】

yeoman 在进行文件处理的时候,把所有即将生成的文件/文件夹都放在了内存里,而不是直接写到磁盘上。

因此,这时候执行,形如 shelljs.rm('-rf', 'xxxxx') 的操作,是不会成功的。因为所有的文件,都还没有写到磁盘上。

详见官网说明:https://yeoman.io/authoring/file-system.html

【解决方法】

在 install() 或 end() 中,进行 shelljs.rm('-rf', 'xxxxx') 这类操作。从语义上,建议在 end() 中执行。

原理:在文件/文件夹写入磁盘后操作。

【解析】

yeoman 共计 8 个生命周期函数,执行顺序如下:

initializing: 1

prompting: 2

configuring: 3

default: 4

// 自定义的原型方法在这个地方按顺序执行

writing: 5

conflicts: 6

// 文件/文件夹写入磁盘,在这里进行

install: 7

end: 8


8.关于argument和option

(1)argument

【如何定义】

constructor(args, opts) {

    super(args, opts);

    this.argument('projectName', {

        type: Array,

        required: false, // 这里不设置,或 this.argument 不传第二个 options 参数,默认都为 必传

        default: this.appname, // 运行 yo name 的文件夹名称

        desc: '项目名称'

    });

}

【如何使用】

yo name my-project

【如何读取】

this.log('argument projectName:', this.options.projectName);

【是否定义多个argument?】

—— 可以。

多个 argument 如何区分?

—— 通常,yo name argument1 argument2 传入多个 argument 时,按照 this.argument 的定义顺序分别赋值。

eg:

this.argument('name');

this.argument('age');

=> this.options.name === argument1

     this.options.age === argument2

【注】

argument 为数组的情况,会取当前定义位置之后的所有 argument 的集合。

定义eg:

this.argument('name');

this.argument('friends', {

    type: Array,

    required: false,

    default: [], // 运行 yo name 的文件夹名称    

    desc: '朋友们'

})

this.argument('age');

使用eg:

yo name Sherry Dennis Jack Tom 25

结果:

this.options.friends:[Dennis, Jack, Tom, 25]

this.options.age:Jack

(2)option(类似flag)

【如何定义】

this.option('coffee', {

    alias: 'co'

})

【如何使用】

yo name --coffee / yo name --co

【如何读取】

this.log('argument projectName:', this.options.coffee);

【查看我们自定义的option】

yo name --help

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容