[Parse] Cloud Modulesの外部ライブラリ読み込みでエラーが出たときの対処

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。mBaaS担当(自称)のこむろです。

Cloud Codeで外部ライブラリを読み込む

Cloud Codeは、Javascriptの外部ライブラリを取り込むことができます。
すでに組み込み済みのライブラリについては、何も用意することなく宣言するだけで簡単に利用することができます。

組み込み済みのライブラリの場合

例えばUnderscore.jsは組み込み済みなので、main.jsの先頭に以下のように記述することで利用できます。

main.js

var _ = require('underscore');

組み込まれていないJavascriptライブラリを使う場合

例えば日時を操作する時に便利なmoment.jsを利用する場合には、
main.jsの先頭に以下のように記述することで利用できます。

main.js

var moment = require('cloud/moment-with-langs.js');

外部ライブラリとして取り込むjsファイルは、cloud/main.jsと同じ階層に配置しておく必要があります。

スクリーンショット_2014-07-29_0.03.57

moment-timezone.jsのライブラリを取り込んでみた

本題です。
何も考えずに取り込みます。ファイル配置は先程のスクリーンショットの通り。

スクリーンショット_2014-07-29_0.03.57

main.js

var moment = require('cloud/moment-timezone-with-data.js');

ParseにDeployします。

$ parse deploy
Uploading source files
Finished uploading files
Update failed with Could not load triggers.  The error was TypeError: Cannot set property '_z' of undefined
    at moment-timezone-with-data.js:325:29
    at moment-timezone-with-data.js:14:20
    at moment-timezone-with-data.js:18:2
    at main.js:3:14

エラーが発生しました。

angry-jenkins

原因

エラーのStackTraceを見てみます。どうやらmain.jsのmoment-timezone.jsをrequireしようとしてる箇所でエラーが発生しているようです。
main.jsの記述には問題がないはずなので、moment-timezone.jsの中に原因があるようです。

moment-timezone.jsを変更する

該当箇所を探します。

//! moment-timezone.js
//! version : 0.1.0
//! author : Tim Wood
//! license : MIT
//! github.com/moment/moment-timezone

(function (root, factory) {
	"use strict";

	/*global define*/
	if (typeof define === 'function' && define.amd) {
		define(['moment'], factory);                 // AMD
	} else if (typeof exports === 'object') {
		module.exports = factory(require('moment')); // Node
	} else {
		factory(root.moment);                        // Browser
	}
}(this, function (moment) {

見つけました。ここのrequireがParseでは呼び出されています。
当然moment.jsは、Parseに組み込まれていないのでこの呼び出し方はNGです。

以下の手順で修正します。

1.moment.jsを準備する。

moment.jsを取得して、cloud/moment.jsに配置する。

2.moment-timezone.jsを書き換える

moment.jsの呼び出しをParse用に書き換えます。

// module.exports = factory(require('moment')); // Node
module.exports = factory(require('cloud/moment-with-langs.js')); // modify for Parse.com

gist - komuro-hiraku

以上の手順でOKです。Deployしてみます。

$ parse deploy
Uploading source files
Finished uploading files
New release is named v49 (using Parse JavaScript SDK v1.2.19)

今度は問題なく成功しました。

まとめ

今回は、Cloud Modulesで外部ライブラリを取り込む際にハマった罠があったので記事にしてみました。

外部のJavascriptのライブラリを気軽に取り込めるCloud Modulesの機能ですが、ライブラリによってはこういった罠が待ち構えているので注意がに必要です。
ほとんどnode.jsと同じような記述で使えますが、こういった微妙な違いでうまく動作しないこともありますので、見つけ次第報告していこうと思います。

参照