Skip to content

Direct loader importModule() calls return empty exports for native CSS modules #22046

Closed

Description

@intellild

Have you used AI?

Yes

Which part of webpack is affected?

loaders

Bug Description

When a loader calls this.importModule("./style.module.css") directly, native CSS-module exports are lost if there is no other JavaScript importer. The call returns {} instead of the class-name mapping.

This reproduces with both css/module and css/auto, with generator.exportsOnly either enabled or disabled.

Link to Minimal Reproduction and steps to reproduce

https://stackblitz.com/edit/vitejs-vite-rcullrws?file=src%2Floader.js

Expected Behavior

The loader receives the CSS-module exports:

{ button: "button", title: "title" }

Actual Behavior

The loader receives {}.

Environment

⬡ webpack info
────────────────────────────────────────────────────────────────────────
System and environment information.


⬡ System:
────────────────────────────────────────────────────────────────────────
  OS:      Linux 5.0 undefined
  CPU:     (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
  Memory:  0 Bytes / 0 Bytes

⬡ Binaries:
────────────────────────────────────────────────────────────────────────
  Node:  22.22.3 - /usr/local/bin/node
  Yarn:  1.22.19 - /usr/local/bin/yarn
  npm:   10.8.2 - /usr/local/bin/npm
  pnpm:  8.15.6 - /usr/local/bin/pnpm

⬡ Packages:
────────────────────────────────────────────────────────────────────────
  webpack:      ^5.110.3 → 5.110.3
  webpack-cli:  ^7.2.3 → 7.2.3
────────────────────────────────────────────────────────────────────────

Is this a regression?

None

Last Working Version

No response

Additional Context

LoaderPlugin creates a LoaderImportDependency with connectOrigin: false. CssGenerator.getTypes() skips incoming connections without an originating module, so it does not recognize this import as requiring JavaScript output.

With exportsOnly: true, the module ends up with no source types. Otherwise, it has only CSS output. Module execution therefore has no JavaScript source to evaluate and returns empty exports.

Two possible fixes:

  1. Always preserve JavaScript output for CSS modules.

    Initialize hasJs from module.buildMeta.isCssModule. This preserves exports for direct loader imports, but also generates JavaScript factories for CSS modules referenced only by other CSS modules.

    In a local verification, this increased the development-mode css-modules fixture's registered JavaScript module count from 6 to 12, including modules referenced through @import, composes, and @value.

  2. Handle LoaderImportDependency explicitly.

    Recognize a loader import as requiring JavaScript output before skipping connections without an originating module. This would preserve exports during importModule() execution while retaining the existing optimization for CSS-only dependencies.

Regression coverage should test a direct CSS-module import without a JavaScript wrapper, both module types, both exportsOnly settings, and persistent caching.

Activity

  1. added theissue type on Sep 11, 2026
  2. added
    area: cssCSS support (lib/css)
    area: loadersLoader execution and loader API (lib/loaders)
    area: cachePersistent and memory caching, serialization (lib/cache, lib/serialization)
    on Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: cachePersistent and memory caching, serialization (lib/cache, lib/serialization)area: cssCSS support (lib/css)area: loadersLoader execution and loader API (lib/loaders)

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions