@wcstack/autoloader 1.9.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +275 -275
- package/README.md +276 -276
- package/dist/auto.js +3 -3
- package/dist/auto.min.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/package.json +74 -74
package/README.ja.md
CHANGED
|
@@ -1,276 +1,276 @@
|
|
|
1
|
-
# @wcstack/autoloader
|
|
2
|
-
|
|
3
|
-
**もしカスタム要素が勝手に読み込まれたら?**
|
|
4
|
-
|
|
5
|
-
カスタム要素のタグを書くだけで、ブラウザが自動的にその定義を見つけてくれる未来を想像してみてください。`import` も `customElements.define()` も、煩雑な登録処理も一切不要です。タグを書くだけで、必要なコンポーネントが読み込まれます。
|
|
6
|
-
|
|
7
|
-
これこそが `<wcs-autoloader>` が追求するコンセプトです。CDNからの読み込みのみで動作し、依存ライブラリはゼロ。標準の Import Map を活用します。
|
|
8
|
-
|
|
9
|
-
## 特徴
|
|
10
|
-
|
|
11
|
-
### 基本機能
|
|
12
|
-
* **自動検出とロード**: 未定義のカスタム要素タグを検知し、自動的に `import()` します。
|
|
13
|
-
* **動的変更への対応**: `innerHTML` や `appendChild` で後から追加された要素も即座に検知します。
|
|
14
|
-
* **ゼロコンフィグ / ビルドレス**: バンドラー設定不要で、ブラウザ標準機能のみで動作します。
|
|
15
|
-
* **依存関係ゼロ**: 外部ライブラリに依存せず軽量です。
|
|
16
|
-
|
|
17
|
-
### ユニークな機能
|
|
18
|
-
* **Import Map 拡張**: 標準の Import Map 内に `@components/` ルールを記述する標準準拠のアプローチ。
|
|
19
|
-
* **名前空間プレフィックスによる自動解決**: 1つ1つの登録は不要。`@components/ui/` のようなプレフィックス定義だけで、`<ui-button>` → `button.js` のように自動解決します。
|
|
20
|
-
* **インラインローダー指定**: Import Map のキーで `@components/ui|lit/` のようにローダーを指定可能。複数フレームワークの混在も容易です。
|
|
21
|
-
* **高度な `is` 属性サポート**: 拡張ビルトイン要素も自動ロード。クラス定義から `extends` を推論し、適切に `define` します。
|
|
22
|
-
* **抽象化されたローダー**: ファイルの読み込みロジック自体がプラガブルで、拡張子や処理系をカスタマイズ可能です。
|
|
23
|
-
|
|
24
|
-
## 使い方
|
|
25
|
-
|
|
26
|
-
### 1. Import Mapの設定
|
|
27
|
-
|
|
28
|
-
`@wcstack/autoloader`キーに、オートローダーのパスを定義します。
|
|
29
|
-
`@components/`プレフィックスを使用して、importmap内にコンポーネントのパスを定義します。
|
|
30
|
-
|
|
31
|
-
```html
|
|
32
|
-
<script type="importmap">
|
|
33
|
-
{
|
|
34
|
-
"imports": {
|
|
35
|
-
"@wcstack/autoloader": "/path/to/autoloader",
|
|
36
|
-
"@components/ui/": "./components/ui/",
|
|
37
|
-
"@components/app/": "./components/app/"
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
</script>
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### 2. オートローダーの読み込み
|
|
44
|
-
|
|
45
|
-
`<script>`タグでオートローダースクリプトを読み込むか、手動で`bootstrapAutoloader`をインポートして呼び出します。
|
|
46
|
-
|
|
47
|
-
```html
|
|
48
|
-
<!-- 方法A: ゼロコンフィグスクリプト(推奨) -->
|
|
49
|
-
<script type="module" src="https://esm.run/@wcstack/autoloader/auto"></script>
|
|
50
|
-
|
|
51
|
-
<!-- 方法B: 手動初期化 -->
|
|
52
|
-
<script type="module">
|
|
53
|
-
import { bootstrapAutoloader } from "@wcstack/autoloader";
|
|
54
|
-
bootstrapAutoloader();
|
|
55
|
-
</script>
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### 3. `<wcs-autoloader>`要素の配置
|
|
59
|
-
|
|
60
|
-
HTMLに`<wcs-autoloader>`を追加します。この要素がロードライフサイクルのトリガーとなり、要素の生成時に即時読み込みが開始され、DOMへの接続時に遅延読み込みが開始されます。
|
|
61
|
-
|
|
62
|
-
```html
|
|
63
|
-
<body>
|
|
64
|
-
<wcs-autoloader></wcs-autoloader>
|
|
65
|
-
<!-- アプリのコンポーネント -->
|
|
66
|
-
</body>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### 4. コンポーネントの使用
|
|
70
|
-
|
|
71
|
-
HTMLでカスタム要素を使用するだけです。`@wcstack/autoloader`が自動的に対応するファイルをインポートします。
|
|
72
|
-
|
|
73
|
-
```html
|
|
74
|
-
<!-- ./components/ui/button.js を読み込み -->
|
|
75
|
-
<ui-button></ui-button>
|
|
76
|
-
|
|
77
|
-
<!-- ./components/app/header.js を読み込み -->
|
|
78
|
-
<app-header></app-header>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Import Map構文
|
|
82
|
-
|
|
83
|
-
`@wcstack/autoloader`は`@components/`で始まるimportmapのキーを解析します。
|
|
84
|
-
|
|
85
|
-
### 遅延読み込み(名前空間)
|
|
86
|
-
|
|
87
|
-
コンポーネントグループの遅延読み込みを有効にするには、`/`で終わるキーを使用します。
|
|
88
|
-
|
|
89
|
-
形式: `"@components/<プレフィックス>[|<ローダー>]/": "<パス>"`
|
|
90
|
-
|
|
91
|
-
- **プレフィックス**: タグのプレフィックス。スラッシュはダッシュに変換されます。
|
|
92
|
-
- **ローダー**(オプション): 使用するローダー(例: `vanilla`、`lit`)。デフォルトは`vanilla`。
|
|
93
|
-
|
|
94
|
-
**例:**
|
|
95
|
-
|
|
96
|
-
```json
|
|
97
|
-
{
|
|
98
|
-
"imports": {
|
|
99
|
-
// <my-component> を ./components/component.js にマッピング
|
|
100
|
-
"@components/my/": "./components/",
|
|
101
|
-
|
|
102
|
-
// <ui-button> を ./ui/button.js にマッピング('lit'ローダーを使用)
|
|
103
|
-
"@components/ui|lit/": "./ui/"
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### 即時読み込み
|
|
109
|
-
|
|
110
|
-
特定のコンポーネントを即座に読み込むには、`/`で終わらないキーを使用します。
|
|
111
|
-
|
|
112
|
-
形式: `"@components/<タグ名>[|<ローダー>[,<extends>]]": "<パス>"`
|
|
113
|
-
|
|
114
|
-
- **ローダー**(オプション): 省略した場合、ファイル拡張子に基づいて自動解決されます(例: `.js` -> デフォルトローダー、`.lit.js` -> litローダー)。
|
|
115
|
-
- **extends**(オプション): 省略した場合、コンポーネントクラスがビルトインHTML要素を継承しているかどうかを自動検出します(例: `HTMLButtonElement` -> `extends: 'button'`)。
|
|
116
|
-
|
|
117
|
-
**例:**
|
|
118
|
-
|
|
119
|
-
```json
|
|
120
|
-
{
|
|
121
|
-
"imports": {
|
|
122
|
-
// <my-button> を ./my-button.js から即時読み込み
|
|
123
|
-
// ローダー: 自動検出(.js)
|
|
124
|
-
// extends: 自動検出(例: クラスがHTMLButtonElementを継承している場合)
|
|
125
|
-
"@components/my-button": "./my-button.js",
|
|
126
|
-
|
|
127
|
-
// ローダーとextendsを明示的に指定
|
|
128
|
-
"@components/fancy-input|vanilla,input": "./fancy-input.js",
|
|
129
|
-
|
|
130
|
-
// Lit要素のローダーを自動検出(litローダーが設定されている場合)
|
|
131
|
-
"@components/my-lit-button": "./my-button.lit.js"
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## コンポーネントの要件
|
|
137
|
-
|
|
138
|
-
デフォルト(`vanilla`ローダー使用時)では、コンポーネントファイルは以下を満たす必要があります:
|
|
139
|
-
|
|
140
|
-
1. `.js`拡張子(設定で変更可能)
|
|
141
|
-
2. カスタム要素クラスを`default`としてエクスポート
|
|
142
|
-
|
|
143
|
-
```javascript
|
|
144
|
-
// components/ui/button.js
|
|
145
|
-
export default class UiButton extends HTMLElement {
|
|
146
|
-
constructor() {
|
|
147
|
-
super();
|
|
148
|
-
this.attachShadow({ mode: 'open' }).innerHTML = '<button><slot></slot></button>';
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## カスタマイズドビルトイン要素(`is`属性)
|
|
154
|
-
|
|
155
|
-
オートローダーは`is`属性を使用したカスタマイズドビルトイン要素を検出します:
|
|
156
|
-
|
|
157
|
-
```html
|
|
158
|
-
<!-- オートローダーが自動的に "my-button" を検出してロード -->
|
|
159
|
-
<button is="my-button">Click me</button>
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
**遅延読み込み**: `extends`値はホスト要素のタグから自動推論されます(例: `<button>` → `extends: "button"`)。
|
|
163
|
-
|
|
164
|
-
**即時読み込み**: `extends`値はコンポーネントクラスのプロトタイプから推論されます(例: `HTMLButtonElement` → `extends: "button"`)。Import Mapで明示的に指定することもできます:
|
|
165
|
-
|
|
166
|
-
```json
|
|
167
|
-
{
|
|
168
|
-
"imports": {
|
|
169
|
-
"@components/my-button|vanilla,button": "./my-button.js"
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
```javascript
|
|
175
|
-
// my-button.js
|
|
176
|
-
export default class MyButton extends HTMLButtonElement {
|
|
177
|
-
connectedCallback() {
|
|
178
|
-
this.style.color = 'red';
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// オートローダーが呼び出す: customElements.define('my-button', MyButton, { extends: 'button' })
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## 設定
|
|
185
|
-
|
|
186
|
-
`bootstrapAutoloader()`にオプションの設定オブジェクトを渡して初期化します:
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
interface ILoader {
|
|
190
|
-
postfix: string;
|
|
191
|
-
loader: (path: string) => Promise<CustomElementConstructor | null>;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
interface IWritableTagNames {
|
|
195
|
-
autoloader?: string;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
interface IWritableConfig {
|
|
199
|
-
loaders?: Record<string, ILoader | string>;
|
|
200
|
-
observable?: boolean;
|
|
201
|
-
tagNames?: IWritableTagNames;
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
| オプション | 型 | デフォルト | 説明 |
|
|
206
|
-
|--------|------|---------|-------------|
|
|
207
|
-
| `loaders` | `Record<string, ILoader \| string>` | 下記参照 | ローダー定義。値は`ILoader`オブジェクトまたは他のローダーキーへの文字列エイリアス。 |
|
|
208
|
-
| `observable` | `boolean` | `true` | MutationObserverによる動的追加要素の検出を有効化。`false`で無効化。 |
|
|
209
|
-
| `tagNames` | `IWritableTagNames` | `{ autoloader: "wcs-autoloader" }` | カスタム要素のタグ名。名前衝突を避けるために変更可能。 |
|
|
210
|
-
|
|
211
|
-
### デフォルト設定
|
|
212
|
-
|
|
213
|
-
```javascript
|
|
214
|
-
{
|
|
215
|
-
loaders: {
|
|
216
|
-
// 組み込みvanillaローダー: モジュールをインポートしdefaultエクスポートを返す
|
|
217
|
-
vanilla: { postfix: ".js", loader: vanillaLoader },
|
|
218
|
-
// デフォルトキー: どのローダーにも一致しない場合のフォールバック
|
|
219
|
-
"*": "vanilla"
|
|
220
|
-
},
|
|
221
|
-
observable: true
|
|
222
|
-
}
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
- **`vanilla`**: 組み込みローダー。モジュールを動的インポートし、`default`エクスポートをカスタム要素コンストラクタとして返します。
|
|
226
|
-
- **`"*"`(デフォルトキー)**: フォールバックローダー。値は文字列エイリアス`"vanilla"`で、マッチしないコンポーネントはvanillaローダーを使用します。
|
|
227
|
-
|
|
228
|
-
### ローダー解決
|
|
229
|
-
|
|
230
|
-
コンポーネントに明示的なローダーキーがない場合(例: `|loader`なしの遅延読み込み名前空間)、以下の順序でローダーを解決します:
|
|
231
|
-
|
|
232
|
-
1. **postfix一致**: ファイルパスを登録済みローダーの`postfix`値と照合(最長一致優先)。
|
|
233
|
-
2. **デフォルトキーフォールバック**: postfixが一致しない場合、`"*"`キーで参照されるローダーを使用。
|
|
234
|
-
|
|
235
|
-
### 例
|
|
236
|
-
|
|
237
|
-
```javascript
|
|
238
|
-
import { bootstrapAutoloader } from "@wcstack/autoloader";
|
|
239
|
-
|
|
240
|
-
bootstrapAutoloader({
|
|
241
|
-
loaders: {
|
|
242
|
-
// vanillaローダーのファイル拡張子を変更
|
|
243
|
-
vanilla: { postfix: ".vanilla.js" },
|
|
244
|
-
// .lit.jsファイル用のカスタムローダーを追加
|
|
245
|
-
lit: {
|
|
246
|
-
postfix: ".lit.js",
|
|
247
|
-
loader: async (path) => {
|
|
248
|
-
const module = await import(path);
|
|
249
|
-
return module.default;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
// MutationObserverを無効化(動的コンテンツ検出なし)
|
|
254
|
-
observable: false
|
|
255
|
-
});
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
## 動作の仕組み
|
|
259
|
-
|
|
260
|
-
### ロードライフサイクル
|
|
261
|
-
|
|
262
|
-
1. **登録**: `bootstrapAutoloader()`が`customElements.define()`で`<wcs-autoloader>`カスタム要素を登録。
|
|
263
|
-
2. **constructor**(要素生成時): すべての`<script type="importmap">`要素から`@components/`エントリを解析。名前空間でないキー(`/`で終わらない)のコンポーネントを即座に並列ロード開始。
|
|
264
|
-
3. **connectedCallback**(DOM接続時): ドキュメントがまだ読み込み中であれば`DOMContentLoaded`を待機し、TreeWalkerを使用してDOMをスキャンして登録済み名前空間に一致する未定義カスタム要素を検出。
|
|
265
|
-
4. **ネストされたロード**: カスタム要素が定義・アップグレードされた後、そのShadow DOM(存在する場合)もスキャンしてネストされたカスタム要素を検出。
|
|
266
|
-
5. **監視**(`observable: true`の場合): MutationObserverがDOMへの新規要素追加を監視し、遅延読み込みをトリガー。
|
|
267
|
-
6. **disconnectedCallback**(要素削除時): MutationObserverを切断し、シングルトンインスタンスを解放。
|
|
268
|
-
|
|
269
|
-
### エラーハンドリング
|
|
270
|
-
|
|
271
|
-
- ロードに失敗したコンポーネントは内部的に追跡され、以降のスキャンで再試行されません。
|
|
272
|
-
- 重複ロードの防止: コンポーネントが既にロード中の場合、後続のリクエストは既存のロード完了を待機します。
|
|
273
|
-
|
|
274
|
-
## ライセンス
|
|
275
|
-
|
|
1
|
+
# @wcstack/autoloader
|
|
2
|
+
|
|
3
|
+
**もしカスタム要素が勝手に読み込まれたら?**
|
|
4
|
+
|
|
5
|
+
カスタム要素のタグを書くだけで、ブラウザが自動的にその定義を見つけてくれる未来を想像してみてください。`import` も `customElements.define()` も、煩雑な登録処理も一切不要です。タグを書くだけで、必要なコンポーネントが読み込まれます。
|
|
6
|
+
|
|
7
|
+
これこそが `<wcs-autoloader>` が追求するコンセプトです。CDNからの読み込みのみで動作し、依存ライブラリはゼロ。標準の Import Map を活用します。
|
|
8
|
+
|
|
9
|
+
## 特徴
|
|
10
|
+
|
|
11
|
+
### 基本機能
|
|
12
|
+
* **自動検出とロード**: 未定義のカスタム要素タグを検知し、自動的に `import()` します。
|
|
13
|
+
* **動的変更への対応**: `innerHTML` や `appendChild` で後から追加された要素も即座に検知します。
|
|
14
|
+
* **ゼロコンフィグ / ビルドレス**: バンドラー設定不要で、ブラウザ標準機能のみで動作します。
|
|
15
|
+
* **依存関係ゼロ**: 外部ライブラリに依存せず軽量です。
|
|
16
|
+
|
|
17
|
+
### ユニークな機能
|
|
18
|
+
* **Import Map 拡張**: 標準の Import Map 内に `@components/` ルールを記述する標準準拠のアプローチ。
|
|
19
|
+
* **名前空間プレフィックスによる自動解決**: 1つ1つの登録は不要。`@components/ui/` のようなプレフィックス定義だけで、`<ui-button>` → `button.js` のように自動解決します。
|
|
20
|
+
* **インラインローダー指定**: Import Map のキーで `@components/ui|lit/` のようにローダーを指定可能。複数フレームワークの混在も容易です。
|
|
21
|
+
* **高度な `is` 属性サポート**: 拡張ビルトイン要素も自動ロード。クラス定義から `extends` を推論し、適切に `define` します。
|
|
22
|
+
* **抽象化されたローダー**: ファイルの読み込みロジック自体がプラガブルで、拡張子や処理系をカスタマイズ可能です。
|
|
23
|
+
|
|
24
|
+
## 使い方
|
|
25
|
+
|
|
26
|
+
### 1. Import Mapの設定
|
|
27
|
+
|
|
28
|
+
`@wcstack/autoloader`キーに、オートローダーのパスを定義します。
|
|
29
|
+
`@components/`プレフィックスを使用して、importmap内にコンポーネントのパスを定義します。
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<script type="importmap">
|
|
33
|
+
{
|
|
34
|
+
"imports": {
|
|
35
|
+
"@wcstack/autoloader": "/path/to/autoloader",
|
|
36
|
+
"@components/ui/": "./components/ui/",
|
|
37
|
+
"@components/app/": "./components/app/"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. オートローダーの読み込み
|
|
44
|
+
|
|
45
|
+
`<script>`タグでオートローダースクリプトを読み込むか、手動で`bootstrapAutoloader`をインポートして呼び出します。
|
|
46
|
+
|
|
47
|
+
```html
|
|
48
|
+
<!-- 方法A: ゼロコンフィグスクリプト(推奨) -->
|
|
49
|
+
<script type="module" src="https://esm.run/@wcstack/autoloader/auto"></script>
|
|
50
|
+
|
|
51
|
+
<!-- 方法B: 手動初期化 -->
|
|
52
|
+
<script type="module">
|
|
53
|
+
import { bootstrapAutoloader } from "@wcstack/autoloader";
|
|
54
|
+
bootstrapAutoloader();
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. `<wcs-autoloader>`要素の配置
|
|
59
|
+
|
|
60
|
+
HTMLに`<wcs-autoloader>`を追加します。この要素がロードライフサイクルのトリガーとなり、要素の生成時に即時読み込みが開始され、DOMへの接続時に遅延読み込みが開始されます。
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<body>
|
|
64
|
+
<wcs-autoloader></wcs-autoloader>
|
|
65
|
+
<!-- アプリのコンポーネント -->
|
|
66
|
+
</body>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 4. コンポーネントの使用
|
|
70
|
+
|
|
71
|
+
HTMLでカスタム要素を使用するだけです。`@wcstack/autoloader`が自動的に対応するファイルをインポートします。
|
|
72
|
+
|
|
73
|
+
```html
|
|
74
|
+
<!-- ./components/ui/button.js を読み込み -->
|
|
75
|
+
<ui-button></ui-button>
|
|
76
|
+
|
|
77
|
+
<!-- ./components/app/header.js を読み込み -->
|
|
78
|
+
<app-header></app-header>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Import Map構文
|
|
82
|
+
|
|
83
|
+
`@wcstack/autoloader`は`@components/`で始まるimportmapのキーを解析します。
|
|
84
|
+
|
|
85
|
+
### 遅延読み込み(名前空間)
|
|
86
|
+
|
|
87
|
+
コンポーネントグループの遅延読み込みを有効にするには、`/`で終わるキーを使用します。
|
|
88
|
+
|
|
89
|
+
形式: `"@components/<プレフィックス>[|<ローダー>]/": "<パス>"`
|
|
90
|
+
|
|
91
|
+
- **プレフィックス**: タグのプレフィックス。スラッシュはダッシュに変換されます。
|
|
92
|
+
- **ローダー**(オプション): 使用するローダー(例: `vanilla`、`lit`)。デフォルトは`vanilla`。
|
|
93
|
+
|
|
94
|
+
**例:**
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"imports": {
|
|
99
|
+
// <my-component> を ./components/component.js にマッピング
|
|
100
|
+
"@components/my/": "./components/",
|
|
101
|
+
|
|
102
|
+
// <ui-button> を ./ui/button.js にマッピング('lit'ローダーを使用)
|
|
103
|
+
"@components/ui|lit/": "./ui/"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 即時読み込み
|
|
109
|
+
|
|
110
|
+
特定のコンポーネントを即座に読み込むには、`/`で終わらないキーを使用します。
|
|
111
|
+
|
|
112
|
+
形式: `"@components/<タグ名>[|<ローダー>[,<extends>]]": "<パス>"`
|
|
113
|
+
|
|
114
|
+
- **ローダー**(オプション): 省略した場合、ファイル拡張子に基づいて自動解決されます(例: `.js` -> デフォルトローダー、`.lit.js` -> litローダー)。
|
|
115
|
+
- **extends**(オプション): 省略した場合、コンポーネントクラスがビルトインHTML要素を継承しているかどうかを自動検出します(例: `HTMLButtonElement` -> `extends: 'button'`)。
|
|
116
|
+
|
|
117
|
+
**例:**
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"imports": {
|
|
122
|
+
// <my-button> を ./my-button.js から即時読み込み
|
|
123
|
+
// ローダー: 自動検出(.js)
|
|
124
|
+
// extends: 自動検出(例: クラスがHTMLButtonElementを継承している場合)
|
|
125
|
+
"@components/my-button": "./my-button.js",
|
|
126
|
+
|
|
127
|
+
// ローダーとextendsを明示的に指定
|
|
128
|
+
"@components/fancy-input|vanilla,input": "./fancy-input.js",
|
|
129
|
+
|
|
130
|
+
// Lit要素のローダーを自動検出(litローダーが設定されている場合)
|
|
131
|
+
"@components/my-lit-button": "./my-button.lit.js"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## コンポーネントの要件
|
|
137
|
+
|
|
138
|
+
デフォルト(`vanilla`ローダー使用時)では、コンポーネントファイルは以下を満たす必要があります:
|
|
139
|
+
|
|
140
|
+
1. `.js`拡張子(設定で変更可能)
|
|
141
|
+
2. カスタム要素クラスを`default`としてエクスポート
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
// components/ui/button.js
|
|
145
|
+
export default class UiButton extends HTMLElement {
|
|
146
|
+
constructor() {
|
|
147
|
+
super();
|
|
148
|
+
this.attachShadow({ mode: 'open' }).innerHTML = '<button><slot></slot></button>';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## カスタマイズドビルトイン要素(`is`属性)
|
|
154
|
+
|
|
155
|
+
オートローダーは`is`属性を使用したカスタマイズドビルトイン要素を検出します:
|
|
156
|
+
|
|
157
|
+
```html
|
|
158
|
+
<!-- オートローダーが自動的に "my-button" を検出してロード -->
|
|
159
|
+
<button is="my-button">Click me</button>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**遅延読み込み**: `extends`値はホスト要素のタグから自動推論されます(例: `<button>` → `extends: "button"`)。
|
|
163
|
+
|
|
164
|
+
**即時読み込み**: `extends`値はコンポーネントクラスのプロトタイプから推論されます(例: `HTMLButtonElement` → `extends: "button"`)。Import Mapで明示的に指定することもできます:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"imports": {
|
|
169
|
+
"@components/my-button|vanilla,button": "./my-button.js"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
// my-button.js
|
|
176
|
+
export default class MyButton extends HTMLButtonElement {
|
|
177
|
+
connectedCallback() {
|
|
178
|
+
this.style.color = 'red';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// オートローダーが呼び出す: customElements.define('my-button', MyButton, { extends: 'button' })
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 設定
|
|
185
|
+
|
|
186
|
+
`bootstrapAutoloader()`にオプションの設定オブジェクトを渡して初期化します:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
interface ILoader {
|
|
190
|
+
postfix: string;
|
|
191
|
+
loader: (path: string) => Promise<CustomElementConstructor | null>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
interface IWritableTagNames {
|
|
195
|
+
autoloader?: string;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
interface IWritableConfig {
|
|
199
|
+
loaders?: Record<string, ILoader | string>;
|
|
200
|
+
observable?: boolean;
|
|
201
|
+
tagNames?: IWritableTagNames;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
| オプション | 型 | デフォルト | 説明 |
|
|
206
|
+
|--------|------|---------|-------------|
|
|
207
|
+
| `loaders` | `Record<string, ILoader \| string>` | 下記参照 | ローダー定義。値は`ILoader`オブジェクトまたは他のローダーキーへの文字列エイリアス。 |
|
|
208
|
+
| `observable` | `boolean` | `true` | MutationObserverによる動的追加要素の検出を有効化。`false`で無効化。 |
|
|
209
|
+
| `tagNames` | `IWritableTagNames` | `{ autoloader: "wcs-autoloader" }` | カスタム要素のタグ名。名前衝突を避けるために変更可能。 |
|
|
210
|
+
|
|
211
|
+
### デフォルト設定
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
{
|
|
215
|
+
loaders: {
|
|
216
|
+
// 組み込みvanillaローダー: モジュールをインポートしdefaultエクスポートを返す
|
|
217
|
+
vanilla: { postfix: ".js", loader: vanillaLoader },
|
|
218
|
+
// デフォルトキー: どのローダーにも一致しない場合のフォールバック
|
|
219
|
+
"*": "vanilla"
|
|
220
|
+
},
|
|
221
|
+
observable: true
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
- **`vanilla`**: 組み込みローダー。モジュールを動的インポートし、`default`エクスポートをカスタム要素コンストラクタとして返します。
|
|
226
|
+
- **`"*"`(デフォルトキー)**: フォールバックローダー。値は文字列エイリアス`"vanilla"`で、マッチしないコンポーネントはvanillaローダーを使用します。
|
|
227
|
+
|
|
228
|
+
### ローダー解決
|
|
229
|
+
|
|
230
|
+
コンポーネントに明示的なローダーキーがない場合(例: `|loader`なしの遅延読み込み名前空間)、以下の順序でローダーを解決します:
|
|
231
|
+
|
|
232
|
+
1. **postfix一致**: ファイルパスを登録済みローダーの`postfix`値と照合(最長一致優先)。
|
|
233
|
+
2. **デフォルトキーフォールバック**: postfixが一致しない場合、`"*"`キーで参照されるローダーを使用。
|
|
234
|
+
|
|
235
|
+
### 例
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
import { bootstrapAutoloader } from "@wcstack/autoloader";
|
|
239
|
+
|
|
240
|
+
bootstrapAutoloader({
|
|
241
|
+
loaders: {
|
|
242
|
+
// vanillaローダーのファイル拡張子を変更
|
|
243
|
+
vanilla: { postfix: ".vanilla.js" },
|
|
244
|
+
// .lit.jsファイル用のカスタムローダーを追加
|
|
245
|
+
lit: {
|
|
246
|
+
postfix: ".lit.js",
|
|
247
|
+
loader: async (path) => {
|
|
248
|
+
const module = await import(path);
|
|
249
|
+
return module.default;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
// MutationObserverを無効化(動的コンテンツ検出なし)
|
|
254
|
+
observable: false
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## 動作の仕組み
|
|
259
|
+
|
|
260
|
+
### ロードライフサイクル
|
|
261
|
+
|
|
262
|
+
1. **登録**: `bootstrapAutoloader()`が`customElements.define()`で`<wcs-autoloader>`カスタム要素を登録。
|
|
263
|
+
2. **constructor**(要素生成時): すべての`<script type="importmap">`要素から`@components/`エントリを解析。名前空間でないキー(`/`で終わらない)のコンポーネントを即座に並列ロード開始。
|
|
264
|
+
3. **connectedCallback**(DOM接続時): ドキュメントがまだ読み込み中であれば`DOMContentLoaded`を待機し、TreeWalkerを使用してDOMをスキャンして登録済み名前空間に一致する未定義カスタム要素を検出。
|
|
265
|
+
4. **ネストされたロード**: カスタム要素が定義・アップグレードされた後、そのShadow DOM(存在する場合)もスキャンしてネストされたカスタム要素を検出。
|
|
266
|
+
5. **監視**(`observable: true`の場合): MutationObserverがDOMへの新規要素追加を監視し、遅延読み込みをトリガー。
|
|
267
|
+
6. **disconnectedCallback**(要素削除時): MutationObserverを切断し、シングルトンインスタンスを解放。
|
|
268
|
+
|
|
269
|
+
### エラーハンドリング
|
|
270
|
+
|
|
271
|
+
- ロードに失敗したコンポーネントは内部的に追跡され、以降のスキャンで再試行されません。
|
|
272
|
+
- 重複ロードの防止: コンポーネントが既にロード中の場合、後続のリクエストは既存のロード完了を待機します。
|
|
273
|
+
|
|
274
|
+
## ライセンス
|
|
275
|
+
|
|
276
276
|
MIT
|