@griffel/webpack-plugin 2.0.0 → 3.0.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/CHANGELOG.md CHANGED
@@ -1,12 +1,26 @@
1
1
  # Change Log - @griffel/webpack-plugin
2
2
 
3
- This log was last generated on Fri, 06 Mar 2026 15:54:55 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 11 Mar 2026 13:31:20 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.0.0
8
+
9
+ Wed, 11 Mar 2026 13:31:20 GMT
10
+
11
+ ### Major changes
12
+
13
+ - BREAKING: Remove babelOptions from WebpackLoaderOptions. Uses @griffel/transform-shaker instead of @linaria/shaker. (olfedias@microsoft.com)
14
+ - Bump @griffel/transform to v2.0.0
15
+
16
+ ### Patches
17
+
18
+ - fix: make CJS the default resolver, ESM the clone (olfedias@microsoft.com)
19
+ - feat: add collectPerfIssues option to report CJS modules and barrel re-exports (olfedias@microsoft.com)
20
+
7
21
  ## 2.0.0
8
22
 
9
- Fri, 06 Mar 2026 15:54:55 GMT
23
+ Fri, 06 Mar 2026 15:56:28 GMT
10
24
 
11
25
  ### Major changes
12
26
 
@@ -1,9 +1,10 @@
1
1
  import { GriffelRenderer } from '@griffel/core';
2
2
  import { Compilation, Compiler } from 'webpack';
3
- import { TransformResolverFactory } from './resolver/types.mjs';
3
+ import { TransformResolverFactory } from './resolver/createResolverFactory.mjs';
4
4
  type EntryPoint = Compilation['entrypoints'] extends Map<unknown, infer I> ? I : never;
5
5
  export type GriffelCSSExtractionPluginOptions = {
6
6
  collectStats?: boolean;
7
+ collectPerfIssues?: boolean;
7
8
  compareMediaQueries?: GriffelRenderer['compareMediaQueries'];
8
9
  /** Allows to override resolver used to resolve imports inside evaluated modules. */
9
10
  resolverFactory?: TransformResolverFactory;
package/constants.d.mts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { LoaderContext } from 'webpack';
2
- import { TransformResolver } from './resolver/types.mjs';
2
+ import { TransformResolver, TransformPerfIssue } from '@griffel/transform';
3
3
  export declare const PLUGIN_NAME = "GriffelExtractPlugin";
4
4
  export declare const GriffelCssLoaderContextKey: unique symbol;
5
5
  export interface GriffelLoaderContextSupplement {
6
+ collectPerfIssues: boolean;
6
7
  resolveModule: TransformResolver;
7
8
  registerExtractedCss(css: string): void;
8
9
  getExtractedCss(): string;
@@ -12,6 +13,7 @@ export interface GriffelLoaderContextSupplement {
12
13
  filename: string;
13
14
  step: 'transform';
14
15
  evaluationMode: 'ast' | 'vm';
16
+ perfIssues?: TransformPerfIssue[];
15
17
  };
16
18
  }): T;
17
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@griffel/webpack-plugin",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "Webpack plugin that performs CSS extraction for Griffel",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,8 +20,8 @@
20
20
  "./package.json": "./package.json"
21
21
  },
22
22
  "dependencies": {
23
- "@griffel/transform": "^1.2.1",
24
23
  "@griffel/core": "^1.20.1",
24
+ "@griffel/transform": "^2.0.0",
25
25
  "oxc-resolver": "^11.19.1",
26
26
  "stylis": "^4.2.0"
27
27
  },
@@ -1,2 +1,4 @@
1
- import { TransformResolverFactory } from './types.mjs';
1
+ import { TransformResolver } from '@griffel/transform';
2
+ import { Compilation } from 'webpack';
3
+ export type TransformResolverFactory = (compilation: Compilation) => TransformResolver;
2
4
  export declare function createResolverFactory(): TransformResolverFactory;
package/webpack-loader.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ASSET_TAG_OPEN, ASSET_TAG_CLOSE, EvalCache, Module, transformSync } from "@griffel/transform";
1
+ import { ASSET_TAG_OPEN, ASSET_TAG_CLOSE, EvalCache, transformSync } from "@griffel/transform";
2
2
  import * as path from "node:path";
3
3
  import { G as GriffelCssLoaderContextKey } from "./constants-aY3k4vvW.js";
4
4
  import { normalizeCSSBucketEntry } from "@griffel/core";
@@ -86,36 +86,34 @@ function webpackLoader(sourceCode, inputSourceMap) {
86
86
  throw new Error("GriffelCSSExtractionPlugin is not configured, please check your webpack config");
87
87
  }
88
88
  }
89
- const { classNameHashSalt, modules, evaluationRules, babelOptions } = this.getOptions();
89
+ const { classNameHashSalt, modules, evaluationRules } = this.getOptions();
90
90
  this[GriffelCssLoaderContextKey].runWithTimer(() => {
91
91
  EvalCache.clearForFile(this.resourcePath);
92
- const originalResolveFilename = Module._resolveFilename;
93
92
  let result = null;
94
93
  let error = null;
95
94
  try {
96
- Module._resolveFilename = (id, params) => {
97
- const resolvedPath = this[GriffelCssLoaderContextKey].resolveModule(id, params);
98
- this.addDependency(resolvedPath);
99
- return resolvedPath;
100
- };
101
95
  result = transformSync(sourceCode, {
102
96
  filename: this.resourcePath,
97
+ resolveModule: (id, params) => {
98
+ const resolved = this[GriffelCssLoaderContextKey].resolveModule(id, params);
99
+ this.addDependency(resolved.path);
100
+ return resolved;
101
+ },
103
102
  classNameHashSalt,
104
103
  modules,
105
104
  evaluationRules,
106
- babelOptions
105
+ collectPerfIssues: this[GriffelCssLoaderContextKey]?.collectPerfIssues
107
106
  });
108
107
  } catch (err) {
109
108
  error = err;
110
- } finally {
111
- Module._resolveFilename = originalResolveFilename;
112
109
  }
113
110
  if (result) {
114
- const { code, cssRulesByBucket, usedVMForEvaluation } = result;
111
+ const { code, cssRulesByBucket, usedVMForEvaluation, perfIssues } = result;
115
112
  const meta = {
116
113
  filename: this.resourcePath,
117
114
  step: "transform",
118
- evaluationMode: usedVMForEvaluation ? "vm" : "ast"
115
+ evaluationMode: usedVMForEvaluation ? "vm" : "ast",
116
+ perfIssues
119
117
  };
120
118
  if (cssRulesByBucket) {
121
119
  const resolvedCssRulesByBucket = resolveAssetPathsInCSSRules(cssRulesByBucket, this.resourcePath);
package/webpack-plugin.js CHANGED
@@ -7,22 +7,22 @@ function isCJSOnlyPackage(id) {
7
7
  return id === "tslib" || id.startsWith("@babel/runtime") || id.startsWith("@swc/helpers");
8
8
  }
9
9
  const RESOLVE_OPTIONS_DEFAULTS = {
10
- conditionNames: ["import", "require"],
10
+ conditionNames: ["require"],
11
11
  extensions: [".js", ".jsx", ".cjs", ".mjs", ".ts", ".tsx", ".json"]
12
12
  };
13
13
  function createResolverFactory() {
14
14
  return function(compilation) {
15
- const defaultResolver = new ResolverFactory({
15
+ const cjsResolver = new ResolverFactory({
16
16
  ...RESOLVE_OPTIONS_DEFAULTS
17
17
  // ...resolveOptionsFromWebpackConfig,
18
18
  });
19
- const cjsResolver = defaultResolver.cloneWithOptions({
20
- conditionNames: ["require"],
21
- extensions: RESOLVE_OPTIONS_DEFAULTS.extensions,
19
+ const esmResolver = cjsResolver.cloneWithOptions({
20
+ ...RESOLVE_OPTIONS_DEFAULTS,
21
+ conditionNames: ["import"],
22
22
  mainFields: ["module", "main"]
23
23
  });
24
24
  return function resolveModule(id, { filename }) {
25
- const resolver = isCJSOnlyPackage(id) ? cjsResolver : defaultResolver;
25
+ const resolver = isCJSOnlyPackage(id) ? cjsResolver : esmResolver;
26
26
  const resolved = resolver.sync(path.dirname(filename), id);
27
27
  if (resolved.error) {
28
28
  throw resolved.error;
@@ -30,7 +30,10 @@ function createResolverFactory() {
30
30
  if (!resolved.path) {
31
31
  throw new Error(`oxc-resolver: Failed to resolve module "${id}"`);
32
32
  }
33
- return resolved.path;
33
+ return {
34
+ path: resolved.path,
35
+ builtin: !!resolved.builtin
36
+ };
34
37
  };
35
38
  };
36
39
  }
@@ -152,12 +155,15 @@ function moveCSSModulesToGriffelChunk(compilation) {
152
155
  class GriffelPlugin {
153
156
  #attachToEntryPoint;
154
157
  #collectStats;
158
+ #collectPerfIssues;
155
159
  #compareMediaQueries;
156
160
  #resolverFactory;
157
161
  #stats = {};
162
+ #perfIssues = /* @__PURE__ */ new Map();
158
163
  constructor(options = {}) {
159
164
  this.#attachToEntryPoint = options.unstable_attachToEntryPoint;
160
165
  this.#collectStats = options.collectStats ?? false;
166
+ this.#collectPerfIssues = options.collectPerfIssues ?? false;
161
167
  this.#compareMediaQueries = options.compareMediaQueries ?? defaultCompareMediaQueries;
162
168
  this.#resolverFactory = options.resolverFactory ?? createResolverFactory();
163
169
  }
@@ -196,6 +202,7 @@ class GriffelPlugin {
196
202
  NormalModule.getCompilationHooks(compilation).loader.tap(PLUGIN_NAME, (loaderContext, module) => {
197
203
  const resourcePath = module.resource;
198
204
  loaderContext[GriffelCssLoaderContextKey] = {
205
+ collectPerfIssues: this.#collectPerfIssues,
199
206
  resolveModule,
200
207
  registerExtractedCss(css) {
201
208
  cssByModuleMap.set(resourcePath, css);
@@ -206,17 +213,34 @@ class GriffelPlugin {
206
213
  return css;
207
214
  },
208
215
  runWithTimer: (cb) => {
216
+ if (!this.#collectStats && !this.#collectPerfIssues) {
217
+ return cb().result;
218
+ }
219
+ const start = this.#collectStats ? process.hrtime.bigint() : 0n;
220
+ const { meta, result } = cb();
209
221
  if (this.#collectStats) {
210
- const start = process.hrtime.bigint();
211
- const { meta, result } = cb();
212
222
  const end = process.hrtime.bigint();
213
223
  this.#stats[meta.filename] = {
214
224
  time: end - start,
215
225
  evaluationMode: meta.evaluationMode
216
226
  };
217
- return result;
218
227
  }
219
- return cb().result;
228
+ if (this.#collectPerfIssues && meta.perfIssues) {
229
+ for (const issue of meta.perfIssues) {
230
+ const key = `${issue.type}:${issue.dependencyFilename}`;
231
+ const existing = this.#perfIssues.get(key);
232
+ if (existing) {
233
+ existing.sourceFilenames.add(meta.filename);
234
+ } else {
235
+ this.#perfIssues.set(key, {
236
+ type: issue.type,
237
+ dependencyFilename: issue.dependencyFilename,
238
+ sourceFilenames: /* @__PURE__ */ new Set([meta.filename])
239
+ });
240
+ }
241
+ }
242
+ }
243
+ return result;
220
244
  }
221
245
  };
222
246
  });
@@ -290,15 +314,17 @@ class GriffelPlugin {
290
314
  return time.toString() + "ns";
291
315
  };
292
316
  const entries = Object.entries(this.#stats).sort(([, a], [, b]) => Number(b.time - a.time));
317
+ const totalTime = entries.reduce((acc, cur) => acc + cur[1].time, 0n);
318
+ const fileCount = entries.length;
319
+ const avgTime = fileCount > 0 ? totalTime / BigInt(fileCount) : 0n;
293
320
  console.log("\nGriffel CSS extraction stats:");
294
321
  console.log("------------------------------------");
295
- console.log(
296
- "Total time spent in Griffel loader:",
297
- logTime(entries.reduce((acc, cur) => acc + cur[1].time, 0n))
298
- );
322
+ console.log("Total time spent in Griffel loader:", logTime(totalTime));
323
+ console.log("Files processed:", fileCount);
324
+ console.log("Average time per file:", logTime(avgTime));
299
325
  console.log(
300
326
  "AST evaluation hit: ",
301
- (entries.filter((s) => s[1].evaluationMode === "ast").length / entries.length * 100).toFixed(2) + "%"
327
+ (entries.filter((s) => s[1].evaluationMode === "ast").length / fileCount * 100).toFixed(2) + "%"
302
328
  );
303
329
  console.log("------------------------------------");
304
330
  for (const [filename, info] of entries) {
@@ -306,6 +332,22 @@ class GriffelPlugin {
306
332
  }
307
333
  console.log();
308
334
  }
335
+ if (this.#collectPerfIssues && this.#perfIssues.size > 0) {
336
+ const issues = Array.from(this.#perfIssues.values());
337
+ const cjsCount = issues.filter((i) => i.type === "cjs-module").length;
338
+ const barrelCount = issues.filter((i) => i.type === "barrel-export-star").length;
339
+ console.log("\nGriffel performance issues:");
340
+ console.log("------------------------------------");
341
+ console.log(`CJS modules (no tree-shaking): ${cjsCount}`);
342
+ console.log(`Barrel files with remaining export *: ${barrelCount}`);
343
+ console.log("------------------------------------");
344
+ for (const issue of issues) {
345
+ const tag = issue.type === "cjs-module" ? "cjs" : "barrel";
346
+ const sources = Array.from(issue.sourceFilenames).join(", ");
347
+ console.log(` [${tag}] ${issue.dependencyFilename} (source: ${sources})`);
348
+ }
349
+ console.log();
350
+ }
309
351
  }
310
352
  );
311
353
  });
@@ -1,7 +1,7 @@
1
1
  import { TransformOptions } from '@griffel/transform';
2
2
  import { SupplementedLoaderContext } from './constants.mjs';
3
3
  import type * as webpack from 'webpack';
4
- export type WebpackLoaderOptions = Omit<TransformOptions, 'filename' | 'generateMetadata'>;
4
+ export type WebpackLoaderOptions = Omit<TransformOptions, 'filename' | 'generateMetadata' | 'resolveModule'>;
5
5
  type WebpackLoaderParams = Parameters<webpack.LoaderDefinitionFunction<WebpackLoaderOptions>>;
6
6
  declare function webpackLoader(this: SupplementedLoaderContext<WebpackLoaderOptions>, sourceCode: WebpackLoaderParams[0], inputSourceMap: WebpackLoaderParams[1]): void;
7
7
  export default webpackLoader;
@@ -1,4 +0,0 @@
1
- import { Module } from '@griffel/transform';
2
- import { Compilation } from 'webpack';
3
- export type TransformResolver = (typeof Module)['_resolveFilename'];
4
- export type TransformResolverFactory = (compilation: Compilation) => TransformResolver;