Summary
On next, transform() in src/index.ts returns early for any file that is not .jsx / .tsx / .tsrx (or a custom extensions entry):
if (!(/\.[mc]?[tj]sx$/i.test(id) || isTsrx || allExtensions.includes(currentFileExtension))) {
// Not a JSX module. The one pass that still applies is primitive
// naming — `createSignal` lives in `.ts`/`.js` as much as in
// components — and it runs alone: no lazy/refresh/JSX work.
if (namePrimitives && PRIMITIVES_ONLY_MODULE.test(id) && !DECLARATION_MODULE.test(id)) {
// transformSourceNames, then return
}
return null;
}
PRIMITIVES_ONLY_MODULE is /\.[mc]?[jt]s$/i (.ts / .js and the m/c variants, not .d.ts). On that path the only pass is transformSourceNames. The hook then returns null. It never runs transformLazy, resolveLazyModuleUrls, solid-refresh, or the SSR injectSsrModuleId that appends export const $$moduleUrl.
The same module written as .tsx goes through all of those after primitive naming.
routes.ts
A routes.ts full of lazy(() => import(...)) therefore gets no module URL, and the lazy targets never get $$moduleUrl. SSR cannot resolve assets or preload those modules from the route table.
This is the plugin half of solidjs/solid#3908. lazyModule landed in solid (solidjs/solid#3941). The plugin still does not annotate non-JSX files, so a route module that is plain .ts still cannot participate. #3908 is the solid-side feature; this issue is the gate in the plugin.
@solidjs/compiler's transformLazy already accepts .ts / .js when it is given a filename. The parser dialect comes from the path, and the pass is a no-op only when filename is omitted. The options tests pass filename: "src/a.js". The gate is the plugin, not the compiler.
Distinct from #390 (a leading slash on a hand-written moduleUrl never resolves) and #299 (query strings dropped from the SSR lazy lookup). Those assume the annotation was emitted.
"use server" should be on this path
transformDirectives also lives in @solidjs/compiler and accepts plain .ts / .js. This transform() never calls it. Vite runs it from a second plugin, serverFunctions() in src/server-functions/index.ts, whose default include is already src/**/*.{jsx,tsx,tsrx,ts,js,mjs,cjs}. So "use server" is the only one of these passes that escaped the JSX gate, and it did so by living in a different plugin. That split is weird.
A non-JSX module should get primitive names, the lazy / $$moduleUrl pipeline, refresh, and "use server" from the same plugin. Do not leave "use server" as the only pass that runs on .ts / .js because a second plugin happens to include those extensions.
Expected
One non-JSX pipeline, in this plugin:
- primitive names (
transformSourceNames)
- lazy /
$$moduleUrl (transformLazy, resolveLazyModuleUrls, SSR injectSsrModuleId)
- refresh
"use server" (transformDirectives)
Summary
On
next,transform()insrc/index.tsreturns early for any file that is not.jsx/.tsx/.tsrx(or a customextensionsentry):PRIMITIVES_ONLY_MODULEis/\.[mc]?[jt]s$/i(.ts/.jsand them/cvariants, not.d.ts). On that path the only pass istransformSourceNames. The hook then returnsnull. It never runstransformLazy,resolveLazyModuleUrls, solid-refresh, or the SSRinjectSsrModuleIdthat appendsexport const $$moduleUrl.The same module written as
.tsxgoes through all of those after primitive naming.routes.tsA
routes.tsfull oflazy(() => import(...))therefore gets no module URL, and the lazy targets never get$$moduleUrl. SSR cannot resolve assets or preload those modules from the route table.This is the plugin half of solidjs/solid#3908.
lazyModulelanded in solid (solidjs/solid#3941). The plugin still does not annotate non-JSX files, so a route module that is plain.tsstill cannot participate. #3908 is the solid-side feature; this issue is the gate in the plugin.@solidjs/compiler'stransformLazyalready accepts.ts/.jswhen it is given a filename. The parser dialect comes from the path, and the pass is a no-op only whenfilenameis omitted. The options tests passfilename: "src/a.js". The gate is the plugin, not the compiler.Distinct from #390 (a leading slash on a hand-written
moduleUrlnever resolves) and #299 (query strings dropped from the SSR lazy lookup). Those assume the annotation was emitted."use server"should be on this pathtransformDirectivesalso lives in@solidjs/compilerand accepts plain.ts/.js. Thistransform()never calls it. Vite runs it from a second plugin,serverFunctions()insrc/server-functions/index.ts, whose default include is alreadysrc/**/*.{jsx,tsx,tsrx,ts,js,mjs,cjs}. So"use server"is the only one of these passes that escaped the JSX gate, and it did so by living in a different plugin. That split is weird.A non-JSX module should get primitive names, the lazy /
$$moduleUrlpipeline, refresh, and"use server"from the same plugin. Do not leave"use server"as the only pass that runs on.ts/.jsbecause a second plugin happens to include those extensions.Expected
One non-JSX pipeline, in this plugin:
transformSourceNames)$$moduleUrl(transformLazy,resolveLazyModuleUrls, SSRinjectSsrModuleId)"use server"(transformDirectives)