Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

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

Ouverte
#420 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@brenelz y travaille déjà.

Depuis le 16/10/2026.

  • #423 par @brenelz — ouverte

Évaluation

Difficulté
3/5
Temps estimé
Une demi-journée
Accessibilité débutants
55/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
typescript

Piste de recherche

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.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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)

Langage dominant
TypeScript
Étoiles
522
Forks
73
Merge moyen
1 j 5 h
PR mergées (30 j)
34

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de solidjs/solid-vite-plugin

Toutes les issues de solidjs/solid-vite-plugin

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.