Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[3.0.0-next.50 / next] SSR build: the $$moduleUrl export added to a Worker main module stops workerd from starting

Aperta
#420 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@brenelz ci sta già lavorando.

Dal 16/10/2026.

  • #423 di @brenelz — aperta

Valutazione

Difficoltà
3/5
Tempo stimato
Mezza giornata
Idoneità per principianti
55/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
typescript

Direzione di ricerca

The export is appended by injectSsrModuleId in src/index.ts, which currently adds it to every SSR module outside node_modules. Start there and check the condition that decides which modules get $$moduleUrl, then run vite build and inspect the last line of dist/server/server.js for the example worker. Done means a server entry keeps only its original exports while lazy()-reached modules still receive the export, and the worker still starts under vite preview.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

In SSR builds, the plugin appends export const $$moduleUrl = "<path>" to project modules. Since #407 (3.0.0-next.49) it does so for plain .ts/.js modules too; .tsx modules already had it. When the module that gets it is a server entry, the export becomes part of the entry's public surface.

With @cloudflare/vite-plugin, which the README names as a host the plugin composes with, the Worker's main module is re-exported as a whole by the Worker entry (export * from "<main>"). workerd accepts only handlers and entrypoint classes as named exports of a Worker. So the production Worker can't start:

Uncaught TypeError: Incorrect type for map entry '$$moduleUrl': the provided value is not of type 'function or ExportedHandler'.

vite dev is not affected. Expected: a server entry keeps only the exports it was written with.

Reproduction

Versions:

  • @solidjs/vite-plugin 3.0.0-next.48 / 49 / 50, with start: true, ssr: true;
  • @cloudflare/vite-plugin 1.64.0 and wrangler 4.151.0;
  • Vite 8.3.4;
  • solid-js / @solidjs/web 2.0.0-rc.15;
  • Node 24.21.0, Linux.
// vite.config.ts
import { cloudflare } from "@cloudflare/vite-plugin";
import solid from "@solidjs/vite-plugin";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [cloudflare({ viteEnvironment: { name: "ssr" } }), solid({ start: true, ssr: true })],
  server: { host: "127.0.0.1", port: 5391, strictPort: true },
});
// wrangler.jsonc
{
  "name": "module-url-probe",
  "main": "src/worker.ts",
  "compatibility_date": "2026-09-19",
  "compatibility_flags": ["nodejs_compat"]
}
// src/worker.ts
export { default } from "virtual:solid-ssr-handler";
// src/App.tsx
export default function App() {
  return <p>Hello</p>;
}

Run vite build, then vite preview --port 5391, then curl http://127.0.0.1:5391/. The second column is the last line of dist/server/server.js.

@solidjs/vite-plugin main dist/server/server.js exports vite preview
3.0.0-next.48 src/worker.ts export { worker_entry_default as default } starts, HTTP 200
3.0.0-next.48 src/worker.tsx (same content) export { $$moduleUrl, worker_entry_default as default } workerd fails to start (error above)
3.0.0-next.49 src/worker.ts export { $$moduleUrl, worker_entry_default as default } workerd fails to start
3.0.0-next.49 src/worker.tsx same workerd fails to start
3.0.0-next.50 src/worker.ts same workerd fails to start
3.0.0-next.50 src/worker.tsx same workerd fails to start

With 3.0.0-next.50, vite dev renders the page (<p _hk=10>Hello</p>).

Cause

injectSsrModuleId in src/index.ts; the code is unchanged on next. It appends the export to every SSR module outside node_modules:

function injectSsrModuleId(code, id, isSsr) {
  if (!isSsr || /node_modules/.test(id) || code.includes('$$moduleUrl')) return code;
  // ...
  return code + `\nexport const $$moduleUrl = ${JSON.stringify(relativeId)};\n`;
}

#407 also runs it on non-JSX modules, which is why a .ts Worker main breaks from next.49 on.

@cloudflare/vite-plugin's Worker entry module (virtual:cloudflare/worker-entry) re-exports the user's main:

import * as mod from "virtual:cloudflare/user-entry";
export * from "virtual:cloudflare/user-entry";
export default mod.default ?? {};

That way, Durable Object classes and other entrypoints written in main reach the Worker. In the build output, the added $$moduleUrl comes along as a named export of the Worker. workerd rejects it, because it is neither a handler nor an entrypoint class.

The only reader of $$moduleUrl is server-side lazy(). It reads it off a module that it resolved through import(), when its callsite has no static module URL (cur.mod?.$$moduleUrl in solid-js's server build). A Worker's main module is never such a target. So the export there serves no purpose, and it changes the entry's public surface.

Expected

A server entry module, and anything a host re-exports from it, keeps only the exports it was written with. $$moduleUrl is only needed on modules that lazy() reaches through import(). Related: #406 / #407 (where .ts/.js modules started getting the export).

(submitted by Claude Opus 5.5 on behalf of rvlzzr)

Lingua principale
TypeScript
Stelle
522
Fork
73
Merge medio
1g 4h
PR unite (30g)
35

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di solidjs/solid-vite-plugin

Tutte le issue di solidjs/solid-vite-plugin

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.