support CSS Modules @value identifiers as @import URLs and inside url()#20925
Conversation
… `url()`
Allow CSS Modules `@value` definitions to be used as the path argument
to `@import` and inside `url()` references. For example:
@value path: "./other.module.css";
@import path;
@value bg: "./image.png";
.a { background: url(bg); }
Both the quoted (`"./x"`, `'./x'`) and bare (`./x`) forms of the value
are accepted; whichever the user wrote is unwrapped and resolved as a
module request, so the asset goes through the normal webpack resolver
and asset pipeline instead of being left as a literal `bg`/`path`
identifier.
Add a `values.module.css` that defines values consumed via `@value … from` in `style.module.css` and `imported-via-value.module.css`, exercising three scenarios: 1. Imported `@value` used as a regular declaration value (`color: externalColor;`) — already worked, now asserted against the bundle output. 2. Imported `@value` used as the URL of `@import` — emits a clear warning explaining that only locally defined values are supported in this position. The whole at-rule is dropped from the output so the unresolved identifier doesn't leak into a malformed CSS `@import`. 3. Imported `@value` used inside `url()` — emits an analogous warning and leaves the original `url(identifier)` text in place. Update the warning messages in `CssParser` to distinguish "unknown identifier" from "imported from another module — not supported here", and add a `warnings.js` listing the two expected warnings for the imported-value scenarios.
🦋 Changeset detectedLatest commit: 88fe1c9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
This PR is packaged and the instant preview is available (10c4fcf). Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@10c4fcf
yarn add -D webpack@https://pkg.pr.new/webpack@10c4fcf
pnpm add -D webpack@https://pkg.pr.new/webpack@10c4fcf |
Codecov Report❌ Patch coverage is
❌ Your changes status has failed because you have indirect coverage changes. Learn more about Unexpected Coverage Changes and reasons for indirect coverage changes. Additional details and impacted files@@ Coverage Diff @@
## main #20925 +/- ##
==========================================
- Coverage 91.37% 91.35% -0.03%
==========================================
Files 566 566
Lines 56093 56130 +37
Branches 14886 14904 +18
==========================================
+ Hits 51254 51276 +22
- Misses 4839 4854 +15
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR extends webpack’s CSS Modules parsing so locally-defined @value identifiers can be used as module requests in @import and inside url(), allowing those references to be resolved via webpack’s normal resolver/asset pipeline.
Changes:
- Teach the CSS tokenizer/parser to recognize
@import <identifier>;and resolve it via CSS Modules@value(local-only), emitting warnings for unsupported imported@values. - Add CSS Modules
url()handling to resolveurl(<identifier>)via local@valuedefinitions (with warnings for imported@values). - Add a new
configCasestest suite (including a fixture image) plus a changeset documenting the new feature.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/css/walkCssTokens.js | Extends @import tokenization to record when the URL was provided as an identifier. |
| lib/css/CssParser.js | Resolves @import and url() identifier forms via local CSS Modules @value definitions and emits warnings for unsupported cases. |
| test/configCases/css/css-modules-value-url-import/webpack.config.js | Adds a config case enabling CSS experiments and CSS Modules for the new scenario. |
| test/configCases/css/css-modules-value-url-import/style.module.css | Exercises local @value usage in @import and url() (quoted and bare forms). |
| test/configCases/css/css-modules-value-url-import/values.module.css | Provides exported @value definitions used by the warning scenario. |
| test/configCases/css/css-modules-value-url-import/imported.module.css | Simple imported stylesheet content used to assert @import worked. |
| test/configCases/css/css-modules-value-url-import/imported-via-value.module.css | Exercises warning paths for imported @value used in @import and url(). |
| test/configCases/css/css-modules-value-url-import/index.js | Asserts behavior for resolved @import/url() and warning-only cases. |
| test/configCases/css/css-modules-value-url-import/warnings.js | Asserts the expected warnings are emitted for unsupported imported @value positions. |
| test/configCases/css/css-modules-value-url-import/img/shape.png | Fixture asset referenced by @value-backed url() cases. |
| .changeset/css-modules-value-url-import.md | Declares a minor release note for the new CSS Modules capability. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (!def.value) { | ||
| this._emitWarning( | ||
| state, | ||
| `'@value' identifier '${name}' was imported from another module and cannot be used as the URL of '@import' — only locally defined values are supported here`, | ||
| locConverter, | ||
| start, | ||
| semi | ||
| ); | ||
| const dep = new ConstDependency("", [start, semi]); | ||
| module.addPresentationalDependency(dep); | ||
| return semi; | ||
| } |
| const matches = [ | ||
| ...cssContent.matchAll(/background-image:\s*url\(([^)]+)\)/g) | ||
| ]; |
- `processAtImport`: distinguish "imported @value" from "locally defined with empty string value" by checking `def.value === undefined` explicitly instead of `!def.value`. A local `@value p: ;` now falls through to the empty-URL handling (which drops the at-rule) instead of being misreported as an imported value. - Replace `String.prototype.matchAll` in the new test with a `RegExp#exec` loop — webpack still supports Node 10.13+ and `matchAll` was added in Node 12.
Types CoverageCoverage after merging claude/add-value-support-url-import-FR6AV into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
…107) (#8244) Webpack 5.107 brings two additions to the experiments.css feature set: - Scope hoisting (module concatenation) now applies to CSS Modules with exportType "text", "css-style-sheet", "style", or "link", reducing runtime overhead in CSS-heavy bundles when optimization.concatenateModules is enabled. - @value identifiers can be used as the path argument to @import and inside url() references, so shared paths/assets are defined once and reused. Both quoted and bare forms are accepted and resolved through webpack's normal asset pipeline. Adds two bullets to the existing experimental features list in experiments.css. Refs: - webpack/webpack#20851 (scope hoisting) - webpack/webpack#20925 (@value in URLs)
Allow CSS Modules
@valuedefinitions to be used as the path argumentto
@importand insideurl()references. For example:Both the quoted (
"./x",'./x') and bare (./x) forms of the valueare accepted; whichever the user wrote is unwrapped and resolved as a
module request, so the asset goes through the normal webpack resolver
and asset pipeline instead of being left as a literal
bg/pathidentifier.