Skip to content
5 changes: 5 additions & 0 deletions .changeset/vite-8-compat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/start": patch
---

Add support for Vite 8 asset manifest loading
1 change: 1 addition & 0 deletions apps/fixtures/hackernews/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"scripts": {
"dev": "vite dev",
"preview": "vite preview",
"build": "vite build"
},
"dependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/start/src/config/fs-routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ export function fsRoutes({ routers }: FsRoutesArgs): Array<PluginOption> {
const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
return {
src: relative(root, buildId),
build: isBuild ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` : undefined,
import: `_$() => import(/* @vite-ignore */ '${buildId}')$_`,
build: isBuild ? `_$() => import('${buildId}')$_` : undefined,
import: `_$() => import('${buildId}')$_`,
};
}
return v;
Expand Down
13 changes: 12 additions & 1 deletion packages/start/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ export function solidStart(options?: SolidStartOptions): Array<PluginOption> {
return {
appType: "custom",
build: { assetsDir: "_build/assets" },
optimizeDeps: {
// Suppress TS errors from Vite 7 types when configuring Vite 8's Rolldown
...({
rolldownOptions: {
transform: {
jsx: "react",
},
},
} as any),
},
environments: {
[VITE_ENVIRONMENTS.client]: {
consumer: "client",
Expand Down Expand Up @@ -233,8 +243,9 @@ export function solidStart(options?: SolidStartOptions): Array<PluginOption> {
{
name: "solid-start:capture-client-bundle",
enforce: "post",
generateBundle(_options, bundle) {
generateBundle(options, bundle) {
globalThis.START_CLIENT_BUNDLE = bundle;
(globalThis as any).START_CLIENT_OUT_DIR = options.dir;
},
},
devServer(),
Expand Down
44 changes: 37 additions & 7 deletions packages/start/src/config/manifest.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { type PluginOption, type ViteDevServer } from "vite";
import fs from "node:fs";
import path from "node:path";
import { type PluginOption, type ViteDevServer, version as viteVersion } from "vite";

import { findStylesInModuleGraph } from "../server/collect-styles.ts";
import { VIRTUAL_MODULES } from "./constants.ts";
Expand Down Expand Up @@ -40,21 +42,49 @@ export function manifest(start: SolidStartOptions): PluginOption {
v => "isEntry" in v && v.isEntry,
);
if (!entry) throw new Error("No client entry found");
clientViteManifest = JSON.parse(
(globalThis.START_CLIENT_BUNDLE[".vite/manifest.json"] as any).source,
);
let rawManifest: string | undefined;

const viteMajor = parseInt(viteVersion.split('.')[0]!, 10);

const manifestKey = Object.keys(globalThis.START_CLIENT_BUNDLE).find(k => k.endsWith("manifest.json"));
if (manifestKey && viteMajor < 8) {
const manifestAsset = globalThis.START_CLIENT_BUNDLE[manifestKey] as any;
rawManifest = manifestAsset.source as string;
} else {
try {
const appRoot = (start as any).appRoot || "./src";
let outDir = ".solid-start/client";
if (devServer?.environments?.client?.config?.build?.outDir) {
outDir = devServer.environments.client.config.build.outDir;
} else if (this.environment?.config?.build?.outDir && this.environment?.config?.consumer === "client") {
outDir = this.environment.config.build.outDir;
} else if ((globalThis as any).START_CLIENT_OUT_DIR) {
outDir = (globalThis as any).START_CLIENT_OUT_DIR;
}
const manifestPath = path.resolve(appRoot, "..", outDir, ".vite/manifest.json");
rawManifest = fs.readFileSync(manifestPath, "utf-8");
} catch (e) {
throw new Error(`Manifest asset not found in bundle and could not be read from disk. Keys: ${Object.keys(globalThis.START_CLIENT_BUNDLE).join(", ")}. Error: ${e}`);
}
}

if (!rawManifest) {
throw new Error("Failed to extract or read raw manifest.");
}

clientViteManifest = JSON.parse(rawManifest);
}
return `export const clientViteManifest = ${JSON.stringify(clientViteManifest)};`;
} else if (id === `\0${VIRTUAL_MODULES.middleware}`) return "export default {};";
else if (id.startsWith("/@manifest")) {
if (this.environment.mode !== "dev")
throw new Error("@manifest queries are only allowed in dev");

const [path, query] = id.split("?");
const [urlPath, query] = id.split("?");
const target = id.split("/")[2]!;
const params = new URLSearchParams(query);
if (!path || !query) return;
if (path.endsWith("assets")) {
if (!urlPath || !query) return;
if (urlPath.endsWith("assets")) {
const id = params.get("id");
if (!id) {
throw new Error("Missing id to get assets.");
Expand Down
Loading