addProvider呼び出しとデプロイ

過去のエントリ (scriptタグで読み込むファイルとデプロイについて) で、Ext JS 4のMVCをExt.Directと一緒に使う際の、addProviderの呼び出し方についてや、Senchaコマンドを用いた デプロイについて言及しました。 今回、実際にExt JS 4のMVCを使ったアプリケーションを作成し、それをデプロイすることになったので、 過去の記述通りにいかなかった部分があり、現在把握している状況を書き留めることにします。

認証との関係

今回のアプリケーションでは、ユーザー認証があり、認証されていない状態ではログイン画面にジャンプするようになっています。 Senchaコマンドのcreate jsbでは、Phantomjsで実際にhtmlファイルを読み込んで、 Ext.Loaderを動かした結果に基づいてjsb3ファイルを作成しているようです。 普通にsencha create jsb をhttpで始まるurlで実行すると、認証されていないのでちゃんとjsb3ファイルを生成する事ができません。

仕方がないので、デプロイ用のhtmlファイルを作成し、開発環境ではそのurlからのアクセスに関しては認証済みとして扱うような 記述をしてログイン認証なしでも動作するようにして、jsb3ファイルの生成に成功しました。

addProvider

MVC フレームワークにおいて、addProvider をどこで実行するかと言うことについては、 MVCでExt.Directを使う で記述しました。 その中ではApplicationのonLoadで実行するという風に結論づけたのですが、 @kotsutsumi さんからのアドバイスで、 別途、onReadyを作ってそこで実行するという方法を教わり、その方がずっとすっきりすると言うことがわかりまして、 そうすることにしました。 (MVCでのDirectについて – Togetter)

なにがすっきりするかというと、onLoadにてaddProviderする場合には、Storeのコンフィグが読み込まれる時点では addProviderされていないため、directFnやapiコンフィグを設定できないのです。 そのため、最初はコンフィグを空にしておいて、あとで設定しなければなりません。 しかし、別途onReadyを記述してそこでaddProviderしておくと、StoreのコンフィグにdirectFnやapiで、Directメソッドを指定できます。 余分なコードが減ってすっきりするわけです。

しかし、Loaderで動かしているうちはよかったのですが、 デプロイする段になって問題が発生しました。 onReadyで指定すると、デプロイ時にjsファイルをマージするとうまく動作しないことがわかったのです。

問題の本質は、は、Storeの定義(というかProxyの定義)とaddProviderが実行される順番です。 Loaderで実行している場合は、onReadyが全部実行されてから、LoaderがStore定義を読みに行くので、 問題なく動作します。 しかし、デプロイするためにファイルをマージした場合には、その順番が後先になってしまい、エラーが発生するのです。

Ext.Loaderでアプリケーションのファイルが読み出される場合、onReadyでaddProviderしても正常に動作します。 Proxyの定義が読み込まれる前にonReadyが実行されるからです。

それらのファイルをマージして、Ext.Loaderのenable: falseにして実行すると、 onReadyが実行される前に、StoreやModelに定義されたProxyに指定されたサーバーサイド関数がさきに読み込まれてしまいます。

解決策

このエラーを避けて動作する状態でデプロイするにはどうしたらよいのか。 というところが、この記事のテーマです。

まず、onReadyに書いていたaddProviderを、平のところに書くようにします。 そしてそれを書く位置は、Ext.direct関連のモジュールが読み込まれた後、 Proxyでサーバーサイド関数を定義する前、である必要があります。

Senchaコマンドは、Ext本体の部分もふくめて、必要なJavaScriptのファイルをすべて集めてマージしてくれるのでとても便利です。

ところが、そこで生成されるファイルは、Ext JS本体とapp.jsやappフォルダ以下の自分が書いたファイルを分離してはくれません。 多分、Loaderが読み込んでゆく順番にファイルを配置するのだと思います。

僕としては、まずExtJS関連のファイルを全部読んで、次にaddProviderして、その次に自分のアプリケーションのファイルを 読んでくれるとうれしいのですが、それをうまくやる方法がありません(やり方がわかりません)。

思った通りにマージできないのなら、Senchaコマンドなぞに頼らず自分でマージしちゃおう、 と思ったのですが、Loaderで書いたアプリケーションをそれが依存する順番にきれいにマージするのって結構難しかったりします。 で、Senchaコマンドの力を借りつつも、上記の問題を解決する方法がないかと考えてなんとかたどり着きました。

まず、sencha create jsb3 でjsb3ファイルを作ります。このファイルの中身はJSONファイルで、 builds配列の1つめの要素にあるfiles配列に読み込むファイルが列挙されています。 このファイルのリストを読みながらファイルをマージするスクリプトを書けば、 自分の思い通りにマージできます。

[php] foreeach($jsb->builds[0]->files as $file){ $fileName = $file->name; $fullPath = WEBAPP . $file->path . $fileName; if( substr($file->path, 0, 3) == ‘ext’ ){ $contents = file_get_contents($fullPath); fwrite($fp, $contents); } } [/php]

こんな感じでやると、pathがextで始まるファイルだけをマージできます。 同様にappに配置されたファイルをマージすることも出来ますね。 そして、

  1. 必要なExtJSファイル(jsb3ファイルを元に抽出)
  2. addProviderをするファイル
  3. app.js
  4. app以下のファイル(jsd3ファイルを元に抽出)

の順でマージします。もちろんこれはスクリプトにします。

このようにすると、マージされたファイルでもエラー無く動作します。 本当にこのやり方でいいのかどうかわかりません。 もっとうまいやり方がありそうな気もします。