@griffel/webpack-plugin 1.1.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,36 @@
1
1
  # Change Log - @griffel/webpack-plugin
2
2
 
3
- This log was last generated on Fri, 06 Mar 2026 08:15:28 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
+
21
+ ## 2.0.0
22
+
23
+ Fri, 06 Mar 2026 15:56:28 GMT
24
+
25
+ ### Major changes
26
+
27
+ - BREAKING: consolidate resolvers into ESM-first createResolverFactory, remove enhanced-resolve dependency (olfedias@microsoft.com)
28
+ - Bump @griffel/transform to v1.2.1
29
+ - Bump @griffel/core to v1.20.1
30
+
7
31
  ## 1.1.0
8
32
 
9
- Fri, 06 Mar 2026 08:15:28 GMT
33
+ Fri, 06 Mar 2026 08:17:05 GMT
10
34
 
11
35
  ### Minor changes
12
36
 
@@ -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/index.d.mts CHANGED
@@ -1,4 +1,2 @@
1
1
  export { GriffelPlugin, type GriffelCSSExtractionPluginOptions } from './GriffelPlugin.mjs';
2
- export { createEnhancedResolverFactory } from './resolver/createEnhancedResolverFactory.mjs';
3
- export { createOxcResolverFactory } from './resolver/createOxcResolverFactory.mjs';
4
- export { createFluentOxcResolverFactory, type FluentOxcResolverOptions, } from './resolver/createFluentOxcResolverFactory.mjs';
2
+ export { createResolverFactory } from './resolver/createResolverFactory.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@griffel/webpack-plugin",
3
- "version": "1.1.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,9 +20,8 @@
20
20
  "./package.json": "./package.json"
21
21
  },
22
22
  "dependencies": {
23
- "@griffel/transform": "^1.2.0",
24
- "@griffel/core": "^1.20.0",
25
- "enhanced-resolve": "^5.15.0",
23
+ "@griffel/core": "^1.20.1",
24
+ "@griffel/transform": "^2.0.0",
26
25
  "oxc-resolver": "^11.19.1",
27
26
  "stylis": "^4.2.0"
28
27
  },
@@ -0,0 +1,4 @@
1
+ import { TransformResolver } from '@griffel/transform';
2
+ import { Compilation } from 'webpack';
3
+ export type TransformResolverFactory = (compilation: Compilation) => TransformResolver;
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
@@ -1,33 +1,39 @@
1
1
  import { styleBucketOrdering, normalizeCSSBucketEntry, defaultCompareMediaQueries } from "@griffel/core";
2
2
  import { P as PLUGIN_NAME, G as GriffelCssLoaderContextKey } from "./constants-aY3k4vvW.js";
3
- import enhancedResolve from "enhanced-resolve";
3
+ import { ResolverFactory } from "oxc-resolver";
4
4
  import * as path from "node:path";
5
5
  import { compile, COMMENT, serialize, stringify } from "stylis";
6
- import { ResolverFactory } from "oxc-resolver";
7
- const RESOLVE_OPTIONS_DEFAULTS$2 = {
6
+ function isCJSOnlyPackage(id) {
7
+ return id === "tslib" || id.startsWith("@babel/runtime") || id.startsWith("@swc/helpers");
8
+ }
9
+ const RESOLVE_OPTIONS_DEFAULTS = {
8
10
  conditionNames: ["require"],
9
11
  extensions: [".js", ".jsx", ".cjs", ".mjs", ".ts", ".tsx", ".json"]
10
12
  };
11
- function createEnhancedResolverFactory(resolveOptions = {}) {
12
- const { inheritResolveOptions = ["alias", "modules", "plugins"], webpackResolveOptions } = resolveOptions;
13
+ function createResolverFactory() {
13
14
  return function(compilation) {
14
- const resolveOptionsFromWebpackConfig = compilation?.options.resolve ?? {};
15
- const resolveSync = enhancedResolve.create.sync({
16
- ...RESOLVE_OPTIONS_DEFAULTS$2,
17
- ...Object.fromEntries(
18
- inheritResolveOptions.map((resolveOptionKey) => [
19
- resolveOptionKey,
20
- resolveOptionsFromWebpackConfig[resolveOptionKey]
21
- ])
22
- ),
23
- ...webpackResolveOptions
15
+ const cjsResolver = new ResolverFactory({
16
+ ...RESOLVE_OPTIONS_DEFAULTS
17
+ // ...resolveOptionsFromWebpackConfig,
18
+ });
19
+ const esmResolver = cjsResolver.cloneWithOptions({
20
+ ...RESOLVE_OPTIONS_DEFAULTS,
21
+ conditionNames: ["import"],
22
+ mainFields: ["module", "main"]
24
23
  });
25
24
  return function resolveModule(id, { filename }) {
26
- const resolvedPath = resolveSync(path.dirname(filename), id);
27
- if (!resolvedPath) {
28
- throw new Error(`enhanced-resolve: Failed to resolve module "${id}"`);
25
+ const resolver = isCJSOnlyPackage(id) ? cjsResolver : esmResolver;
26
+ const resolved = resolver.sync(path.dirname(filename), id);
27
+ if (resolved.error) {
28
+ throw resolved.error;
29
29
  }
30
- return resolvedPath;
30
+ if (!resolved.path) {
31
+ throw new Error(`oxc-resolver: Failed to resolve module "${id}"`);
32
+ }
33
+ return {
34
+ path: resolved.path,
35
+ builtin: !!resolved.builtin
36
+ };
31
37
  };
32
38
  };
33
39
  }
@@ -149,14 +155,17 @@ function moveCSSModulesToGriffelChunk(compilation) {
149
155
  class GriffelPlugin {
150
156
  #attachToEntryPoint;
151
157
  #collectStats;
158
+ #collectPerfIssues;
152
159
  #compareMediaQueries;
153
160
  #resolverFactory;
154
161
  #stats = {};
162
+ #perfIssues = /* @__PURE__ */ new Map();
155
163
  constructor(options = {}) {
156
164
  this.#attachToEntryPoint = options.unstable_attachToEntryPoint;
157
165
  this.#collectStats = options.collectStats ?? false;
166
+ this.#collectPerfIssues = options.collectPerfIssues ?? false;
158
167
  this.#compareMediaQueries = options.compareMediaQueries ?? defaultCompareMediaQueries;
159
- this.#resolverFactory = options.resolverFactory ?? createEnhancedResolverFactory();
168
+ this.#resolverFactory = options.resolverFactory ?? createResolverFactory();
160
169
  }
161
170
  apply(compiler) {
162
171
  const IS_RSPACK = Object.prototype.hasOwnProperty.call(compiler.webpack, "rspackVersion");
@@ -193,6 +202,7 @@ class GriffelPlugin {
193
202
  NormalModule.getCompilationHooks(compilation).loader.tap(PLUGIN_NAME, (loaderContext, module) => {
194
203
  const resourcePath = module.resource;
195
204
  loaderContext[GriffelCssLoaderContextKey] = {
205
+ collectPerfIssues: this.#collectPerfIssues,
196
206
  resolveModule,
197
207
  registerExtractedCss(css) {
198
208
  cssByModuleMap.set(resourcePath, css);
@@ -203,17 +213,34 @@ class GriffelPlugin {
203
213
  return css;
204
214
  },
205
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();
206
221
  if (this.#collectStats) {
207
- const start = process.hrtime.bigint();
208
- const { meta, result } = cb();
209
222
  const end = process.hrtime.bigint();
210
223
  this.#stats[meta.filename] = {
211
224
  time: end - start,
212
225
  evaluationMode: meta.evaluationMode
213
226
  };
214
- return result;
215
227
  }
216
- 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;
217
244
  }
218
245
  };
219
246
  });
@@ -287,15 +314,17 @@ class GriffelPlugin {
287
314
  return time.toString() + "ns";
288
315
  };
289
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;
290
320
  console.log("\nGriffel CSS extraction stats:");
291
321
  console.log("------------------------------------");
292
- console.log(
293
- "Total time spent in Griffel loader:",
294
- logTime(entries.reduce((acc, cur) => acc + cur[1].time, 0n))
295
- );
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));
296
325
  console.log(
297
326
  "AST evaluation hit: ",
298
- (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) + "%"
299
328
  );
300
329
  console.log("------------------------------------");
301
330
  for (const [filename, info] of entries) {
@@ -303,66 +332,28 @@ class GriffelPlugin {
303
332
  }
304
333
  console.log();
305
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
+ }
306
351
  }
307
352
  );
308
353
  });
309
354
  }
310
355
  }
311
- const RESOLVE_OPTIONS_DEFAULTS$1 = {
312
- conditionNames: ["require"],
313
- extensions: [".js", ".jsx", ".cjs", ".mjs", ".ts", ".tsx", ".json"]
314
- };
315
- function createOxcResolverFactory() {
316
- return function(compilation) {
317
- const resolverFactory = new ResolverFactory({
318
- ...RESOLVE_OPTIONS_DEFAULTS$1
319
- // ...resolveOptionsFromWebpackConfig,
320
- });
321
- return function resolveModule(id, { filename }) {
322
- const resolvedResolver = resolverFactory.sync(path.dirname(filename), id);
323
- if (resolvedResolver.error) {
324
- throw resolvedResolver.error;
325
- }
326
- if (!resolvedResolver.path) {
327
- throw new Error(`oxc-resolver: Failed to resolve module "${id}"`);
328
- }
329
- return resolvedResolver.path;
330
- };
331
- };
332
- }
333
- function defaultIsFluentPackage(id) {
334
- return id.startsWith("@fluentui/");
335
- }
336
- const RESOLVE_OPTIONS_DEFAULTS = {
337
- conditionNames: ["require"],
338
- extensions: [".raw.js", ".js", ".jsx", ".cjs", ".mjs", ".ts", ".tsx", ".json"]
339
- };
340
- function createFluentOxcResolverFactory(resolveOptions) {
341
- const { isFluentPackage = defaultIsFluentPackage, ...restOptions } = resolveOptions ?? {};
342
- return function(compilation) {
343
- const defaultResolver = new ResolverFactory({
344
- ...RESOLVE_OPTIONS_DEFAULTS,
345
- ...restOptions
346
- });
347
- const esmResolver = defaultResolver.cloneWithOptions({
348
- conditionNames: ["import", "require"]
349
- });
350
- return function resolveModule(id, { filename }) {
351
- const resolver = isFluentPackage(id) ? esmResolver : defaultResolver;
352
- const resolved = resolver.sync(path.dirname(filename), id);
353
- if (resolved.error) {
354
- throw resolved.error;
355
- }
356
- if (!resolved.path) {
357
- throw new Error(`oxc-resolver: Failed to resolve module "${id}"`);
358
- }
359
- return resolved.path;
360
- };
361
- };
362
- }
363
356
  export {
364
357
  GriffelPlugin,
365
- createEnhancedResolverFactory,
366
- createFluentOxcResolverFactory,
367
- createOxcResolverFactory
358
+ createResolverFactory
368
359
  };
@@ -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,6 +0,0 @@
1
- import { Configuration } from 'webpack';
2
- import { TransformResolverFactory } from './types.mjs';
3
- export declare function createEnhancedResolverFactory(resolveOptions?: {
4
- inheritResolveOptions?: ('alias' | 'modules' | 'plugins' | 'conditionNames' | 'extensions')[];
5
- webpackResolveOptions?: Pick<Required<Configuration>['resolve'], 'alias' | 'modules' | 'plugins' | 'conditionNames' | 'extensions'>;
6
- }): TransformResolverFactory;
@@ -1,7 +0,0 @@
1
- import { NapiResolveOptions } from 'oxc-resolver';
2
- import { TransformResolverFactory } from './types.mjs';
3
- export type FluentOxcResolverOptions = Pick<NapiResolveOptions, 'conditionNames' | 'extensions' | 'alias' | 'mainFields' | 'modules'> & {
4
- /** Predicate to determine if a module specifier should be resolved with ESM conditions. Defaults to matching `@fluentui/` prefixed packages. */
5
- isFluentPackage?: (id: string) => boolean;
6
- };
7
- export declare function createFluentOxcResolverFactory(resolveOptions?: FluentOxcResolverOptions): TransformResolverFactory;
@@ -1,2 +0,0 @@
1
- import { TransformResolverFactory } from './types.mjs';
2
- export declare function createOxcResolverFactory(): TransformResolverFactory;
@@ -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;