Skip to content
This repository was archived by the owner on Mar 19, 2026. It is now read-only.
This repository was archived by the owner on Mar 19, 2026. It is now read-only.

CJS plugin hooks (resolveId, load, transform) not applied to new Worker() sub-bundles #610

@t-muko

Description

@t-muko

Describe the bug

Bug: Plugin hooks (resolveId, load, transform) not applied to new Worker() sub-bundles

Description

When a project uses
new Worker(new URL('./worker.js', import.meta.url), { type: 'module' }), Vite
8/Rolldown builds the worker as a separate sub-bundle. Plugin hooks
(resolveId, load, transform) registered in vite.config.js are silently
skipped for that sub-bundle. Hooks fire correctly in the main bundle but not in
worker bundles.

This surfaces as an unrecoverable CJS↔ESM interop regression:

Rolldown now resolves JSON files as ESM (export default [...]). When legacy
CJS code calls require('some-package') and that package does
module.exports = require('./data.json'), Rolldown's interop helper returns a
namespace object { __esModule: true, default: [...] } instead of the raw
array. This is a behavioral regression from Vite 7 / Rollup. The only
userland fix is a plugin hook — which doesn't reach the worker.


Workaround

resolve.alias is applied at the Rolldown config level and does reach worker
sub-bundles. Generate a .cjs shim at config-load time and alias the package to
it:

// vite.config.js
import path from "path";
import fs from "node:fs";

const shimDir = path.resolve(process.cwd(), "src/shims");
const osmShim = path.join(shimDir, "osm-polygon-features.cjs");
fs.mkdirSync(shimDir, { recursive: true });
fs.writeFileSync(
    osmShim,
    "module.exports = " +
        fs.readFileSync(
            path.resolve(
                process.cwd(),
                "node_modules/osm-polygon-features/polygon-features.json",
            ),
            "utf-8",
        ) + ";\n",
);

export default defineConfig({
    resolve: {
        alias: {
            "osm-polygon-features": osmShim,
        },
    },
});

With this alias in place the worker bundle contains:

// In worker bundle — fixed
Bo = Ae(((e, t) => {
  t.exports = [{ key: "building", polygon: "all" }, ...]  // raw array, forEach works
}))

Additional context

  • osm-polygon-features is also consumed by overpass-frontend,
    osm-polygon-features-extended, and any other library wrapping
    osmtogeojson, so this affects a broad set of OSM tooling.
  • The two issues (plugin hooks skipped for workers; JSON→namespace regression)
    may have the same underlying cause in Rolldown's worker build pipeline, or may
    be separate. Fixing either one would unblock userland.

Reproduction

https://stackblitz.com/edit/vitejs-rolldown-vite-ipktsxdp?file=package.json

Steps to reproduce

Reproduction

Packages involved:

  • osmtogeojson@3.0.0-beta.5 (CJS) — used inside a new Worker()
  • osm-polygon-features@0.9.2 (CJS, JSON re-export) — dependency of
    osmtogeojson

osmtogeojson/index.js:

require("osm-polygon-features").forEach(function(tags) { ... });

osm-polygon-features/index.js:

module.exports = require("./polygon-features.json");

Steps:

  1. Import osmtogeojson inside a Worker module:

    // myWorker.js
    import osmtogeojson from "osmtogeojson";
    // ...
    // main app
    new Worker(new URL("./myWorker.js", import.meta.url), { type: "module" });
  2. Register a plugin in vite.config.js to intercept osm-polygon-features and
    return it as a proper CJS module:

    {
      name: 'fix-osm-polygon-features',
      enforce: 'pre',
      resolveId(id) {
        if (id === 'osm-polygon-features') return '\0virtual:osm-polygon-features';
      },
      load(id) {
        if (id === '\0virtual:osm-polygon-features') {
          const data = fs.readFileSync('node_modules/osm-polygon-features/polygon-features.json', 'utf-8');
          return `module.exports = ${data};`;
        }
      }
    }
  3. Run vite build.

Result: The plugin hook fires for the main bundle. It does not fire for
the worker sub-bundle. The worker crashes at runtime:

Uncaught TypeError: jo(...).forEach is not a function
    at osmParserWorker-XXX.js:3369

Inspecting the built worker bundle confirms the interop wrapper still wraps the
JSON as a namespace object:

// In worker bundle — broken
jo = Te((e, t) => {
    t.exports = (Jo(), rs(Ho)); // rs() returns { __esModule: true, default: [...] }
});

Expected behaviour

  1. Plugin hooks (resolveId, load, transform) should be invoked for all
    modules resolved in worker sub-bundles, consistent with Vite 7/Rollup
    behaviour.

  2. (Separate but related) require() of a CJS module whose only export is a
    JSON file should return the parsed value directly, not a namespace object.
    This was the Rollup/Vite 7 behaviour and is what downstream CJS consumers
    expect.


System Info

**Vite version:** `8.0.0-beta.18`\
**Rolldown version:** `1.0.0-rc.8`\
**OS:** Windows 11\
**Node:** `v22.22.1`


Error:
// In worker bundle — broken
jo = Te(((e, t) => {
  t.exports = (Jo(), rs(Ho));  // rs() returns { __esModule: true, default: [...] }
}))

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions