2012年11月7日 星期三

[node.js] 在heroku上用bower管理前端第三方元件

在做web applications時,或多或少都會使用到像是jQuery, bootstrap這類的第三方元件,使用已經host在既有CDN 的版本(比如說google的)是一個不錯的方法,但不是每一種都有這類方案,一個個從各網站下載回本地端又不是那麼容易管理,bower就是為此出現的,bower是一個類似npm的軟體,由Twitter所開發出來且是開放原始碼,所不同的是,npm是管理node.js相關的套件,但bower是管前端的

舉一個例子,你可以利用bower來安裝jQuery :
bower install jQuery
bower會把jQuery 安裝到"components/jQuery" 目錄裡

在npm , 你可以把所有相關的模組設定在package.json中,這樣就不用一個個下"npm install mypackage"這樣的指令了,bower也有類似的設計,只是為了避免跟package.json造成混淆它採用的檔名是component.json,內容跟package.json差不多:
{
    dependencies: {
      "JQuery": "*"
    }
}
在Heroku deploy node.js app有個很方便的地方是,當你做git push 後,它會根據package.json自動幫你安裝相關的node.js 模組,但不幸的是它並不支援bower,只支援npm

還好Heroku很有彈性,可以藉由buildpack來自己加這部份

buildpack API其實還蠻簡單的, 基本上只要準備三支shell script:
  • bin/detect
  • bin/compile
  • bin/release
大部分的東西, 大多在"bin/compile"裡完成的

自己做的buildpack也只要放github, 然後將自己app的buildpack指定到這來即可 (使用heroku toolbelt):
  • 新建的程式使用自己的buildpack: 
    heroku create myapp --buildpack https://github.com/heroku/heroku-buildpack-ruby
  • 既有的程式更換buildpack:
    heroku config:add BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-ruby
當然, 不需要重頭建立自己的buildpack, Heroku官方的buildpack都有open source在github上, 如Node.js buildpack, 所以只要fork出來修改即可, 因此我從Node.js buildpack fork出一個新的buidlpack, 主要的修改是:

  1. 安裝bower
  2. 找出所有的component.json並用"bower install"安裝套件
本想說 "1" 應該蠻簡單的, 因為bower也是用node.js開發的, 應該只要用npm install bower就搞定了, 但事實是, 這樣會碰壁, 因為bower採用了lodash , lodash跟Heroku的npm似乎八字不合, 安裝過程到lodash的post-install就會失敗, 也沒明顯的錯誤, 只說這應該是套件問題, 而去查了lodash, 也有人報過類似的issue, 但作者卻以lodash沒問題應該是npm的問題把這issue給關了(鬼打牆?), 但:
  • 自己電腦上安裝bower或lodash都沒問題
  • 在自己的package.json加上lodash, deploy到Heroku也一樣掛
  • 在package.json裡設定engine裡的npm版本到最新的1.1.65(跟自己電腦上一樣版本), 也一樣不行

那...就不得不懷疑是npm問題了, 查了原本buildpack寫的, Heroku的node.js和npm其實是拿他們自己放在S3的binary package來安裝的, 可疑!

因此就使用了下一招 - 用npm來裝npm

用Heroku系統內的npm來裝npm是可行的, npm install npm的結果是, 會有一份最新的npm被安裝到node_modules底下, 可以用"node_modules/.bin/npm"來呼叫這版本, 因此就加上了:
node_modules/.bin/npm install bower
Bingo! 這樣可行, bower一樣被安裝到 node_modules/.bin底下, 加上 "2"的邏輯到"bin/compile"後就大功告成了,

有修改的部份只有"bin/compile", 比對一下commit history就可以知道我修改過啥, 中間有做了很多實驗, 所以有不少垃圾commits, 可以忽略

如果有需要這版本buildpack, 也歡迎利用:

https://github.com/julianshen/heroku-buildpack-nodejs