Yeoman,教你快速打造自己的腳手架

yeoman.png

不造大家在實際開發(fā)項目中浆熔,有沒有這樣的困惑本辐,就是每次起一個新的項目,腳手架都要從舊有的項目copy医增,然后改名慎皱、刪除內(nèi)容,留下基本框架叶骨,最后還有npm install茫多,安裝包。并且忽刽,經(jīng)常會因為插件的版本問題天揖,導(dǎo)致運行出錯(當然,如果你所在的小組有一套完整的工具流跪帝,可以忽略我)今膊。

身為程序媛的我,怎么可以忍受這種不高bigger的項目腳手架搭建方式呢歉甚?

還好万细,有Yeoman來相助。

搭建腳手架必備工具

  • yeoman
  • 腳手架模板

起始準備

  • 確定你安裝了node和npm纸泄,node的版本要求在4.0以上赖钞,npm要求與node相匹配的版本。
    版本號可以通過以下方式查看:
node-version.png
  • 全局安裝yeoman
sudo npm install -g yo
  • 查看版本
yo-version.png

創(chuàng)建屬于你自己的generator

創(chuàng)建文件目錄

  • 創(chuàng)建文件夾聘裁,文件夾名為generator-name雪营,name是你創(chuàng)建的generator的名字。這里我以generator-gulp為例衡便,創(chuàng)建以gulp為構(gòu)建工具的腳手架

  • 創(chuàng)建package.json

npm init
  • 創(chuàng)建文件夾app献起、templates,文件index.js

  • 現(xiàn)在的文件目錄如下:

  - generator-gulp
    - app
      - templates  // 存放腳手架目錄
      - index.js     // 對腳手架進行操作的代碼
    - package.json

修改package.json

{
    "name": "generator-gulp",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [
        "yeoman-generator"
    ],
    "author": "huangxiaoyan",
    "license": "ISC",
    "dependencies": {
        "del": "^2.2.0",
        "yeoman-generator": "^0.23.3"
    }
}

安裝插件

執(zhí)行npm install镣陕,安裝yeoman-generator和del這兩個插件

npm install

創(chuàng)建腳手架模板

我以基于gulp的腳手架為例谴餐。分為pc端和移動端這兩種模板,創(chuàng)建后的目錄如下:

  - templates
    - mobile
      - html
      - js
      - sass
      -images
    - pc
     - html
      - js
      - sass
      -images
    - gulpfile.js
    - package.json

編寫index.js

這是最重要最關(guān)鍵的一步呆抑。

Yeoman提供了多個方法來搭建你自己的腳手架岂嗓。具體的可以去看看官方文檔,在這里鹊碍,我只抽取里面主要的方法來完成腳手架的搭建厌殉。

先上框架版的index.js

var generators = require('yeoman-generator'),
    _ = require('yeoman-generator/node_modules/lodash'),
    glob = require('yeoman-generator/node_modules/glob'),
    chalk = require('yeoman-generator/node_modules/chalk'),
    log = console.log,
    fs = require('fs'),
    path = require('path'),
    del = require('del'),
    generatorName = 'gulp';  // 記住這個名字食绿,下面會有用

 // 導(dǎo)出模塊,使得yo xxx能夠運行
module.exports = yeoman.generators.Base.extend({
    constructor: function () {
        // 默認會添加的構(gòu)造函數(shù)
        yeoman.generators.Base.apply(this, arguments);
    },
    prompting: function () {
         // 詢問用戶
    },
    writing: {
        // 拷貝文件公罕,搭建腳手架
    },
    end: {
        // 搭建完執(zhí)行的操作
    }
})

constructor

在這個階段器紧,檢查腳手架是否已經(jīng)存在,如果存在楼眷,則退出铲汪。

  constructor: function(){
        generators.Base.apply(this, arguments);

        // 檢查腳手架是否已經(jīng)存在
        var dirs = glob.sync('+(src)');
        //now _.contains has been abandoned by lodash,use _.includes
        if(_.includes(dirs, 'src')){
            // 如果已經(jīng)存在腳手架,則退出
            log(chalk.bold.green('資源已經(jīng)初始化罐柳,退出...'));
            setTimeout(function(){
                process.exit(1);
            }, 200);
        }
    },

prompting

詢問用戶桥状,根據(jù)答案生成不同模板的腳手架

  prompting: function(){
        var questions = [
            {
                name: 'projectAssets',
                type: 'list',
                message: '請選擇模板:',
                choices: [
                    {
                        name: 'PC模板',
                        value: 'pc',
                        checked: true   // 默認選中
                    },{
                        name: 'Mobile模板',
                        value: 'mobile'
                    }
                ]
            },
            {
                type: 'input',
                name: 'projectName',
                message: '輸入項目名稱',
                default: this.appname
            },
            {
                type: 'input',
                name: 'projectAuthor',
                message: '項目開發(fā)者',
                store: true,   // 記住用戶的選擇
                default: 'huangxiaoyan'
            },{
                type: 'input',
                name: 'projectVersion',
                message: '項目版本號',
                default: '0.0.1'
            }
        ]
        return this.prompt(questions).then(
            function(answers){
                for(var item in answers){
                    // 把answers里的內(nèi)容綁定到外層的this,便于后面的調(diào)用
                    answers.hasOwnProperty(item) && (this[item] = answers[item]);
                }
            }.bind(this));
    }

writing

copy文件到指定目錄硝清,生成腳手架辅斟。

writing: function(){
        /**
        * 可以在prompting階段讓用戶輸入
        * 也可以指定,完全根據(jù)個人習(xí)慣
        **/
        this.projectOutput = './dist';
        //拷貝文件
        this.directory(this.projectAssets,'src');
        this.copy('gulpfile.js', 'gulpfile.js');
        this.copy('package.json', 'package.json');
    }

end

生成腳手架后芦拿,進行的一些處理士飒。

end: function(){
          /**
          * 刪除一些多余的文件
          * 由于無法復(fù)制空文件到指定目錄,因此蔗崎,如果想要復(fù)制空目錄的話
          * 只能在空文件夾下建一個過渡文件酵幕,構(gòu)建完后將其刪除
        **/
        del(['src/**/.gitignore','src/**/.npmignore']);
        var dirs = glob.sync('+(node_modules)');
        if(!_.includes(dirs, 'node_modules')){
            // 將你項目的node_modules和根目錄下common-packages的node_modules進行軟連接
            // 為什么要這樣做,大家可以先想想
            this.spawnCommand('ln', ['-s', '/usr/local/lib/node_modules/common-packages/'+generatorName+'/node_modules', 'node_modules']);
        }
    }

最后一步

generator-gulp目錄下執(zhí)行

npm link

這一步將generator-gulp軟連接到你的usr/local/lib/node_modules/generator-gulp缓苛。
這樣運行yo時芳撒,就可以找到這個generator-gulp

未解決的問題

最后還有一個問題,就是為什么在end階段要對node_modules進行軟連接呢未桥?

因為這樣每次構(gòu)建腳手架的時候笔刹,不需要每次都去安裝插件,不需要每次都去執(zhí)行npm install冬耿,并且可以保證包的版本號一致舌菜。

common-packages

我們可以創(chuàng)建這樣的一個目錄,專門存放需要的node_modules亦镶。common-packages就是這樣的一個功能日月。
目錄結(jié)構(gòu)如下:

- common-packages
  - gulp
    - package.json
    - node_modules

其中,gulp這個文件名是跟你的generatorName是一致的缤骨。
剛剛上面說了爱咬,這個文件是在根目錄下的,但是绊起,由于我們可能以后會對這個目錄進行修改添加精拟,所以放在根目錄不是很合適。
所以我們可以這樣做,將common-package同樣軟連接到根目錄串前。

進入common-packages,執(zhí)行

npm link

至此实蔽,腳手架模板打造完成荡碾。

新建項目文件,打開終端局装,執(zhí)行yo坛吁,可以看到:

腳手架搭建.png

恭喜恭喜,您已經(jīng)成功了铐尚!

完整的項目代碼可以到我的github上查看拨脉。
github項目地址:https://github.com/SunnySnail/yo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市宣增,隨后出現(xiàn)的幾起案子玫膀,更是在濱河造成了極大的恐慌,老刑警劉巖爹脾,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帖旨,死亡現(xiàn)場離奇詭異,居然都是意外死亡灵妨,警方通過查閱死者的電腦和手機解阅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泌霍,“玉大人货抄,你說我怎么就攤上這事≈熳” “怎么了蟹地?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長藤为。 經(jīng)常有香客問我锈津,道長,這世上最難降的妖魔是什么凉蜂? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任琼梆,我火速辦了婚禮,結(jié)果婚禮上窿吩,老公的妹妹穿的比我還像新娘茎杂。我一直安慰自己,他們只是感情好纫雁,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布煌往。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刽脖。 梳的紋絲不亂的頭發(fā)上羞海,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音曲管,去河邊找鬼却邓。 笑死,一個胖子當著我的面吹牛院水,可吹牛的內(nèi)容都是我干的腊徙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼檬某,長吁一口氣:“原來是場噩夢啊……” “哼撬腾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恢恼,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤民傻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后场斑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饰潜,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年和簸,在試婚紗的時候發(fā)現(xiàn)自己被綠了彭雾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡锁保,死狀恐怖薯酝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情爽柒,我是刑警寧澤吴菠,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站浩村,受9級特大地震影響做葵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜心墅,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一酿矢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧怎燥,春花似錦瘫筐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春之众,著一層夾襖步出監(jiān)牢的瞬間拙毫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工棺禾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缀蹄,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓帘睦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親坦康。 傳聞我的和親對象是個殘疾皇子竣付,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容