Sencha Cmdの主要コンポーネントのひとつにコンパイラがあり、JavaScript間でのフレームワーク認識を最適化します。この最適化ツールは高度なExt JSおよびSencha Touchコードを認識し、これらの高度な抽象化をサポートできる可能な限り小規模で効率的なコードを生成します。
前提条件
先に進む前に以下のガイドをご覧になることをお勧めします。
setsとcurrent set
コンパイラはバックグラウンドで一連のソースファイルを管理し分析して、依存関係を決定します。全ファイルのセットはclasspath
によって決定されます。
sencha compile -classpath=common,app ...
この例では、コンパイラにより"*.js"
が指定したリストのフォルダから再帰的にロードされます。この全ファイルのセットにより、後続の処理を行うベースが定義されます(つまり、その「在りよう」が定義される)。
コンパイラによって使用されるデフォルトの classpath
は、次のような設定プロパティに記述されています。
${framework.classpath},${workspace.classpath},${app.classpath}
sencha app build
などの高レベルコマンドを実行する場合、Sencha Cmd は使用する SDK を認識し、適切な設定をロードし、そのフレームワークの "src"
フォルダを classpath
に含めます。コンパイラをこれらの状況以外で使用する場合、-sdk
スイッチを使用する必要があります。
sencha -sdk /path/to/sdk compile -classpath=common,app ...
コンパイラの出力コマンド(たとえばconcat
やmetadata
)は“current set”と呼ぶファイルセットに対して実行されます。current setは、最初の時点では全ファイルの在りようと同じものですが、セット処理用に用意されている多数のコマンドを使用して操作することができます。
注意 コンパイラではand
コマンドチェーンメカニズムを使用した長いコマンドラインを頻繁に目にすることになります。また、実際的な使用方法として、長いコマンドラインについてはAntまたは「レスポンスファイル」の使用を検討してください。Sencha Cmd高度な利用法を参照してください。
このガイドでは、例をわかりやすくするために、すべてのコマンドラインが完全な形(かつ、おそらくは長いもの)となっています。
フレームワークとクラスパス
最終的に、コンパイラは必要な SDK の "src"
フォルダに到達する必要がありますが、 -classpath
に追加するだけでは最適な結果を生むことはできません。代わりに、上記の例では、-sdk
スイッチを使用してコンパイラに使用する Sencha フレームワークを知らせます。これにより、コンパイラはクラスの依存関係(Ext.data.Store
の model
コンフィグなど)を示すコンフィグプロパティなどのフレームワーク特有の内容を認識できるようになります。
concat
を使用した出力の生成
コンパイラは、突き詰めていうと、指定された入力から有効な出力を記述するものです。concat
コマンドは現在のファイルセットのソースを適切な依存関係順に連結します。
唯一の必須パラメーターは、出力ファイル名を示す-out
です。その他のオプションは生成するファイルに影響します。圧縮処理には次のいずれかのオプションを選択できます。
-compress
- デフォルトのコンプレッサーを使用して生成したファイルを圧縮します。現在では、これは-yui
と同じです。-closure
- Google Closure Compilerを使用して生成したファイルを圧縮します。-yui
- YUI Compressorを使用してソースファイルを圧縮します。-strip
- 出力ファイルからコメントを削除しますが、空白は残します。このオプションでは、“ext-all-debug-w-comments.js”は“ext-all-debug.js”に変換されます。
次のコマンドは、1回のソースファイル読み込みで3種類の出力を生成します。
sencha -sdk sdk compile \
exclude -namespace Ext.chart and \
concat ext-all-nocharts-debug-w-comments.js and \
-debug=true \
concat -strip ext-all-nocharts-debug.js and \
-debug=false \
concat -yui ext-all-nocharts.js
メタデータの生成
コンパイラでは、さまざまな用途に役立つメタデータを生成することもできます。たとえば、全ソースファイルの名前、依存関係順によるファイルセットなどです。作成できるものに関する詳細は、メタデータを生成するガイドを参照してください。
セットの保存と復元
複数の出力ファイルを生成する場合、current setを後々のためにとっておくと便利なことがあります。
sencha -sdk sdk compile \
exclude -namespace Ext.chart and \
save nocharts and \
...
restore nocharts and \
...
save
コマンドでは、current set のスナップショットを撮り、指定した名前で保存します(この例では nocharts
)。
保存したセットの最も簡単な使用方法は、restore
コマンドを使用してcurrent setをsave
した時点の状態に復元回復することです。
セット処理
コンパイラによって提供されているコマンドの多くはセット処理に分類され、セットの作成やセットに対する操作を行います。コンパイラの場合、これはファイルまたはクラスのセットを指します。まずは、セットの用語から見て行きましょう。
セットの理論概要
セット処理には次に示す3つの標準的なものがあります。
共通部分 - 2つの集合の共通部分は、両方の集合内に存在したもののみを含んでいる集合です。
Union - 2つのセットのunionは、いずれかのセットに含まれているものを持つセットです。
差 - 2つの集合の差は、2つ目の集合内に存在しない1つ目の集合内のすべての集合です。
include
とexclude
セット
この2つはセット処理の最も一般的(かつ柔軟)なものといえるでしょう。いずれも、次の基本的なスイッチをサポートしています。
-namespace
- 指定した名前空間でタイプを定義しているファイルをマッチングします。-class
- 指定した定義タイプをマッチングします。-file
- Ant-style globパターンを使用してファイル名やフォルダ名を一致させます(「*」は、「**」がフォルダと一致するファイル名の文字とのみ一致します)。-tag
- 指定したタグを持つすべてのファイルをマッチングします(次を参照してください)。-set
- 指定した名前付きセットのいずれかに含まれるファイルです。
いずれの場合も、次のコマンドライン引数はマッチ条件をカンマで区切ったものとなります。また、単一のexclude
またはinclude
は必要なだけのスイッチ/値のペアを保持できます。
では、簡単な例から始めましょう。 "ext-all-no-charts-debug-w-comments.js"
を作成します。
sencha -sdk sdk compile \
exclude -namespace Ext.chart and \
...
ここでは、Ext JSソース("sdk/src"
内)のみを使用して開始します。これらはすべて“current set”に含まれています。次に、Ext.chart
名前空間にあるファイルすべてを除外するset differenceを行います。これでcurrent setは"ext-all.js"
と同じになりましたが、Chartパッケージは使用していません。
-not
を使用したinclude
とexclude
の否定
include
およびexclude
では、豊富なマッチング条件をサポートしています。これには後続のマッチング条件を否定する-not
スイッチも含まれます。つまり、含めたり除外したりするファイルとして、条件に一致しないものを選択することが可能です。
例えば、
sencha -sdk sdk compile -classpath=js \
... \
exclude -not -namespace Ext and \
...
exclude
コマンドによりcurrent setからExt
名前空間にないクラスがすべて除外されます。
all
セット
場合によっては、current setをすべてのファイルまたは空のセットに復元する際に役立ちます。この処理を行うには、include
またはexclude
を-all
スイッチと共に使用します。前回の例に対して行う場合を示します。
sencha -sdk sdk compile -classpath=js \
... \
include -all and \
... \
exclude -all and \
...
include -all
実行後、current setはすべてのファイルとなります。exclude -all
実行後には、空のセットとなります。
Union
先に示したとおり、include
コマンドはset unionの一形式であり、マッチするファイルセットを持つcurrent setのunion処理を行います。場合によっては、unionにcurrent setを含めず条件にマッチするファイルのみを含めるほうが好ましいことがあります。union
コマンドではこのような処理を行えます。
union
コマンドにはinclude
のオプションをすべて使用できます。次のunion
コマンドを見てください。
sencha -sdk sdk compile -classpath=js ... and \
union -namespace Ext.grid,Ext.chart and \
...
これは、exclude
およびinclude
コマンドの次の組み合わせとまったく同じです。
sencha -sdk sdk compile -classpath=js ... and \
exclude -all and \
include -namespace Ext.grid,Ext.chart and \
...
移行性/再帰的Union
セット処理における最も重要なものに、明示的に指定したすべてのファイルおよび当該ファイルが必要とするファイルすべてのunionがあります。必要なファイルセットのみを選択する方法として、ビルド処理の中核となるものです。したがって、トップレベルのファイルで構成される小さなセット、ここではMyApp.App
クラスとしますが、これに対して処理を開始する場合、次のものを使用できます。
sencha -sdk sdk compile -classpath=app \
union -r -class MyApp.App and \
...
このunion
コマンドではcurrent setはなくMyApp.App
クラスのみが含まれており、 これに必要なものすべてを再帰的に含める処理を行います。作成されるcurrent setにはアプリケーションに必要なファイルすべてが含まれます。
intersect (厳格)
intersect
コマンドでサポートされている条件はやや柔軟性にかけます。使用できるのは名前付きセット(-set
を使用したもの)のみです。
sencha -sdk sdk compile -classpath=common,page1/src,page2/src \
... \
intersect -set page1,page2 and \
... \
このコマンドでは2つのページセットの交差処理を行い、交差する部分を使用してcurrent setを生成します。
intersect (あいまい)
3つ以上のセットに対応するため、intersect
にはcurrent setにおけるメンバーシップの閾値を定める-min
というオプションが用意されています。
次に例を示します。
sencha compile ... \
intersect -min=2 -set page1,page2,page3 and \
...
intersect
をこのように使用すると、指定した3つのセットのうち2つのセットに含まれるファイルすべてを持つcurrent setが生成されます。
コンパイラのディレクティブ
コンパイラのみが使用できるメタデータをファイルに埋め込んでおくと、さまざまな場面で役立ちます。この処理を実現するため、コンパイラでは特別なラインコマンドをディレクティブとして認識します。これらの指令は @-prefix の単語で始まる単行コメントです。例:
// @define Foo.bar.Thing
ディレクティブの一覧を次に示します。
// @charset
// @tag
// @define
// @require
文字エンコーディング
特定のJSファイルに文字エンコーディングを指定する標準的な方法はありません。ただし、Sencha Cmdコンパイラでは次のディレクティブを認識できます。
// @charset ISO-9959-1
これらはJSファイルの1行目に記述することが必要です。charset
の右側の値は有効なJava文字セット名であれば何でも構いません。デフォルト値は“UTF-8”です。
charset
ディレクティブは入力ファイルのエンコーディングをコンパイラに通知するために使用します。出力ファイルのエンコーディングには影響しません。入力ファイルのコンテンツは内部的にUnicodeに変換されます。
タグ付け
理想的には、対象のセットの定義には名前空間で十分です。ただし、セットは非常に恣意的なものになることがあり、名前空間の境界を越えたものとなることがあります。この問題をコマンドラインレベルで解決しなくても、コンパイラでファイル内の任意のタグを追跡できます。
次の例を見てください。
// @tag foo,bar
この処理ではfoo
およびbar
というタグをファイルに割り当てます。これらのタグはinclude
、exclude
、union
の各コマンドで-tag
オプションと共に使用できます。
「その他」のJavaScriptファイルの取り扱い
場合によっては、JavaScriptファイルではクラスやオブジェクトを定義し、Ext.define
およびrequires
またはExt.require
に関しては記述されていないクラスやオブジェクトを必要とします。Ext.define
を使用しても、クラスにはこのようなものが必要
であり、動的ローダーからはこれらが存在していれば警告は出ません(存在しない場合、ローダーがこれらのロードを試み、おそらくは失敗に終わります)。
タイプの定義と要求を行うために恣意的なJavaScriptアプローチをサポートするため、コンパイラでは次のディレクティブも提供しています。
// @define Foo.bar.Thing
// @require Bar.foo.Stuff
これらのディレクティブはコンパイラに同じ基本メタデータを設定します。このメタデータはどのファイルでタイプを定義し、どのファイルにはどのようなタイプが必要なのかを追跡します。これらのディレクティブは多くの点でrequires
プロパティを持つExt.define
と同じ結果をもたらします。
ファイル中ではどちらか一方のみを使用してかまいません。
条件付きコンパイル
コンパイラでは、次のような条件付きコンパイルディレクティブをサポートしています。
foo: function () {
//<debug>
if (sometest) {
Ext.log.warn("Something is wrong...");
}
//</debug>
this.bar();
}
これは条件付きディレクティブの中で最も便利なものであり、開発環境のみで実行し本番環境では実行しないコードに使用できます。
重要 条件付きコンパイルを使用する際には、コンパイル済みコードを常に実行する場合を除き、ディレクティブは単なるコメントであり条件付コードは開発中も「有効」であることを忘れないようにしてください。
デバッグディレクティブ
コンパイルの際、デフォルトではプロセッサステートメントは一切精査されません。したがって、この場合、結果は開発モードです。-debug
に変更した場合、よく似た結果が得られますが、プリプロセッサはアクティブとなります。実際には、プリプロセッサディレクティブが削除されている点のみが異なります。
たとえば、次のコマンドを見てください。
sencha compile -classpath=... \
-debug \
...
次のようなコードを生成します。
foo: function () {
if (sometest) {
Ext.log.warn("Something is wrong...");
}
this.bar();
}
では、こちらのコマンドはどうでしょうか。
sencha compile -classpath=... \
-debug=false \
...
次のようなコードを生成します。
foo: function () {
this.bar();
}
見てのとおり、if
テストとログステートメントの双方が削除されています。
ifディレクティブ
最も一般的なディレクティブはif
です。if
ディレクティブでは1つ以上の設定済みオプションをディレクティブの属性に対してテストし、偽と判定されたコードをブロック内から削除します。
例えば、
//<if debug>
//</if>
これは<debug>
ディレクティブに相当します。