@bestcss/webpack-loader 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yuta Ura
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/css.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ interface LoaderContext {
2
+ resourcePath: string;
3
+ }
4
+ /**
5
+ * 元ファイル(css`` を含む tsx 等)を受け取り、抽出した CSS テキストを
6
+ * 返す loader。メイン loader が発行する matchResource import
7
+ * (`<file>.bestcss.css!=!@bestcss/webpack-loader/css!<file>`)から使われる
8
+ */
9
+ export default function bestCssCssLoader(this: LoaderContext, source: string): string;
10
+ export {};
11
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAEA,UAAU,aAAa;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,MAAM,GACb,MAAM,CAMR"}
package/dist/css.js ADDED
@@ -0,0 +1,14 @@
1
+ import { transform } from "@bestcss/core";
2
+ /**
3
+ * 元ファイル(css`` を含む tsx 等)を受け取り、抽出した CSS テキストを
4
+ * 返す loader。メイン loader が発行する matchResource import
5
+ * (`<file>.bestcss.css!=!@bestcss/webpack-loader/css!<file>`)から使われる
6
+ */
7
+ export default function bestCssCssLoader(source) {
8
+ const result = transform(source, { filename: this.resourcePath });
9
+ // css`` を含まない入力はそのまま返す(冪等)。Turbopack は as: "*.css" の
10
+ // 適用後にルールを再評価することがあり、2 周目の入力は抽出済みの
11
+ // CSS テキストになるため、素通しできないと空になってしまう
12
+ return result?.css ?? source;
13
+ }
14
+ //# sourceMappingURL=css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.js","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAM1C;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAEtC,MAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAClE,qDAAqD;IACrD,mCAAmC;IACnC,iCAAiC;IACjC,OAAO,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface BestCssLoaderOptions {
2
+ /**
3
+ * 抽出 CSS の取り込み方。
4
+ *
5
+ * - "match-resource"(デフォルト): webpack の matchResource(`!=!`)構文で
6
+ * 「元ファイル自身を @bestcss/webpack-loader/css で CSS として再読み込み」する
7
+ * - "query": 自分自身をクエリ付き(`./file.tsx?bestcss`)で import する。
8
+ * matchResource を解釈しない Turbopack 向け。利用側で
9
+ * 「query が bestcss のとき @bestcss/webpack-loader/css を as: '*.css' で
10
+ * 実行する」rule を設定する
11
+ */
12
+ importStyle?: "match-resource" | "query";
13
+ }
14
+ interface LoaderContext {
15
+ resourcePath: string;
16
+ getOptions?: () => BestCssLoaderOptions;
17
+ callback: (error: Error | null, content?: string, sourceMap?: unknown) => void;
18
+ }
19
+ /**
20
+ * css`` をクラス名リテラルへ変換する webpack loader。
21
+ *
22
+ * 抽出した CSS は仮想モジュールではなく「元ファイル自身を CSS として
23
+ * 再読み込み」する形で取り込む。ファイルが実在するため、仮想モジュール
24
+ * 機構を持たないバンドラー(Turbopack 等の loader 互換環境)にも
25
+ * 同じ発想を展開できる(ADR-0008)
26
+ */
27
+ export default function bestCssLoader(this: LoaderContext, source: string): void;
28
+ export {};
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC;CAC1C;AAED,UAAU,aAAa;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,oBAAoB,CAAC;IACxC,QAAQ,EAAE,CACR,KAAK,EAAE,KAAK,GAAG,IAAI,EACnB,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,OAAO,KAChB,IAAI,CAAC;CACX;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CACnC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,MAAM,GACb,IAAI,CA4BN"}
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ import path from "node:path";
2
+ import { transform } from "@bestcss/core";
3
+ /**
4
+ * css`` をクラス名リテラルへ変換する webpack loader。
5
+ *
6
+ * 抽出した CSS は仮想モジュールではなく「元ファイル自身を CSS として
7
+ * 再読み込み」する形で取り込む。ファイルが実在するため、仮想モジュール
8
+ * 機構を持たないバンドラー(Turbopack 等の loader 互換環境)にも
9
+ * 同じ発想を展開できる(ADR-0008)
10
+ */
11
+ export default function bestCssLoader(source) {
12
+ const result = transform(source, { filename: this.resourcePath });
13
+ if (result === null) {
14
+ this.callback(null, source);
15
+ return;
16
+ }
17
+ // webpack のリクエスト文字列では ! が loader 区切り、? がクエリ開始として
18
+ // 解釈され、エスケープ手段がない。パスに含まれると任意 loader の注入に
19
+ // なり得るため明示的に拒否する
20
+ if (/[!?]/.test(this.resourcePath)) {
21
+ throw new Error(`bestcss: パスに "!" または "?" を含むファイルは扱えません: ${this.resourcePath}`);
22
+ }
23
+ const importStyle = this.getOptions?.().importStyle ?? "match-resource";
24
+ const cssRequest = importStyle === "query"
25
+ ? `./${path.basename(this.resourcePath)}?bestcss`
26
+ : // matchResource を .css にすることで、利用側の既存 CSS ルール
27
+ // (css-loader / mini-css-extract 等)がそのまま適用される
28
+ `${this.resourcePath}.bestcss.css!=!@bestcss/webpack-loader/css!${this.resourcePath}`;
29
+ this.callback(null, `${result.code}\nimport ${JSON.stringify(cssRequest)};\n`, result.map);
30
+ }
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AA0B1C;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAEnC,MAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAClE,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,iDAAiD;IACjD,yCAAyC;IACzC,iBAAiB;IACjB,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,2CAA2C,IAAI,CAAC,YAAY,EAAE,CAC/D,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,WAAW,IAAI,gBAAgB,CAAC;IACxE,MAAM,UAAU,GACd,WAAW,KAAK,OAAO;QACrB,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU;QACjD,CAAC,CAAC,6CAA6C;YAC7C,8CAA8C;YAC9C,GAAG,IAAI,CAAC,YAAY,8CAA8C,IAAI,CAAC,YAAY,EAAE,CAAC;IAC5F,IAAI,CAAC,QAAQ,CACX,IAAI,EACJ,GAAG,MAAM,CAAC,IAAI,YAAY,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,EACzD,MAAM,CAAC,GAAG,CACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,58 @@
1
+ export interface BestCssWebpackPluginOptions {
2
+ /**
3
+ * ビルド時にクラス名を使用頻度順の短い名前(a, b, ...)へ振り直す。
4
+ *
5
+ * @default true
6
+ */
7
+ minifyClassNames?: boolean;
8
+ }
9
+ interface AssetSource {
10
+ source: {
11
+ source: () => string | Buffer;
12
+ };
13
+ }
14
+ interface CompilationLike {
15
+ hooks: {
16
+ processAssets: {
17
+ tap: (options: {
18
+ name: string;
19
+ stage: number;
20
+ }, handler: (assets: Record<string, unknown>) => void) => void;
21
+ };
22
+ };
23
+ getAsset: (name: string) => AssetSource | undefined;
24
+ updateAsset: (name: string, source: unknown) => void;
25
+ }
26
+ interface CompilerLike {
27
+ webpack: {
28
+ Compilation: {
29
+ PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE: number;
30
+ };
31
+ sources: {
32
+ RawSource: new (source: string) => unknown;
33
+ };
34
+ };
35
+ hooks: {
36
+ thisCompilation: {
37
+ tap: (name: string, handler: (compilation: CompilationLike) => void) => void;
38
+ };
39
+ };
40
+ }
41
+ /**
42
+ * Vite 版の generateBundle 相当のサイズ最適化を webpack で行うプラグイン。
43
+ * CSS アセットの重複ルール排除と、クラス名の頻度順短縮(ADR-0004)。
44
+ *
45
+ * 生成クラス名の一覧は loader と状態を共有せず、CSS アセットのセレクタ
46
+ * (.bc...)から集める。loader が別プロセス・別インスタンスで動いても
47
+ * 自己完結するため。
48
+ *
49
+ * Turbopack にはアセット後処理のフックが存在しないため、このプラグインは
50
+ * webpack ビルド専用(Turbopack では内容ハッシュ名のまま配信される)
51
+ */
52
+ export declare class BestCssWebpackPlugin {
53
+ private readonly minifyClassNames;
54
+ constructor(options?: BestCssWebpackPluginOptions);
55
+ apply(compiler: CompilerLike): void;
56
+ }
57
+ export {};
58
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAID,UAAU,WAAW;IACnB,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,UAAU,eAAe;IACvB,KAAK,EAAE;QACL,aAAa,EAAE;YACb,GAAG,EAAE,CACH,OAAO,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,EACxC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,KAC/C,IAAI,CAAC;SACX,CAAC;KACH,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IACpD,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CACtD;AAED,UAAU,YAAY;IACpB,OAAO,EAAE;QACP,WAAW,EAAE;YAAE,kCAAkC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5D,OAAO,EAAE;YAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,KAAK,OAAO,CAAA;SAAE,CAAC;KACzD,CAAC;IACF,KAAK,EAAE;QACL,eAAe,EAAE;YACf,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,IAAI,KAAK,IAAI,CAAC;SAC9E,CAAC;KACH,CAAC;CACH;AAID;;;;;;;;;;GAUG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;gBAE/B,OAAO,GAAE,2BAAgC;IAIrD,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;CAgEpC"}
package/dist/plugin.js ADDED
@@ -0,0 +1,61 @@
1
+ import { applyRename, createRenameMap, dedupeCss } from "@bestcss/core";
2
+ const PLUGIN_NAME = "BestCssWebpackPlugin";
3
+ /**
4
+ * Vite 版の generateBundle 相当のサイズ最適化を webpack で行うプラグイン。
5
+ * CSS アセットの重複ルール排除と、クラス名の頻度順短縮(ADR-0004)。
6
+ *
7
+ * 生成クラス名の一覧は loader と状態を共有せず、CSS アセットのセレクタ
8
+ * (.bc...)から集める。loader が別プロセス・別インスタンスで動いても
9
+ * 自己完結するため。
10
+ *
11
+ * Turbopack にはアセット後処理のフックが存在しないため、このプラグインは
12
+ * webpack ビルド専用(Turbopack では内容ハッシュ名のまま配信される)
13
+ */
14
+ export class BestCssWebpackPlugin {
15
+ minifyClassNames;
16
+ constructor(options = {}) {
17
+ this.minifyClassNames = options.minifyClassNames ?? true;
18
+ }
19
+ apply(compiler) {
20
+ const { Compilation, sources } = compiler.webpack;
21
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
22
+ compilation.hooks.processAssets.tap({
23
+ name: PLUGIN_NAME,
24
+ stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE,
25
+ }, (assets) => {
26
+ const readAsset = (name) => compilation.getAsset(name)?.source.source().toString() ?? "";
27
+ const cssNames = Object.keys(assets).filter((n) => n.endsWith(".css"));
28
+ for (const name of cssNames) {
29
+ compilation.updateAsset(name, new sources.RawSource(dedupeCss(readAsset(name))));
30
+ }
31
+ if (!this.minifyClassNames) {
32
+ return;
33
+ }
34
+ const generated = new Set();
35
+ for (const name of cssNames) {
36
+ for (const matched of readAsset(name).matchAll(/\.(bc[a-z0-9]+)/g)) {
37
+ generated.add(matched[1]);
38
+ }
39
+ }
40
+ if (generated.size === 0) {
41
+ return;
42
+ }
43
+ const jsNames = Object.keys(assets).filter((n) => n.endsWith(".js"));
44
+ const frequencies = new Map([...generated].map((name) => [name, 0]));
45
+ for (const name of jsNames) {
46
+ for (const matched of readAsset(name).matchAll(/\bbc[a-z0-9]+\b/g)) {
47
+ const count = frequencies.get(matched[0]);
48
+ if (count !== undefined) {
49
+ frequencies.set(matched[0], count + 1);
50
+ }
51
+ }
52
+ }
53
+ const renameMap = createRenameMap(frequencies);
54
+ for (const name of [...jsNames, ...cssNames]) {
55
+ compilation.updateAsset(name, new sources.RawSource(applyRename(readAsset(name), renameMap)));
56
+ }
57
+ });
58
+ });
59
+ }
60
+ }
61
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AA0CxE,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,oBAAoB;IACd,gBAAgB,CAAU;IAE3C,YAAY,UAAuC,EAAE;QACnD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,QAAsB;QAC1B,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC;QAClD,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;YAC9D,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,CACjC;gBACE,IAAI,EAAE,WAAW;gBACjB,KAAK,EAAE,WAAW,CAAC,kCAAkC;aACtD,EACD,CAAC,MAAM,EAAE,EAAE;gBACT,MAAM,SAAS,GAAG,CAAC,IAAY,EAAU,EAAE,CACzC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAC/D,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAChD,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CACnB,CAAC;gBAEF,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;oBAC5B,WAAW,CAAC,WAAW,CACrB,IAAI,EACJ,IAAI,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAClD,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBAC3B,OAAO;gBACT,CAAC;gBAED,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;gBACpC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;oBAC5B,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,CAC5C,kBAAkB,CACnB,EAAE,CAAC;wBACF,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAW,CAAC,CAAC;oBACtC,CAAC;gBACH,CAAC;gBACD,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAO;gBACT,CAAC;gBAED,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;gBACrE,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CACxC,CAAC;gBACF,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;oBAC3B,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,CAC5C,kBAAkB,CACnB,EAAE,CAAC;wBACF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC1C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;4BACxB,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;wBACzC,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;gBAC/C,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC;oBAC7C,WAAW,CAAC,WAAW,CACrB,IAAI,EACJ,IAAI,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC,CAC/D,CAAC;gBACJ,CAAC;YACH,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
package/docs/index.md ADDED
@@ -0,0 +1,80 @@
1
+ # @bestcss/webpack-loader ドキュメント
2
+
3
+ このディレクトリはパッケージに同梱されており、インストールされているバージョンと常に一致する。**css`` の文法や内部のしくみは [core のドキュメント](../../core/docs/index.md)**(`node_modules/@bestcss/core/docs/`)を参照。
4
+
5
+ Vite 版と同じ変換コア(`@bestcss/core`)が動く。
6
+
7
+ ## webpack
8
+
9
+ ```js
10
+ // webpack.config.js
11
+ import MiniCssExtractPlugin from "mini-css-extract-plugin";
12
+ import { BestCssWebpackPlugin } from "@bestcss/webpack-loader/plugin";
13
+
14
+ export default {
15
+ module: {
16
+ rules: [
17
+ {
18
+ test: /\.[jt]sx?$/,
19
+ exclude: /node_modules/,
20
+ use: ["@bestcss/webpack-loader"],
21
+ },
22
+ {
23
+ test: /\.css$/,
24
+ // sideEffects: false 宣言下でも CSS import を保持する(css-loader の定石)
25
+ sideEffects: true,
26
+ use: [MiniCssExtractPlugin.loader, "css-loader"],
27
+ },
28
+ ],
29
+ },
30
+ plugins: [
31
+ new MiniCssExtractPlugin(),
32
+ // サイズ最適化(クラス名の頻度順短縮 + CSS の重複排除)
33
+ new BestCssWebpackPlugin(),
34
+ ],
35
+ };
36
+ ```
37
+
38
+ loader は抽出 CSS を matchResource(`!=!`)構文で「元ファイル自身の CSS としての再読み込み」として取り込むため、既存の CSS ルール(css-loader / mini-css-extract)がそのまま適用される。
39
+
40
+ ## Next.js(Turbopack)
41
+
42
+ Turbopack は matchResource を解釈しないため、`importStyle: "query"` と `turbopack.rules` で統合する:
43
+
44
+ ```ts
45
+ // next.config.ts
46
+ import type { NextConfig } from "next";
47
+
48
+ const nextConfig: NextConfig = {
49
+ turbopack: {
50
+ rules: {
51
+ "*.tsx": {
52
+ condition: {
53
+ all: [{ not: "foreign" }, { not: { query: /bestcss/ } }],
54
+ },
55
+ loaders: [
56
+ {
57
+ loader: "@bestcss/webpack-loader",
58
+ options: { importStyle: "query" },
59
+ },
60
+ ],
61
+ },
62
+ "*": {
63
+ condition: { all: [{ not: "foreign" }, { query: /bestcss/ }] },
64
+ loaders: ["@bestcss/webpack-loader/css"],
65
+ as: "*.css",
66
+ },
67
+ },
68
+ },
69
+ };
70
+
71
+ export default nextConfig;
72
+ ```
73
+
74
+ ## 制限
75
+
76
+ - **Turbopack ではサイズ最適化(クラス名短縮・CSS 重複排除)が使えない** — Turbopack にはアセット後処理のフック(webpack の processAssets 相当)が存在しないため。内容ハッシュ名(`bc...`、9 文字程度)のまま配信される。抽出・ゼロランタイムは動作する
77
+ - SSR スイート(ルート単位分割・`routeCssHrefs`)は Vite 版のみ
78
+ - ファイルパスに `!` または `?` を含むファイルは扱えない(webpack のリクエスト構文と衝突するため明示的にエラーになる)
79
+
80
+ 補足: `"sideEffects": false` を宣言したパッケージ内で css`` を使う場合は、上記 CSS ルールの `sideEffects: true` に加え、そのパッケージの宣言を `"sideEffects": ["**/*.css"]` にすること。
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@bestcss/webpack-loader",
3
+ "version": "0.1.0",
4
+ "description": "bestcss の webpack / Next.js (Turbopack) 統合。loader と最適化プラグイン",
5
+ "keywords": [
6
+ "css",
7
+ "css-in-js",
8
+ "zero-runtime",
9
+ "bestcss"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Yuta Ura",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/YutaUra/bestcss.git",
16
+ "directory": "packages/webpack-loader"
17
+ },
18
+ "type": "module",
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ },
30
+ "./css": {
31
+ "types": "./dist/css.d.ts",
32
+ "default": "./dist/css.js"
33
+ },
34
+ "./plugin": {
35
+ "types": "./dist/plugin.d.ts",
36
+ "default": "./dist/plugin.js"
37
+ }
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "docs"
42
+ ],
43
+ "dependencies": {
44
+ "@bestcss/core": "0.1.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^26.1.0",
48
+ "css-loader": "^7.1.4",
49
+ "mini-css-extract-plugin": "^2.10.2",
50
+ "typescript": "^6.0.3",
51
+ "webpack": "^5.108.3"
52
+ },
53
+ "scripts": {
54
+ "build": "tsc -p tsconfig.build.json",
55
+ "typecheck": "tsc --noEmit"
56
+ }
57
+ }