create-solid (Solid 2 templates): SSR toggle missing for with-* variants, stale pnpm-lock after devtools edit, generated server.js blocks the [...404] chunk
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Accessibilité débutants
- 35/100
- Type d'issue
- Bug
- Clarté
- Plutôt claire
- Activité
- Active
- Stack technique
- typescript, vite
- Domaine
- backend, build-system, cli
Piste de recherche
Start with templates.json, the bundled fallback in dist/bin.mjs, and the generated server.js path used by the SSR toggle; compare them with dist/server/node.js and the fullstack template. Reproduce the listed scaffolding, frozen-install, build, and curl commands. Done means all solid-v2 with-* variants offer SSR, mutations leave package-manager metadata usable, and the [...404] asset is served correctly without unsafe path handling.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Three defects in [email protected]'s Solid 2 (solid-v2) scaffolding, found while triaging two user reports of a fresh rc.9 project failing on Firebase App Hosting:
- https://github.com/solidjs/templates/issues/309 (with-tailwindcss:
npm startruns the Vite dev server in production) - https://github.com/solidjs/templates/issues/310 (basic + SSR: direct load of
/usersthrows "Uncaught Client Exception")
(a) SSR toggle is only offered for basic
templates.json (and the bundled fallback uo(iw, "basic", "basic", "with-tsrx")) sets ssrToggle: true only on basic. Scaffolding with-tailwindcss --solid never asks "Enable server-side rendering?", so the project keeps "start": "vite" — the dev server. Hosts that run npm run build then prune devDependencies and npm start (Firebase App Hosting does exactly this) fail with Could not resolve '@tailwindcss/vite', 'vitest/config', '@solidjs/vite-plugin'. The same user's basic project deployed fine only because he answered yes to SSR, which rewrites start to node server.js.
Every with-* variant in solid-v2 is basic plus one tool and contains the exact solid({ start: true marker the SSR rewrite (kw) keys on, so enabling ssrToggle for with-bootstrap, with-sass, with-tailwindcss, with-tanstack-router, with-tsrx, with-unocss, with-vitest-browser-mode should work with no other change (verified the marker is present in with-tailwindcss/vite.config.ts).
Proposed fix: set ssrToggle: true on the with-* entries (templates.json upstream + the bundled fallback), or derive it from the marker's presence at scaffold time.
(b) --devtools edits package.json but ships the template's pnpm-lock.yaml unchanged
Repro:
node dist/bin.mjs my-app with-tailwindcss --solid --js --devtools
cd my-app && pnpm install --frozen-lockfile
# ERR_PNPM_OUTDATED_LOCKFILE
# specifiers in the lockfile don't match specifiers in package.json:
# * 1 dependencies were added: @solidjs/start-devtools@^1.0.0-next.4
The unmodified template lockfiles are in sync (pnpm install --frozen-lockfile --lockfile-only passes in solid-v2/basic and solid-v2/with-tailwindcss). CI environments (App Hosting, GitHub Actions, Vercel, …) default to frozen installs, so every devtools-enabled project fails its first CI install until the user deletes pnpm-lock.yaml/pnpm-workspace.yaml by hand — which is what the reporter ended up doing ("I have to remove the yaml files").
Proposed fix: whenever create-solid mutates package.json (devtools add, SSR start rewrite, TS→JS conversion), delete pnpm-lock.yaml (and pnpm-workspace.yaml if the project is not going to use pnpm), or regenerate the lock when pnpm is the chosen package manager. The templates README already says the lockfile "can be safely removed once you clone a template".
(c) Generated SSR server.js refuses the [...404] route chunk
The server.js written by the SSR toggle guards static serving with:
if (url !== '/' && !url.includes('..')) {
const content = readFileSync(path.resolve(__dirname, 'dist/client' + url.split('?')[0]));
The catch-all route src/routes/[...404].tsx compiles to dist/client/assets/_...404_-<hash>.js, whose URL contains ... The guard rejects it, the request falls through to handleRequest, which SSR-renders the 404 page as text/html with status 404. The browser rejects HTML as a module script, so on every direct load of a nonexistent URL (and on client navigation to one) the console shows
Hydration module preload failed; rendering boundary content on the client: TypeError: Failed to fetch dynamically imported module: …/assets/_...404_-Ctz1Phvb.js
TypeError: Failed to fetch dynamically imported module: … (Safari: "Importing a module script failed.")
and the page shows the Error | Uncaught Client Exception banner. Reproduced locally:
node dist/bin.mjs repro basic --solid --ssr --ts --devtools=false
cd repro && npm i && npm run build && PORT=8080 node server.js
curl -i "http://localhost:8080/assets/_...404_-<hash>.js" # 404 text/html
The server @solidjs/vite-plugin emits with start: { node: true } (dist/server/node.js) serves the same URL as 200 text/javascript: it decodes the pathname, rejects only dot-segments, then path.join(clientRoot, decoded) and requires file.startsWith(clientRoot + path.sep).
Also worth noting: server.js builds request.url as http://${req.headers.host}${req.url}. Behind a proxy that rewrites Host (App Hosting rewrites it to the Cloud Run *.a.run.app host; original is in X-Forwarded-Host) getRequestEvent().request.url points at a host the container cannot reach itself through, which is what broke the basic template's SSR-time fetch(new URL('/users.json', request.url)) in templates#310 (the render fails and the client sees the sanitized Error: Internal Server Error). The template side is tracked in the templates repo, but the scheme/host construction here is the other half.
Proposed fix: either
- drop the hand-rolled
server.jsand have the SSR toggle setstart: { node: true }invite.configplus"start": "node --env-file-if-exists=.env dist/server/node.js"(what thefullstacktemplate already does), or - keep
server.jsbut replace theincludes('..')guard with a containment check:
const clientRoot = path.resolve(__dirname, 'dist/client');
const file = path.resolve(clientRoot, '.' + decodeURIComponent(url.split('?')[0]));
if (url !== '/' && file.startsWith(clientRoot + path.sep)) { /* serve file */ }
and consider honouring X-Forwarded-Proto/X-Forwarded-Host when constructing the Request URL.
— filed by Claude via Cursor
- Langage dominant
- TypeScript
- Étoiles
- 79
- Forks
- 24
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de solidjs-community/solid-cli
-
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 30/100
solidjs-community/solid-cli#88 · 3 commentaires ·
-
Visible ErrorsOuverte
Difficulté 3/5 1-2 jours Accessibilité débutants 35/100
solidjs-community/solid-cli#59 · 1 commentaire · 1 réaction ·
-
Add CONTRIBUTING.mdOuvertedocumentation
Difficulté 2/5 1-3 heures Accessibilité débutants 35/100
-
README GenerationOuverteenhancement
Difficulté 4/5 3-5 jours Accessibilité débutants 35/100
Toutes les issues de solidjs-community/solid-cli
Issues similaires
-
area/dashboard kind/bug QA/dev-automation
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
rancher/dashboard#19379 · 2 commentaires ·
Les mainteneurs répondent en général sous 5 jours
-
perf(core): getComments() runs the approved count and the comment list as two sequential queriesOuvertearea/core bot:bug bot:working
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
emdash-cms/emdash#3905 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulté 1/5 Moins d'une heure Accessibilité débutants 90/100
lingdojo/kana-dojo#31728 · 1 commentaire · 5 réactions ·
Les mainteneurs répondent en général sous 1 jour
-
selective-claw: freshTailTurns=0 keeps ALL turns verbatim and summarizes none (slice(-0) === slice(0))Peut-être pris @zjncs l’a pris aujourd’hui. Ouvertecomponent:tokenless
Difficulté 2/5 1-3 heures Accessibilité débutants 80/100
agentic-os-org/ANOLISA#6112 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
bug needs triage
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
rjsf-team/react-jsonschema-form#5439 ·
Les mainteneurs répondent en général sous 1 jour