serverFunctions.components: CSS below a use server boundary is missing from production client assets (rc.15 / next)
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 56/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- typescript, vite
- Bereich
- build-system, frontend
Rechercherichtung
Start with the referenced client transform in packages/compiler/src/directives/transform.rs and the plugin’s server-functions handling in src/server-functions/index.ts; then compare production manifest loading in src/index.ts with dev CSS collection in src/dev-manifest.ts. Reproduce with the supplied minimal app using bunx vite build and check the client manifest and production SSR output. Done means the server component’s CSS is represented in production assets and appears on both document loads and frame navigation, with the reported reproduction styled.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
CSS imported only below a module-level 'use server' boundary is not delivered to the browser in production SSR start mode with serverFunctions: { components: true }. The server component's HTML is present, but its CSS is absent on both document loads and subsequent frame requests. Plain Vite reproduces this without Cloudflare or Vite+.
Versions tested
- Published:
solid-js,@solidjs/web,@solidjs/signals,@solidjs/compiler, and@solidjs/babel-plugin2.0.0-rc.15;@solidjs/vite-plugin3.0.0-next.50. - Source builds of both
nextbranches:- solidjs/solid: 2aa9e86ada5beb33211f60260c59234bbcf14899 (local Signals, Solid, Web/frames, Babel plugin, and a locally compiled native compiler).
- solidjs/solid-vite-plugin: ec6b58d0c17290d6f474a9ed93bfa03d1dc9b8a0.
- Both: plain
vite8.3.4, Bun 1.4.2, Node 26.12.0, macOS arm64; browser checks withplaywright-core1.64.1 and system Google Chrome 155.0.8059.85 (channel: 'chrome').
The published versions were resolved from solid-js@next, @solidjs/web@next, and @solidjs/vite-plugin@latest; the plugin's next tag currently points to an older release.
Minimal reproduction
Start with an empty directory and package.json containing {"private":true,"type":"module"}, then:
bun add solid-js@next @solidjs/web@next @solidjs/vite-plugin@latest vite
// vite.config.ts
import { defineConfig } from 'vite';
import solid from '@solidjs/vite-plugin';
export default defineConfig({
plugins: [solid({ start: true, ssr: true,
serverFunctions: { components: true }, performanceTracks: false })],
});
// src/App.tsx
import { createSignal, Loading } from 'solid-js';
import { dynamic, getRequestEvent, isServer } from '@solidjs/web';
import { getNotes } from './server';
function PageB() {
const Notes = dynamic(() => getNotes());
return <Loading fallback={<p>Loading...</p>}><Notes /></Loading>;
}
export default function App() {
const url = isServer ? getRequestEvent()!.request.url : location.href;
const [page, setPage] = createSignal(new URL(url).pathname === '/b' ? 'b' : 'a');
return <main>
<button id="to-a" onClick={() => setPage('a')}>Page A</button>
<button id="to-b" onClick={() => setPage('b')}>Page B</button>
{page() === 'b' ? <PageB /> : <p>Plain page A</p>}
</main>;
}
// src/server.tsx
'use server';
import { Notes } from './notes';
export async function getNotes() { return () => <Notes />; }
// src/notes.tsx — imported ONLY by server.tsx
import './notes.css';
export function Notes() {
return <div id="notes" class="notes">Server-only notes</div>;
}
/* src/notes.css */
.notes { color: rgb(255, 0, 0); background-color: rgb(255, 255, 0); }
No authored entries, router, custom manifest, optimizeDeps exclusions, or css.filter settings are required. For the linked HEAD package check, I used start: { devtools: false } to disable the optional devtools detected in the plugin checkout; the production result is the same.
Steps and results
The following results are the same for the published packages and the two source-built HEADs:
- Build:
bunx vite build. Expected: the server component's stylesheet is available as a browser-served asset (or inline CSS) and represented in the relevant asset collection. Actual: no notes CSS underdist/client, no notes CSS entry indist/client/.vite/manifest.json. With plain Vite's default SSR asset settings, this minimal repro emits no standalone CSS underdist/servereither. The CSS Module variant still embeds the hashed class string in the server output. - Production document:
bunx vite preview --host 127.0.0.1 --port 5200 --strictPort, then open/bin a fresh browser context. Expected: red notes. Actual: HTTP 200, raw SSR HTML contains#notes, but no stylesheet link or inline rule;getComputedStyle(document.querySelector('#notes')).colorisrgb(0, 0, 0). Boot makes zero/_serverrequests, so document adoption itself works. - Production client navigation: in another fresh browser context, open
/aand click Page B. Expected: red notes, with styles delivered before reveal if they were not already loaded. Actual: a successfulapplication/x-frame-streamresponse from/_server/data/getNotes-d166722econtainsstart,html,complete, but noassetsrecord /styles. The element appears with black text. There are no page/console errors in these production checks. - Dev: run
bunx vite --host 127.0.0.1 --port 5201 --strictPortand repeat both browser paths. Actual: both are red. The initial document inlines the notes stylesheet in a<style data-asset="…/src/notes.css" data-vite-dev-id="…">, even on page A. The subsequent frame response still has no style assets, but this case already has the CSS. This dev/production difference hides the problem during development.
The CSS Module variant also reproduces: replace the import with import css from './notes.module.css' and use class={css.notes}. Production SSR and frame HTML contain a hashed class, e.g. _notes_5xr5i_1, with no matching stylesheet; dev is styled.
Workaround verified on both versions
With the plain .css variant above, also add import './notes.css' to src/App.tsx. The build then emits a client CSS asset, its manifest entry has css, the SSR document links it, and both production browser paths compute rgb(255, 0, 0). Dev also stays styled. This workaround eagerly loads the server component's styles through a client-owned import.
Design and source observations
I read the plugin README sections for serverFunctions, start, start.css.filter, and virtual:solid-manifest, plus the server-components docs. I did not find a documented requirement to repeat a server component's CSS import in a client module. css.filter is documented as development-only, and virtual:solid-manifest exposes the client build manifest in production.
The frame streams RFC, “4. Fragment assets and styles” describes assets with styles and style-gated reveal. This transport is present: frame-sink.ts, lines 565–577 emits CSS entries from meta.preloads as assets.styles.
The collection boundary appears to be earlier:
- The compiler's module-level client transform, lines 570–573 rebuilds the module from its server-function references, dropping its original imports. Directly inspecting the transform of this repro yields only
createServerReference(...)and the exported proxy;./notesis gone. Removing server implementation imports is expected; this observation explains why its transitive stylesheet is absent from the client graph. - The plugin consumes that transform and records function metadata, while the production manifest loader reads the client build manifest. In this repro that manifest has no notes CSS to deliver.
- In contrast, dev CSS collection traverses the SSR graph, which matches the observed working dev documents.
These are collection/transform observations, rather than a claim that the frames consumer rejects a supplied stylesheet. Should server-component CSS reached only through this boundary be collected for production as well, or is there an intended authoring pattern that should be documented?
Related context: #428 is my earlier report about a duplicated server-functions client in dev with optimizeDeps.exclude; this repro uses no exclusions and produces valid component HTML. Existing #414/#415 concern dev manifest timing/cache, and #425 concerns CSS ordering; those do not cover this production omission.
- Vorherrschende Sprache
- TypeScript
- Sterne
- 522
- Forks
- 73
- Ø Merge
- 1 T. 8 Std.
- Gemergte PRs (30 T.)
- 31
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus solidjs/solid-vite-plugin
-
Vitest config is dropped when test.server.deps.external already lists solid-jsEvtl. vergeben @RaphaelFakhri hat das vor 2 Tagen übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
solidjs/solid-vite-plugin#454 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Test environment detection doesn't consider Vitest workspacesEvtl. vergeben @carloitaben hat das vor 59 Tagen übernommen. Offen1.x
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
solidjs/solid-vite-plugin#205 · 1 Kommentar · 2 Reaktionen ·
Maintainer antworten meist innerhalb von 1 Tag
-
serverFunctions.components (dev): server-functions client is duplicated when @solidjs/web is in optimizeDeps.exclude, so post-boot server components resolve to undefinedEvtl. vergeben Ein verknüpfter Pull Request ist offen oder bereits gemergt. Offen
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 58/100
solidjs/solid-vite-plugin#428 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
[3.0.0-next.50 / next] Dev with a host-owned SSR environment: the first server-function call after startup, a restart or a new "use server" file waits a fixed 1 sEvtl. vergeben Ein verknüpfter Pull Request ist offen oder bereits gemergt. Offen
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 58/100
solidjs/solid-vite-plugin#427 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Dev: a stylesheet shared by the entry and a lazy component moves after the lazy component's stylesEvtl. vergeben Ein verknüpfter Pull Request ist offen oder bereits gemergt. Offen
Schwierigkeit 3/5 Ein halber Tag Anfängerfreundlichkeit 62/100
solidjs/solid-vite-plugin#425 ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in solidjs/solid-vite-plugin
Ähnliche Issues
-
Edit: Tele Posadas HDOffencheck:passed streams:edit
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
Maintainer antworten meist innerhalb von 1 Tag
-
area:mcp bug has repro platform:vscode regression
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
anthropics/claude-code#103970 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 84/100
Maintainer antworten meist innerhalb von 1 Tag
-
sdk-typescript: unquoted COPY globs in shell form are silently dropped from the image build contextOffenbug javascript
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag