古いnode.js(0.10.x)でMoment.jsのプラグインとMoment Timezoneを共存させる方法

More than 1 year has passed since last update.

古いnode.js(0.10.x)でMoment.jsのプラグインとMoment Timezoneを両方使った時に出るエラーと、修正方法をご紹介。


経緯


  • 自分が作ったHubotのScript「hubot-amesh」を入れたHubotをHerokuにデプロイし、コマンド(amesh)をリプライしたら何も返ってこず、ログを見たらエラーが出ていた。

  • エラーはMoment.jsのプラグイン「Round」のfloor関数が無いというエラー(has no method 'floor')だった。

  • 自分の環境では動いていた。


エラー箇所

moment = require 'moment-timezone'

require 'moment-round'

# ...

getFilename = ->
moment()
.tz('Asia/Tokyo')
.floor(5, 'minutes')
# ^ <- ここ
.format('YYYYMMDDHHmm')

node.jsのバージョンが6.3.1のローカル環境では動いていた。


調査


  • Herokuのnode.jsのバージョンを確認



    • 0.10.46


      • 理由はHubotの雛形のgenerator-hubotのpackage.jsonでengines.nodeが0.10.xと設定されているため





  • enginesの部分を下記のように自分の環境と合わせる


    • npmのバージョンも指定できるので指定する



{

...

"engines": {
- "node": "0.10.x"
+ "node": "6.3.1"
+ "npm": "3.10.3"
}
}

上記のバージョン指定の修正を加えることでエラーが起きなくなった。

古いnode.jsで起きるエラーでした。

READMEに対応するnode.jsのバージョン書いてめでたしめでたし。。。

、、、って思ったけど、HubotをHerokuで使ってる人の何人がpackage.jsonのenginesでHerokuのnode.jsのバージョンを変えられると知っているだろうかと考えると、script自体を0.10.xに対応させた方が良い気がした。


:star2:0.10.xでMoment.jsのプラグインとMoment Timezoneを共存させる

というわけで本題。

0.10.xに対応させるためscript修正する。

momentTimezone = require 'moment-timezone'

moment = require 'moment'
require 'moment-round'

# ...

getFilename = ->
tokyo = momentTimezone().tz('Asia/Tokyo')
moment(tokyo).floor(5, 'minutes').format('YYYYMMDDHHmm')

moment-timezoneとmomentを別変数に持ち、

moment-timezoneでタイムゾーンを指定した時間オブジェクトを作ってから、

Moment Cloneの仕組みを使って時間オブジェクトをコピーして次の処理を行う。

こうすることによって0.10.xでもエラーが出なくなった。

node.jsのバージョン変遷に詳しくないのだが、0.10.xと6.xではnpmのパッケージの管理方法が違うのではないかと思った。

あるいは、requireのアルゴリズムが違う?

ともかく、試行錯誤して答えが見つかった。


ゆる募

なんで0.10.xと6.xでこういう差が出るのか解説記事があればぜひ教えて下さい。


おまけ

経緯の中でも紹介していますが、「hubot-amesh」というscriptを作りました。

「amesh」と話しかけると現在の雨の状況を画像で教えてくれます。

hubot-amesh sample image

※ ImageMagick(Herokuにはデフォルトで入っています。)とimgurのClient IDが必要になります。

ぜひ使ってみてください。