拡張スクリプト・スタイルの条件指定とファイル単位の配信(改修案)
本体の標準機能ではありません
このページは本体を改修する場合の設計メモです。前提にした現行の実装は 1.5.8.1 です。
1.5.8.1 では、App_Data/Parameters/ExtendedScripts・ExtendedStyles に置いた .js / .css には適用条件を付けられず、全ページに効きます。また、条件に合うものを全部つないで 1 本のファイルとして配信します。ここでは、同じ名前の JSON を横に置くと条件を指定でき、条件付きのものはファイルごとに配信する改修をまとめます。
現行の実装
拡張機能ごとのファイル構成
拡張機能は「JSON(メタデータ)を持つか」で 2 種類に分かれます。
| 拡張機能 | ファイル | JSON | 本体を別ファイルに置く | 条件指定 |
|---|---|---|---|---|
| ExtendedScripts | .js | なし | — | 不可(全ページ) |
| ExtendedStyles | .css | なし | — | 不可(全ページ) |
| ExtendedHtmls | .html | なし | — | 不可(ファイル名の _ja などで言語だけ) |
| ExtendedServerScripts | .json | あり | .json.js(あれば Body を上書き) | 可 |
| ExtendedSqls | .json | あり | .json.sql(あれば CommandText を上書き) | 可 |
| ExtendedPlugins | .json | あり | なし(LibraryPath で DLL を指定) | 可 |
| ExtendedNavigationMenus | .json | あり | なし | 可 |
| ExtendedFields | .json | あり | なし | 可 |
.js / .css を読み込む Initializer.ExtendedScripts() / ExtendedStyles() は、ファイル名の昇順(サブフォルダは再帰)に Name・Path・Script(Style)だけを設定します。SiteIdList などの条件は空のままなので、ExtensionWhere で「条件なし」と判定されて全ページに効きます。詳しくは 拡張スクリプトの仕組み と 拡張スタイルの仕組み を参照してください。なお Extensions テーブルに登録した拡張スクリプト・スタイルには条件を付けられます(Extensions テーブルで拡張機能を DB 管理)。
条件の判定(ExtensionWhere)
どの拡張機能も ExtendedBase を継承し、ExtensionUtilities.ExtensionWhere<T>() で絞り込まれます(ExtensionUtilities.cs)。
| プロパティ | 型 | 意味 |
|---|---|---|
SiteIdList / IdList | List<long> | サイト ID / レコード ID |
DeptIdList / GroupIdList / UserIdList | List<int> | 組織 / グループ / ユーザー |
Controllers / Actions | List<string> | コントローラ名 / アクション名 |
ColumnList | List<string> | 項目名(項目拡張 HTML など) |
Disabled | bool | true で無効 |
SpecifyByName | bool | true なら Name が一致したときだけ |
リストが空なら条件なし、値があれば一致したときだけ、先頭に - を付けた値は「それ以外」です。
配信の流れ
図を読み込み中…
この方式には次の問題があります。
| 問題 | 内容 |
|---|---|
| キャッシュ | 1 ファイル変えるだけで v が変わり、関係ないスクリプトも取り直しになる |
| デバッグ | ブラウザの開発者ツールで、どのファイルのコードかが分かりにくい |
| 順序 | ファイル名の昇順でつながるので、依存関係のある順序はファイル名で調整するしかない |
改修案
1. .js.json / .css.json で条件を指定する
.js / .css と同じ名前に .json を付けたファイル(コンパニオンファイル)を置き、そこから条件だけを読み込みます。
App_Data/Parameters/ExtendedScripts/
├── my-script.js ← スクリプト本体(今までどおり)
└── my-script.js.json ← 条件(新規){
"SiteIdList": [100, 200],
"Controllers": ["items"],
"Actions": ["edit", "new"],
"Disabled": false
}Initializer.ExtendedScripts() の .js のループで、file.FullName + ".json" があれば ExtendedScript としてデシリアライズし、SiteIdList・IdList・DeptIdList・GroupIdList・UserIdList・Controllers・Actions・Disabled・Description を読み込んだ要素に写します。ExtendedStyles() も同じです。条件のプロパティは ExtendedBase にあるので、ExtendedScript / ExtendedStyle のクラスにプロパティを足す必要はありません。
*.js だけを列挙しているので、.js.json がスクリプトとして読まれることはありません。拡張 HTML にも name_ja.html.json のように同じ考え方を当てはめられます。
2. 条件付きのものはファイルごとに配信する
コンパニオンファイルを持つスクリプトは 1 つずつ <script> タグにし、/resources/scripts?name=ファイル名&v=そのファイルのハッシュ で返します。フォルダ構成を URL に出さないよう、パスではなく Name で識別します。
図を読み込み中…
ResourcesController.Scripts に name を受け取らせ、空なら今までどおり JavaScripts.Get、あれば新しく作る JavaScripts.GetByName(context, name) を呼びます。GetByName でも ExtensionWhere で条件を確かめ、条件に合わない名前を指定されたら返さないようにします。スタイル(Styles・Css・HtmlStyles)も同じ形にします。
3. 互換性
| 置いたファイル | 動作 |
|---|---|
.js だけ | 今までどおり(つないで配信・全ページ) |
.js と .js.json | JSON の条件で絞り、ファイルごとに配信 |
コンパニオンファイルを置かない限り今の動作は変わらないので、既存環境への影響はありません。
改修箇所
| ファイル | 内容 |
|---|---|
Implem.DefinitionAccessor/Initializer.cs | ExtendedScripts()・ExtendedStyles() でコンパニオンファイルを読む |
Implem.Pleasanter/Libraries/HtmlParts/HtmlScripts.cs | コンパニオンファイルのあるものを個別の <script> で出す |
Implem.Pleasanter/Libraries/HtmlParts/HtmlStyles.cs | 同じく個別の <link> で出す |
Implem.Pleasanter/Libraries/Resources/JavaScripts.cs | GetByName(context, name) を足す |
Implem.Pleasanter/Libraries/Resources/Css.cs | GetByName(context, name) を足す |
Implem.Pleasanter/Controllers/ResourcesController.cs | Scripts / Styles に name パラメータを足す |