ユーザーエクステンションを作成しArchitect 3に統合する (Part II)
こんにちは、ゼノフィnakamuraです。
Sencha Architect 3上では便利なサードパーティのライブラリを、全てのプロジェクトで再利用可能なツールとしてパッケージ化したユーザーエクステンションが生成できるようになります。
このブログシリーズの Part 1 (日本語訳は こちら ) でAaron ConranがCar Query APIの概要を説明し、Ext JSを利用した便利なコンポーネントの作成方法を説明しました。 彼が生成した LinkedComboContainer は皆様のほとんどのプロジェクトで利用する価値があるかと思います:いくつかのコンボ ボックスがお互いの値に影響する状況は珍しくないことです。
この記事で、再利用可能なAUX (Architect User Extension:アーキテクト・ユーザー・エクステンション)パッケージ作成の手順を説明します。AUXのコンポーネントはとてもシンプルです。AUXパッケージはSencha Cmdのパッケージにならって生成され、Sencha Cmdと互換性があります。通常のSencha Cmdパッケージと比べて、AUXパッケージは追加で二つのデータが含まれています。そのデータを細かく説明します。
- package.jsonの「architect」セクションは、Architectではクラスがどのように読み込まれるべきか、またどのCSSファイルを同時に読み込む必要があるかを指示します。
- 「definitions」はあなたのクラスがツールボックス上でどのように表示されるかをSencha Architectに指示するデータです。
初めに
まず、Sencha Cmdで空のパッケージを生成しましょう。コマンドシェルからCmdのワークスペースに移動して、 “sencha generate package [packageName]” を次のように実行して下さい:
sencha generate package LinkedComboContainer |
これでパッケージの生成を示す出力が発生します。それはワークスペースフォルダ内の「packages」ディレクトリに格納されます。利用したパッケージ名が、そのパッケージのフォルダ名として定義されます。
例えば:もし/cmd-workspace/というディレクトリにいる場合、パッケージは /cmd-workspace/packages/LinkedComboContainer に格納されます。
次は、特にArchitectに関係するパッケージの内容をご覧にいれましょう。簡単に読めるように、生成されたフォルダのうちoverridesフォルダとsassフォルダはこのAUXには不要のため、2つとも省かれています。
architect/ # 各AUXクラスのJSON定義ファイル Xx.Definition.js # XX.Definitionクラスの定義ファイル build.xml # AUXがどう構築されるか管理するファイル docs/ package.png # このAUXの為にSencha Marketで利用されるグラフィック screenshots/ pict.png # Sencha Marketで利用されるグラフィック licenses/ # このAUXのライセンス契約 Readme.md package.json # Readme.md # Sencha Marketで利用されるこのAUXの説明文 resources/ # このAUXで利用されている静的リソース css/ # このAUXのCSSリソース images/ # このAUXで利用された映像のファイル src/ # 各エクステンションクラスのJavaScriptソースファイル xxxx.js yyyy.js |
この構造から、三つのタスクがあることが分かります:
- src/ フォルダに我々のコードを追加する
- Architectがそのコードを認識するためにpackage.jsonを編集する
- Definition(定義)ファイルを生成して、architect/ のフォルダに格納する
Step 1:あなたの外部ソースコードをパッケージに追加する
最初の手順はシンプルです。Part I の例からコードをダウンロードします。
次に生成されたパッケージ内のsrc/ フォルダに挿入します。src/LinkedComboContainer.jsに置きます。
それだけです。もし追加のファイルがある場合は、このsrcフォルダに格納して下さい。もし整理しておきたいファイルがたくさんある場合は、サブフォルダも可能です。ただ、次に説明するpackage.json内に指定する必要があります。
Step 2:package.jsonの編集:
Sencha ArchitectとSencha Cmdがこのパッケージの内容を理解できるように、package.jsonファイルを利用します。編集されてないpackage.jsonは下記のようになっています:
1 2 3 4 5 6 7 8 9 10 11 12 | { "name": "LinkedComboContainer", "type": "code", "creator": "anonymous", "summary": "Short summary", "detailedDescription": "Long description of package", "version": "1.0.0", "compatVersion": "1.0.0", "format": "1", "local": true, "requires": [] } |
自分の名前を “creator” フィールドに挿入して、パッケージの概要と細かい説明をそれぞれのフィールドに追加して下さい。
今の段階では”version” フィールドは1.0.0のままで残してもいいです。もしこのパッケージの新たなバージョンを公開した場合、この値もアップデートしたほうがいいでしょう。
Architectは現時点では“compatVersion” を利用していませんが、もしアップグレードされたパッケージを設置したとしても、API の変更があった場合は、あなたのプロジェクトが変更されなくても済むようSencha Cmdが利用します。詳しくは、ここのSencha Cmd Packagesガイドの“Package Versioning”のセクションをご覧ください。
次はpackage.jsonに“architect”: {}のオブジェクトを追加する必要があります。次のようになるはずです:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | "architect": { "compatFrameworks": [ "ext42" ], "classes": [{ "definition": "LinkedComboContainer.Definition.js", "className": "Ext.ux.LinkedComboContainer", "js": [ "LinkedComboContainer.js" ], "css": [ ] }] }, |
これを部分毎に検討しましょう:
“compatFrameworks”は単純にこのコードはどのフレームワークで実行可能か示す文字列の配列となります。この場合は、これはExt JS 4.2だけのために構築とテストされたので、 “ext42”をリストします。例えば、もしSencha Touch 2.2と2.3用のエクステンションを作成した場合、 [ “touch22”, “touch23” ] をリストします。
“classes” はオブジェクトの配列で、各オブジェクトは一つのクラスを定義します。各オブジェクトのコンポーネントを検討しましょう:
1 2 3 4 5 6 7 8 9 | { "definition": "LinkedComboContainer.Definition.js", "className": "Ext.ux.LinkedComboContainer", "js": [ "LinkedComboContainer.js" ], "css": [ ] } |
クラスオブジェクトの詳細:
“definition”:ユーザーがツールボックスからドラッグできるクラスやコンポーネントとdefinitionの間には1:1の関連付けが常にあります。この値は単純にarchitect/ フォルダに格納されたdefinitionファイルのファイル名となります。この場合は、 “LinkedComboContainer.Definition.js” です:これは近々作成します。
“className”:これは読み込んでいるclassNameと一致するべきです。Part Iで生成されたクラスは Ext.define(‘Ext.ux.LinkedComboContainer’, { … }); を使って定義されていますので、単純にそのclassNameをここに挿入します。注:Architectは最初に”src”フォルダ内から検索を始めますので、これは指定しなくても大丈夫です。しかし、もしこのファイルをサブフォルダに格納したら(例えば“src/lib”)その入力は “lib/LinkedComboContainer.js” となります。
“js”:これはパッケージのsrc/フォルダに存在するクラスを生成するJavaScriptの配列です。今回の場合は1つのファイルが必要です:“LinkedComboContainer.js”。しかし、もしLinkedComboContainer.js が我々が生成した別のコード(例えば“SpecialComboContainer.js”)の一部が最初に読み込まれる必要がある場合、次のように依存関係の順番で両方のファイルをリストします: “SpecialComboContainer.js”,”LinkedComboContainer.js”]
“css”:このインスタンスでは特別なCSSはありません。しかし、特別なスタイルが関連しているコンポーネントを生成するかもしれません。ここに一つあるいは複数のファイルをリストすると、このコンポーネントを外にドラッグした場合に読み込まれるようになります。
もし我々の例に追加のクラスがあったら、JSONのように、単純にカンマで分けられているそれぞれのオブジェクトが付きます。
definitionを書く:
definitionはArchitectにコードを導入する魔法となります。最もシンプルなdefinitionの書き込み自体は簡単ですが、もし気が向けば 、開発者はいくつかの細かいタスクをdefinitionで実行できます。我々のLinkedComboContainerのdefinitionです:これを部分的に分けて説明します:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | { "classAlias": "widget.linkedcombocontainer", "className": "Ext.ux.LinkedComboContainer", "inherits": "Ext.container.Container", "autoName": "MyLinkedComboContainer", "helpText": "A linked combo container", "toolbox": { "name": "Linked Combo Container", "category": "Form Fields", "groups": ["Forms"] }, "configs": [{ "name":"disclosureMode", "type":"string", "initialValue":"enable" },{ "name":"loadMode", "type":"string", "initialValue":"ondemand" },{ "name":"listeners", "type":"object", "initialValue":null }] } |
必要なフィールドは:
className: これはclassNameと一致するはずです
classAlias: これはカスタムコードautoName: で生成したクラスのエイリアスと一致するはずです。これはあなたのクラスのインスタンスに与えるベース名です:ユーザーがArchitectから外にドラッグするコンポーネントの名称になります。
toolbox: {} このオブジェクトはコンポーネントがツールボックスで表示された場合、どの名称になるべきかと、どのカテゴリー/グループにそれを格納するべきかArchitectに指定します。”group”はツールボックスの左側のウィンドウで、この場合はコンポーネントは”forms”内に格納されました。”category”は右側のウィンドウのどのセクションにコンポーネントを格納するか(下記の通りに)指定します。

このdefinitionで利用しているオプショナルな項目
inherits: もしあなたのコンポーネントが他から拡張や継承をしているなら、ここでそれを指定することが便利です。Architectが既にそのコンポーネント用に公開しているコンフィグは自動的に引っ張られます。これで作業が大きく節約できますので、あなたのコンポーネントは単純に構成できるようになります。我々の場合は”Ext.Container”を拡張するので、inherits: “Ext.Container” を指定します。これは実際のクラス継承と異なります:Architectはただコンフィグを公開するなどの行動を継承するために利用しています。
helpText: このテキストはツールボックスの(?)アイコンの上にマウスが移動させたら表示されます。ユーザーにコンポーネントに対する詳細を提供するためにこれを利用して下さい。これは説明が必要となる様々なコンポーネントが含まれているエクステンションに非常に便利です。
configs: Ext JSとSencha Touchの全てのコンポーネントには”configs”があります:シンプルな文字列から複合オブジェクトまで、コンポーネントがコンフィグオプションとして利用する値です。この場合、我々のコンポーネントはComboBoxが既に提供しているコンフィグに、いくつか追加で特別なコンフィグが必要となります。上記のように、AUXでコンフィグの名前、種類、初期値をdefinitionで指定すればコンフィグを公開できます。
definition の中でできることの全てを紹介してはいませんが、この段階でプロジェクトを充分進めていくことができます。詳しくは、ドキュメンテーションのCreating App Templates and User Extensionsをご覧下さい。
全部合わせましょう
さて、package.jsonとdefinitionを生成し、ファイルも適切な場所に格納したので、入力ミスさえなければ、これで動作するパッケージが出来た筈です。
次の手順はパッケージがロードされるようにします。Architectがそのパッケージを発見して、ロードできるような場所にコピーする必要があります。上記で説明した通り、AUXファイルは簡単に配布できるようにZIPアーカイブとなっています。しかし、ArchitectはSencha Architectのpreferencesメニュー (Sencha Architect -> Preferences)に指定されているディレクトリにインストールされたエクステンションを格納します。
各パッケージは次のようにディレクトリに格納されます:
%ExtensionDir%/{extensionName}/{version}
そのため、もしLinkedComboComponent というフォルダを生成して、1.0.0というサブフォルダを生成したら、そこにファイルをコピーした場合、Architectはすぐテスト用にそれを読み込みます。
注:“.sencha” フォルダがコピーされていることを確認して下さい。Linux/OSXのシステムでは、”cp”のコマンドは隠しフォルダを移動しない可能性がありますが、これはArchitectとCmdがそれを読み込む為には必要です。
もし速く始めたかったら、我々のgithubレポジトリにLinkedComboContainerエクステンションに関連しているフォルダがあります。
エクステンションの編集とデバッグに関する注意点:
まず、最も重要なこと:ユーザーエクステンションのコンポーネントを利用するプロジェクトを保存している時、そのパッケージは配布に必要となるので、プロジェクトにコピーされます。このため、それ以降の%ExtensionDir% フォルダからの編集は自動的にプロジェクトに挿入されません。その代わりに、デバッグ中に保存されているプロジェクト内のパッケージフォルダから直接編集して、エクステンションが公開できる状態になるまで微調整をするのが一番簡単な方法かもしれません。
もしdefinitionがツールボックスに読み込まれていなかったら、下部のLogウィンドウにエラー警告が発生しているか確認して下さい。最もあり得る原因は、definition内の入力ミス(例えばカンマが足りないなど)、または必要なフィールドが不足しているなどです。
最後に、もし苦労していて、少し助けが必要な時、我々の新しいフォーラム“Sencha Architect User Extensions and Templates” を参照して下さい。
エクステンションのパッケージ化:
パッケージが公開できる状態になったら、パッケージ化は本当に簡単です。単純に”Extensions”の下のツールボックスの項目を右クリックして、”Package Extension”を選択して下さい。ファイルを保存するロケーションを選択して、”save”をクリックして下さい。それだけです。

パッケージされたエクステンションをインストールする
AUXファイルをインストールするのはとても簡単です。単純にツールボックス内で”Install User Extensions”のアイコンをクリックするか、または File -> Install User Extensionをクリックして、ファイルを指定して下さい。
この記事で生成されたエクステンションをダウンロードして試して下さい。
Sencha Architectのユーザーエクステンションを開発することに対して、役に立つ紹介でしたか? Senchaの開発者コミュニティが素晴らしいものを生み出す結果を見るのが楽しみです。Sencha MarketplaceのUser Extensions sectionの部分を見ておくと、そこであなたの開発工程がより早くなるための役に立つエクステンションがアップされるでしょう。