Skip to content

url() assets broken when using !=! matchResource imports #1161

@Mad-Kat

Description

@Mad-Kat

Have you used AI?

Yes

Bug Description

The pitch function constructs the importModule request using this.resourcePath:

this.importModule(
  `${this.resourcePath}.webpack[javascript/auto]!=!!!${request}`,
  ...
);

When the module was imported via !=! matchResource syntax (e.g. Box.module.css!=!./Box), this.resourcePath is the actual resource (Box.tsx), not the matchResource (Box.module.css). The child module's matchResource becomes Box.tsx, so webpack identifies it as a .tsx file rather than a .css file.

This breaks issuer-based rules that check for CSS extensions, e.g.:

  { test: /\.png$/, issuer: /\.(css|scss|sass)$/, type: "asset/resource" }

Assets referenced via url() in the CSS get type: javascript/auto instead of asset/resource, producing url([object Object]).

See this reproduction: https://github.com/mad-kat/next-css-url-match-resource-repro which shows a next.js app with a !=! virtual CSS module and a real .module.css side by side

Suggested fix:

- this.importModule(`${this.resourcePath}.webpack[javascript/auto]!=!!!${request}`, ...)
+ this.importModule(`${this._module.matchResource || this.resourcePath}.webpack[javascript/auto]!=!!!${request}`, ...)

Caveat: I used claude to identify the issue we encountered with our setup, but I'm pretty sure this is the main culprit and this could unblock us to use "real" virtual CSS

Link to Minimal Reproduction and step to reproduce

https://github.com/mad-kat/next-css-url-match-resource-repro

  1. npm install
  2. npm run dev
  3. Open http://localhost:3000
  4. Inspect the generated CSS. The real .module.css has a resolved url(), the !=! matchResource module has url([object Object])

Expected Behavior

url() references in virtual CSS modules (via !=! matchResource) should resolve to asset URLs, the same as in real .css files.

Actual Behavior

url() produces url([object Object]) because the asset's issuer is identified as .tsx instead of .css, so the issuer-based asset/resource rule doesn't match.

Environment

System:
  OS: macOS 26.3.1
  CPU: (14) arm64 Apple M4 Pro
  Memory: 6.68 GB / 48.00 GB
Binaries:
  Node: 24.13.1
  npm: 11.8.0
Packages:
  webpack-cli: 7.0.2
  mini-css-extract-plugin: (bundled with next@16.2.1)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions