diff --git a/apps/fixtures/css/README.md b/apps/fixtures/css/README.md new file mode 100644 index 000000000..128403d02 --- /dev/null +++ b/apps/fixtures/css/README.md @@ -0,0 +1,30 @@ +# SolidStart + +Everything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com); + +## Creating a project + +```bash +# create a new project in the current directory +npm init solid@latest + +# create a new project in my-app +npm init solid@latest my-app +``` + +## Developing + +Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: + +```bash +npm run dev + +# or start the server and open the app in a new browser tab +npm run dev -- --open +``` + +## Building + +Solid apps are built with _presets_, which optimise your project for deployment to different environments. + +By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, add it to the `devDependencies` in `package.json` and specify in your `app.config.js`. diff --git a/apps/fixtures/css/package.json b/apps/fixtures/css/package.json new file mode 100644 index 000000000..b3b32953b --- /dev/null +++ b/apps/fixtures/css/package.json @@ -0,0 +1,23 @@ +{ + "name": "fixture-css", + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "start": "node .output/server/index.mjs" + }, + "dependencies": { + "@solidjs/meta": "^0.29.4", + "@solidjs/router": "^0.15.0", + "@solidjs/start": "workspace:*", + "solid-js": "^1.9.9", + "vite": "7.1.10" + }, + "engines": { + "node": ">=22" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.1.12", + "tailwindcss": "^4.1.12" + } +} diff --git a/apps/fixtures/css/public/favicon.ico b/apps/fixtures/css/public/favicon.ico new file mode 100644 index 000000000..fb282da07 Binary files /dev/null and b/apps/fixtures/css/public/favicon.ico differ diff --git a/apps/fixtures/css/src/app.css b/apps/fixtures/css/src/app.css new file mode 100644 index 000000000..7b8888fa1 --- /dev/null +++ b/apps/fixtures/css/src/app.css @@ -0,0 +1,21 @@ +@import "tailwindcss"; + +@theme { + --color-success: var(--color-emerald-700); + --color-error: var(--color-rose-700); + --color-warn: var(--color-orange-500); +} + +@layer base { + body { + @apply bg-gray-800 text-gray-100; + } + + a { + @apply text-sky-400 underline underline-offset-4 hover:no-underline; + } + + h1 { + @apply text-2xl font-bold; + } +} diff --git a/apps/fixtures/css/src/app.tsx b/apps/fixtures/css/src/app.tsx new file mode 100644 index 000000000..32aeff5ec --- /dev/null +++ b/apps/fixtures/css/src/app.tsx @@ -0,0 +1,28 @@ +import { MetaProvider, Title } from "@solidjs/meta"; +import { Router } from "@solidjs/router"; +import { FileRoutes } from "@solidjs/start/router"; +import { Suspense } from "solid-js"; +import "./app.css"; + +export default function App() { + return ( + ( + + SolidStart - CSS Fixture +
+
+ Index + Empty + Unstyled +
+ + {props.children} +
+
+ )} + > + +
+ ); +} diff --git a/apps/fixtures/css/src/components/layout.tsx b/apps/fixtures/css/src/components/layout.tsx new file mode 100644 index 000000000..91d077054 --- /dev/null +++ b/apps/fixtures/css/src/components/layout.tsx @@ -0,0 +1,56 @@ +import { createSignal, FlowProps, onMount } from "solid-js"; +import { getRequestEvent } from "solid-js/web"; + +const Badge = (props: FlowProps) => ( +
{props.children}
+); + +const Layout = (props: FlowProps<{ title: string }>) => { + const [mounted, setMounted] = createSignal(false); + onMount(() => setMounted(true)); + + return ( +
+
+

{props.title}

+ Environment: {import.meta.env.DEV ? "DEV" : "PROD"} + Rendered: {!mounted() ? "Server" : "Server & Client"} +
+ +
+ Agent:{" "} + + {getRequestEvent()?.request.headers.get("user-agent") ?? navigator.userAgent} + +
+ + + +
+
+
Component
+
File
+
Integration
+
Lazy
+
Comments
+
+ + {props.children} +
+ +
+
pass
+
fail
+
not supported
+
+
+ ); +}; + +export default Layout; diff --git a/apps/fixtures/css/src/components/lazy.tsx b/apps/fixtures/css/src/components/lazy.tsx new file mode 100644 index 000000000..462362ec2 --- /dev/null +++ b/apps/fixtures/css/src/components/lazy.tsx @@ -0,0 +1,7 @@ +import "../styles/lazy.css"; + +const Lazy = () => { + return <> +} + +export default Lazy; diff --git a/apps/fixtures/css/src/components/lazyGlob.tsx b/apps/fixtures/css/src/components/lazyGlob.tsx new file mode 100644 index 000000000..75dca500b --- /dev/null +++ b/apps/fixtures/css/src/components/lazyGlob.tsx @@ -0,0 +1,7 @@ +import "../styles/lazyGlob.css"; + +const Lazy = () => { + return <> +} + +export default Lazy; diff --git a/apps/fixtures/css/src/components/lazyLink.tsx b/apps/fixtures/css/src/components/lazyLink.tsx new file mode 100644 index 000000000..f3b9084e7 --- /dev/null +++ b/apps/fixtures/css/src/components/lazyLink.tsx @@ -0,0 +1,5 @@ +import url from "../styles/lazyLink.css?url"; + +const Lazy = () => + +export default Lazy; diff --git a/apps/fixtures/css/src/components/lazyLinkTmp.tsx b/apps/fixtures/css/src/components/lazyLinkTmp.tsx new file mode 100644 index 000000000..3a04dd96e --- /dev/null +++ b/apps/fixtures/css/src/components/lazyLinkTmp.tsx @@ -0,0 +1,5 @@ +import url from "../styles/lazyLinkTmp.css?url"; + +const Lazy = () => + +export default Lazy; diff --git a/apps/fixtures/css/src/components/test.tsx b/apps/fixtures/css/src/components/test.tsx new file mode 100644 index 000000000..8f3e8ea1a --- /dev/null +++ b/apps/fixtures/css/src/components/test.tsx @@ -0,0 +1,107 @@ +import { JSX } from "solid-js"; + +const clsx = (...args: (string | false | undefined)[]) => args.filter(Boolean).join(" "); + +const integrations = { + import: "import", + module: "import module", + url: "?url without render", + link: "?url + ", +}; +const Test = (props: { + invert?: boolean; + class?: string; + component: string; + file: string; + integration?: keyof typeof integrations; + lazy?: boolean; + noSupport?: boolean; + comment?: JSX.Element; +}) => ( +
+
{props.component}
+
{props.file}
+
{integrations[props.integration ?? "import"]}
+
{props.lazy ? <>✓ : null}
+
{props.comment}
+
+); + +export const CommonTests = (props: { routeModuleClass?: string }) => ( + <> + + + + + + + + + + + + + Tests fallbacks, only mounted while loading. +
+ Red while mounted. + + } + /> + +); + +export default Test; diff --git a/apps/fixtures/css/src/entry-client.tsx b/apps/fixtures/css/src/entry-client.tsx new file mode 100644 index 000000000..b9fc52a4e --- /dev/null +++ b/apps/fixtures/css/src/entry-client.tsx @@ -0,0 +1,5 @@ +// @refresh reload +import { mount, StartClient } from "@solidjs/start/client"; +import "./styles/entryClient.css"; + +mount(() => , document.getElementById("app")!); diff --git a/apps/fixtures/css/src/entry-server.tsx b/apps/fixtures/css/src/entry-server.tsx new file mode 100644 index 000000000..47822cea1 --- /dev/null +++ b/apps/fixtures/css/src/entry-server.tsx @@ -0,0 +1,24 @@ +// @refresh reload +import { createHandler, StartServer } from "@solidjs/start/server"; +import "./styles/entryServer.css"; +import url from "./styles/entryServerUrl.css?url"; + +export default createHandler(() => ( + ( + + + + + + + {assets} + + +
{children}
+ {scripts} + + + )} + /> +)); diff --git a/apps/fixtures/css/src/global.d.ts b/apps/fixtures/css/src/global.d.ts new file mode 100644 index 000000000..dc6f10c22 --- /dev/null +++ b/apps/fixtures/css/src/global.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/fixtures/css/src/routes/[...404].tsx b/apps/fixtures/css/src/routes/[...404].tsx new file mode 100644 index 000000000..53b221ce7 --- /dev/null +++ b/apps/fixtures/css/src/routes/[...404].tsx @@ -0,0 +1,19 @@ +import { Title } from "@solidjs/meta"; +import { HttpStatusCode } from "@solidjs/start"; + +export default function NotFound() { + return ( +
+ Not Found + +

Page Not Found

+

+ Visit{" "} + + start.solidjs.com + {" "} + to learn how to build SolidStart apps. +

+
+ ); +} \ No newline at end of file diff --git a/apps/fixtures/css/src/routes/empty.tsx b/apps/fixtures/css/src/routes/empty.tsx new file mode 100644 index 000000000..65eff5795 --- /dev/null +++ b/apps/fixtures/css/src/routes/empty.tsx @@ -0,0 +1,10 @@ +import { Title } from "@solidjs/meta"; + +export default function Empty() { + return ( +
+ Empty +

Empty

+
+ ); +} diff --git a/apps/fixtures/css/src/routes/index.tsx b/apps/fixtures/css/src/routes/index.tsx new file mode 100644 index 000000000..08933785e --- /dev/null +++ b/apps/fixtures/css/src/routes/index.tsx @@ -0,0 +1,44 @@ +import { createAsync, query } from "@solidjs/router"; +import { lazy, Show } from "solid-js"; +import Layout from "../components/layout"; +import { CommonTests } from "../components/test"; +import notRenderedInlineCSS from "../styles/notRendered.css?url"; +import "../styles/route.css"; +import classes from "../styles/route.module.css"; +import renderedInlineCSS from "../styles/url.css?url"; + +const Lazy = lazy(() => import("../components/lazy")); +const LazyLink = lazy(() => import("../components/lazyLink")); +const LazyLinkTmp = lazy(() => import("../components/lazyLinkTmp")); + +const entries = import.meta.glob("../components/lazyG*.tsx"); +const LazyGlob = lazy(Object.values(entries)[0] as any); + +const getData = query(async () => { + "use server"; + await new Promise(res => setTimeout(res, 1000)); + return "CSS Tests"; +}, "data"); + +export default function Home() { + const data = createAsync(() => getData(), { deferStream: true }); + + return ( +
+ + + + + + + + + + + + + + +
+ ); +} diff --git a/apps/fixtures/css/src/routes/unstyled.tsx b/apps/fixtures/css/src/routes/unstyled.tsx new file mode 100644 index 000000000..f9b22315f --- /dev/null +++ b/apps/fixtures/css/src/routes/unstyled.tsx @@ -0,0 +1,14 @@ +import { Title } from "@solidjs/meta"; +import Layout from "../components/layout"; +import { CommonTests } from "../components/test"; + +export default function Others() { + return ( +
+ Unstyled + + + +
+ ); +} diff --git a/apps/fixtures/css/src/styles/entryClient.css b/apps/fixtures/css/src/styles/entryClient.css new file mode 100644 index 000000000..84dafa95c --- /dev/null +++ b/apps/fixtures/css/src/styles/entryClient.css @@ -0,0 +1,3 @@ +.entryClient { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/src/styles/entryServer.css b/apps/fixtures/css/src/styles/entryServer.css new file mode 100644 index 000000000..aac9295a0 --- /dev/null +++ b/apps/fixtures/css/src/styles/entryServer.css @@ -0,0 +1,3 @@ +.entryServer { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/src/styles/entryServerUrl.css b/apps/fixtures/css/src/styles/entryServerUrl.css new file mode 100644 index 000000000..ce4d8b91c --- /dev/null +++ b/apps/fixtures/css/src/styles/entryServerUrl.css @@ -0,0 +1,3 @@ +.entryServerUrl { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/src/styles/lazy.css b/apps/fixtures/css/src/styles/lazy.css new file mode 100644 index 000000000..fdc1d5a60 --- /dev/null +++ b/apps/fixtures/css/src/styles/lazy.css @@ -0,0 +1,3 @@ +.lazy { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/src/styles/lazyGlob.css b/apps/fixtures/css/src/styles/lazyGlob.css new file mode 100644 index 000000000..4c7b92f51 --- /dev/null +++ b/apps/fixtures/css/src/styles/lazyGlob.css @@ -0,0 +1,3 @@ +.lazyGlob { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/src/styles/lazyLink.css b/apps/fixtures/css/src/styles/lazyLink.css new file mode 100644 index 000000000..50c6d1663 --- /dev/null +++ b/apps/fixtures/css/src/styles/lazyLink.css @@ -0,0 +1,3 @@ +.lazyLink { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/src/styles/lazyLinkTmp.css b/apps/fixtures/css/src/styles/lazyLinkTmp.css new file mode 100644 index 000000000..3523d74df --- /dev/null +++ b/apps/fixtures/css/src/styles/lazyLinkTmp.css @@ -0,0 +1,3 @@ +.lazyLinkTmp { + background-color: var(--color-error); +} diff --git a/apps/fixtures/css/src/styles/notRendered.css b/apps/fixtures/css/src/styles/notRendered.css new file mode 100644 index 000000000..bf07490f8 --- /dev/null +++ b/apps/fixtures/css/src/styles/notRendered.css @@ -0,0 +1,3 @@ +.notRendered { + background-color: var(--color-error); +} diff --git a/apps/fixtures/css/src/styles/route.css b/apps/fixtures/css/src/styles/route.css new file mode 100644 index 000000000..1cddfd725 --- /dev/null +++ b/apps/fixtures/css/src/styles/route.css @@ -0,0 +1,3 @@ +.route { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/src/styles/route.module.css b/apps/fixtures/css/src/styles/route.module.css new file mode 100644 index 000000000..1cddfd725 --- /dev/null +++ b/apps/fixtures/css/src/styles/route.module.css @@ -0,0 +1,3 @@ +.route { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/src/styles/url.css b/apps/fixtures/css/src/styles/url.css new file mode 100644 index 000000000..a587a91d2 --- /dev/null +++ b/apps/fixtures/css/src/styles/url.css @@ -0,0 +1,3 @@ +.url { + background-color: var(--color-success); +} diff --git a/apps/fixtures/css/tsconfig.json b/apps/fixtures/css/tsconfig.json new file mode 100644 index 000000000..1f0bda6da --- /dev/null +++ b/apps/fixtures/css/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "allowJs": true, + "strict": true, + "noEmit": true, + "isolatedModules": true, + "paths": { + "~/*": ["./src/*"] + }, + "types": ["vite/client"] + } +} diff --git a/apps/fixtures/css/vite.config.ts b/apps/fixtures/css/vite.config.ts new file mode 100644 index 000000000..598584d4b --- /dev/null +++ b/apps/fixtures/css/vite.config.ts @@ -0,0 +1,8 @@ +import tailwindcss from "@tailwindcss/vite"; +import { defineConfig } from "vite"; +import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src"; +import { solidStart } from "../../../packages/start/src/config"; + +export default defineConfig({ + plugins: [solidStart(), nitroV2Plugin(), tailwindcss()] +}); diff --git a/packages/start/package.json b/packages/start/package.json index 1c78617e0..23d52ccda 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -37,6 +37,7 @@ "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "^1.133.11", "@types/babel__traverse": "^7.28.0", diff --git a/packages/start/src/config/fs-routes/index.ts b/packages/start/src/config/fs-routes/index.ts index aff1cbd3c..81bad92fe 100644 --- a/packages/start/src/config/fs-routes/index.ts +++ b/packages/start/src/config/fs-routes/index.ts @@ -1,7 +1,6 @@ -import { relative, resolve } from "node:path"; -import { normalizePath, type PluginOption } from "vite"; +import { relative } from "node:path"; +import { type PluginOption } from "vite"; -import { VITE_ENVIRONMENTS } from "../constants.ts"; import { fileSystemWatcher } from "./fs-watcher.ts"; import type { BaseFileSystemRouter } from "./router.ts"; import { treeShake } from "./tree-shake.ts"; @@ -59,10 +58,7 @@ export function fsRoutes({ routers }: FsRoutesArgs): Array { build: isBuild ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` : undefined, - import: - this.environment.name === VITE_ENVIRONMENTS.server - ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` - : `_$(() => clientManifestImport('${relative(root, buildId)}'))$_`, + import: `_$() => import(/* @vite-ignore */ '${buildId}')$_` }; } return v; @@ -72,15 +68,6 @@ export function fsRoutes({ routers }: FsRoutesArgs): Array { const code = ` ${js.getImportStatements()} -${ - this.environment.name === VITE_ENVIRONMENTS.server - ? "" - : ` -import { getClientManifest } from "solid-start:get-client-manifest"; -function clientManifestImport(id) { - return getClientManifest().import(id) -}` -} export default ${routesCode}`; return code; }, diff --git a/packages/start/src/config/index.ts b/packages/start/src/config/index.ts index 879eb6530..b284bdaa1 100644 --- a/packages/start/src/config/index.ts +++ b/packages/start/src/config/index.ts @@ -1,12 +1,11 @@ +import { TanStackServerFnPlugin } from "@tanstack/server-functions-plugin"; +import { defu } from "defu"; import { globSync } from "node:fs"; import { extname, isAbsolute, join, normalize } from "node:path"; import { fileURLToPath } from "node:url"; -import { TanStackServerFnPlugin } from "@tanstack/server-functions-plugin"; -import { defu } from "defu"; -import { type PluginOption, type ViteDevServer } from "vite"; +import { type PluginOption } from "vite"; import solid, { type Options as SolidOptions } from "vite-plugin-solid"; -import { isCssModulesFile } from "../server/collect-styles.ts"; import { DEFAULT_EXTENSIONS, VIRTUAL_MODULES, @@ -19,6 +18,7 @@ import { } from "./fs-router.ts"; import { fsRoutes } from "./fs-routes/index.ts"; import type { BaseFileSystemRouter } from "./fs-routes/router.ts"; +import lazy from "./lazy.ts"; import { manifest } from "./manifest.ts"; import { parseIdQuery } from "./utils.ts"; @@ -158,7 +158,6 @@ export function solidStart(options?: SolidStartOptions): Array { }, }, manifest(start), - css(), fsRoutes({ routers: { client: new SolidStartClientFileRouter({ @@ -172,6 +171,7 @@ export function solidStart(options?: SolidStartOptions): Array { }), }, }), + lazy(), // Must be placed after fsRoutes, as treeShake will remove the // server fn exports added in by this plugin TanStackServerFnPlugin({ @@ -236,38 +236,3 @@ export function solidStart(options?: SolidStartOptions): Array { }), ]; } - -function css(): PluginOption { - let viteServer!: ViteDevServer; - const cssModules: Record = {}; - return { - name: "solid-start:css-hmr", - configureServer(dev) { - viteServer = dev; - }, - async handleHotUpdate({ file, server }) { - if (file.endsWith(".css")) { - const resp = await server.transformRequest(file); - if (!resp) return; - const json = resp.code - .match(/const __vite__css = .*\n/)?.[0] - ?.slice("const __vite__css = ".length); - if (!json) return; - resp.code = JSON.parse(json); - viteServer.ws.send({ - type: "custom", - event: "css-update", - data: { - file, - contents: resp.code, - }, - }); - } - }, - transform(code, id) { - if (isCssModulesFile(id)) { - cssModules[id] = code; - } - }, - }; -} diff --git a/packages/start/src/config/lazy.ts b/packages/start/src/config/lazy.ts new file mode 100644 index 000000000..65602f3bb --- /dev/null +++ b/packages/start/src/config/lazy.ts @@ -0,0 +1,100 @@ +import type { PluginItem } from "@babel/core"; +import babel from "@babel/core"; +import * as t from "@babel/types"; +import { sep as osSep } from "path"; +import { basename, relative, sep } from "path/posix"; +import type { PluginOption } from "vite"; +import { VITE_ENVIRONMENTS } from "./constants.ts"; + +const idTransform = (id: string): PluginItem => { + return { + visitor: { + Program(path) { + path.node.body.unshift( + t.exportNamedDeclaration( + t.variableDeclaration("const", [ + t.variableDeclarator(t.identifier("id$$"), t.stringLiteral(id)) + ]) + ) + ); + } + } + }; +}; + +const importTransform = (): PluginItem => { + return { + visitor: { + ImportDeclaration(path) { + if (path.node.source.value !== "solid-js") return; + path.traverse({ + ImportSpecifier(subPath) { + if (subPath.node.local.name !== "lazy") return; + subPath.remove(); + path.insertAfter( + t.importDeclaration( + [t.importSpecifier(t.identifier("lazy"), t.identifier("lazy"))], + t.stringLiteral("@solidjs/start/server") + ) + ); + } + }); + } + } + }; +}; + +const fileEndingRegex = /(ts|js)x(\?.*)?$/; + +const lazy = (): PluginOption => { + const cwd = process.cwd().replaceAll(osSep, sep); + return { + name: "solid-lazy-css", + enforce: "pre", + applyToEnvironment(env) { + return env.name === VITE_ENVIRONMENTS.server; + }, + async transform(src, id) { + if (!id.match(fileEndingRegex)) return; + + // The transformed files either import "lazy" or css files + // Therefore we skip, if the src doesn't have any import + if (src.indexOf("import") === -1) return; + + const plugins: PluginItem[] = []; + + const hasDefaultExport = src.indexOf("export default") !== -1; + if (hasDefaultExport) { + const localId = relative(cwd, id); + plugins.push(idTransform(localId)); + } + + const hasLazy = src.indexOf("lazy(") !== -1; + if (hasLazy) plugins.push(importTransform()); + + if (!plugins.length) { + return; + } + + const transformed = await babel.transformAsync(src, { + plugins, + parserOpts: { + plugins: ["jsx", "typescript"] + }, + filename: basename(id), + ast: false, + sourceMaps: true, + configFile: false, + babelrc: false, + sourceFileName: id + }); + + if (!transformed?.code) return; + + const { code, map } = transformed; + return { code, map }; + } + }; +}; + +export default lazy; diff --git a/packages/start/src/router.tsx b/packages/start/src/router.tsx index e36da7381..7b2116e25 100644 --- a/packages/start/src/router.tsx +++ b/packages/start/src/router.tsx @@ -1,12 +1,15 @@ -import { getManifest } from "solid-start:get-manifest"; +import { lazy, type Component } from "solid-js"; import { getRequestEvent, isServer } from "solid-js/web"; -import lazyRoute from "./server/lazyRoute.tsx"; import { pageRoutes as routeConfigs } from "./server/routes.ts"; import type { PageEvent } from "./server/types.ts"; +const components: Record = {}; + export function createRoutes() { function createRoute(route: any) { + const component = route.$component && (components[route.$component.src] ??= lazy(route.$component.import)); + return { ...route, ...(route.$$route ? route.$$route.require().route : undefined), @@ -14,8 +17,7 @@ export function createRoutes() { ...(route.$$route ? route.$$route.require().route.info : {}), filesystem: true }, - component: - route.$component && lazyRoute(route.$component, getManifest("client"), getManifest("ssr")), + component, children: route.children ? route.children.map(createRoute) : undefined }; } diff --git a/packages/start/src/server/StartServer.tsx b/packages/start/src/server/StartServer.tsx index 370e97831..1059412bf 100644 --- a/packages/start/src/server/StartServer.tsx +++ b/packages/start/src/server/StartServer.tsx @@ -1,37 +1,21 @@ // @refresh skip -import App from "solid-start:app"; -import type { Component, JSX } from "solid-js"; +import type { Component } from "solid-js"; import { Hydration, HydrationScript, NoHydration, getRequestEvent, - ssr, - useAssets + ssr } from "solid-js/web"; +import App from "solid-start:app"; import { ErrorBoundary, TopErrorBoundary } from "../shared/ErrorBoundary.tsx"; -import { renderAsset } from "./renderAsset.tsx"; -import type { Asset, DocumentComponentProps, PageEvent } from "./types.ts"; +import { useAssets } from "./assets/index.ts"; import { getSsrManifest } from "./manifest/ssr-manifest.ts"; +import type { DocumentComponentProps, PageEvent } from "./types.ts"; const docType = ssr(""); -function matchRoute(matches: any[], routes: any[], matched = []): any[] | undefined { - for (let i = 0; i < routes.length; i++) { - const segment = routes[i]; - if (segment.path !== matches[0].path) continue; - let next: any = [...matched, segment]; - if (segment.children) { - const nextMatches = matches.slice(1); - if (nextMatches.length === 0) continue; - next = matchRoute(nextMatches, segment.children, next); - if (!next) continue; - } - return next; - } -} - /** * * Read more: https://docs.solidjs.com/solid-start/reference/server/start-server @@ -41,60 +25,16 @@ export function StartServer(props: { document: Component // @ts-ignore const nonce = context.nonce; - - let assets: Asset[] = []; - Promise.resolve() - .then(async () => { - const manifest = getSsrManifest("ssr"); - - let assetPromises: Promise[] = []; - // @ts-ignore - if (context.router && context.router.matches) { - // @ts-ignore - const matches = [...context.router.matches]; - while (matches.length && (!matches[0].info || !matches[0].info.filesystem)) matches.shift(); - const matched = matches.length && matchRoute(matches, context.routes); - if (matched) { - for (let i = 0; i < matched.length; i++) { - const segment = matched[i]; - assetPromises.push(manifest.getAssets(segment["$component"].src)); - } - } else if (import.meta.env.DEV) - console.warn( - `No route matched for preloading js assets for path ${new URL(context.request.url).pathname}` - ); - } - assets = await Promise.all(assetPromises).then(a => - // dedupe assets - [...new Map(a.flat().map(item => [item.attrs.key, item])).values()].filter(asset => - import.meta.env.START_ISLANDS - ? false - : (asset.attrs as JSX.LinkHTMLAttributes).rel === "modulepreload" && - !context.assets.find((a: Asset) => a.attrs.key === asset.attrs.key) - ) - ); - }) - .catch(console.error); - - useAssets(() => (assets.length ? assets.map(m => renderAsset(m)) : undefined)); + useAssets(context.assets, nonce); return ( {docType as unknown as any} - - {context.assets.map((m: any) => renderAsset(m, nonce))} - - } + assets={} scripts={ <> -