Skip to content

Commit

Permalink
refactor: adopt @tanstack/server-functions-plugin (#1715)
Browse files Browse the repository at this point in the history
  • Loading branch information
brenelz authored Jan 27, 2025
1 parent f9f1ff7 commit 5a166a4
Show file tree
Hide file tree
Showing 5 changed files with 503 additions and 287 deletions.
5 changes: 5 additions & 0 deletions .changeset/violet-steaks-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solidjs/start": patch
---

Adopt tanstack server functions plugin
51 changes: 34 additions & 17 deletions packages/start/config/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { serverFunctions } from "@vinxi/server-functions/plugin";
import { server as serverFunctionServer, serverTransform } from "@vinxi/server-functions/server";
import { createTanStackServerFnPlugin } from "@tanstack/server-functions-plugin";
import defu from "defu";
import { existsSync } from "node:fs";
import { join } from "node:path";
Expand Down Expand Up @@ -38,6 +37,36 @@ function solidStartServerFsRouter(config) {
);
}

const SolidStartServerFnsPlugin = createTanStackServerFnPlugin({
// This is the ID that will be available to look up and import
// our server function manifest and resolve its module
manifestVirtualImportId: "solidstart:server-fn-manifest",
client: {
getRuntimeCode: () =>
`import { createServerReference } from "${normalize(
fileURLToPath(new URL("../dist/runtime/server-runtime.js", import.meta.url))
)}"`,
replacer: opts =>
`createServerReference(${() => {}}, '${opts.functionId}', '${opts.extractedFilename}')`
},
ssr: {
getRuntimeCode: () =>
`import { createServerReference } from '${normalize(
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)}'`,
replacer: opts =>
`createServerReference(${opts.fn}, '${opts.functionId}', '${opts.extractedFilename}')`
},
server: {
getRuntimeCode: () =>
`import { createServerReference } from '${normalize(
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)}'`,
replacer: opts =>
`createServerReference(${opts.fn}, '${opts.functionId}', '${opts.extractedFilename}')`
}
});

export function defineConfig(baseConfig = {}) {
let { vite = {}, ...start } = baseConfig;
const extensions = [...DEFAULT_EXTENSIONS, ...(start.extensions || [])];
Expand Down Expand Up @@ -112,11 +141,7 @@ export function defineConfig(baseConfig = {}) {
}
}),
...plugins,
serverTransform({
runtime: normalize(
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)
}),
SolidStartServerFnsPlugin.ssr,
start.experimental.islands ? serverComponents.server() : null,
solid({ ...start.solid, ssr: true, extensions: extensions.map(ext => `.${ext}`) }),
config("app-server", {
Expand Down Expand Up @@ -177,11 +202,7 @@ export function defineConfig(baseConfig = {}) {
}
}),
...plugins,
serverFunctions.client({
runtime: normalize(
fileURLToPath(new URL("../dist/runtime/server-runtime.js", import.meta.url))
)
}),
SolidStartServerFnsPlugin.client,
start.experimental.islands ? serverComponents.client() : null,
solid({ ...start.solid, ssr: start.ssr, extensions: extensions.map(ext => `.${ext}`) }),
config("app-client", {
Expand Down Expand Up @@ -247,11 +268,7 @@ export function defineConfig(baseConfig = {}) {
cacheDir: "node_modules/.vinxi/server-fns"
}),
...plugins,
serverFunctionServer({
runtime: normalize(
fileURLToPath(new URL("../dist/runtime/server-fns-runtime.js", import.meta.url))
)
}),
SolidStartServerFnsPlugin.server,
start.experimental.islands ? serverComponents.server() : null,
solid({ ...start.solid, ssr: true, extensions: extensions.map(ext => `.${ext}`) }),
config("app-server", {
Expand Down
2 changes: 1 addition & 1 deletion packages/start/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"dependencies": {
"@vinxi/plugin-directives": "^0.4.3",
"@vinxi/server-components": "^0.4.3",
"@vinxi/server-functions": "^0.4.3",
"@tanstack/server-functions-plugin": "^1.97.2",
"defu": "^6.1.2",
"error-stack-parser": "^2.1.4",
"html-to-image": "^1.11.11",
Expand Down
33 changes: 25 additions & 8 deletions packages/start/src/runtime/server-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { getExpectedRedirectStatus } from "../server/handler";
import { createPageEvent } from "../server/pageEvent";
// @ts-ignore
import { FetchEvent, PageEvent } from "../server";
// @ts-ignore
import serverFnManifest from "solidstart:server-fn-manifest";

function createChunk(data: string) {
const encodeData = new TextEncoder().encode(data);
Expand Down Expand Up @@ -78,19 +80,34 @@ async function handleServerFunction(h3Event: HTTPEvent) {
const instance = request.headers.get("X-Server-Instance");
const singleFlight = request.headers.has("X-Single-Flight");
const url = new URL(request.url);
let filepath: string | undefined | null, name: string | undefined | null;
let functionId: string | undefined | null, name: string | undefined | null;
if (serverReference) {
invariant(typeof serverReference === "string", "Invalid server function");
[filepath, name] = serverReference.split("#");
[functionId, name] = serverReference.split("#");
} else {
filepath = url.searchParams.get("id");
functionId = url.searchParams.get("id");
name = url.searchParams.get("name");
if (!filepath || !name) throw new Error("Invalid request");
if (!functionId || !name) throw new Error("Invalid request");
}

const serverFnInfo = serverFnManifest[functionId];
let fnModule: undefined | { [key: string]: any };


if (process.env.NODE_ENV === "development") {
// In dev, we use Vinxi to get the "server" server-side router
// Then we use that router's devServer.ssrLoadModule to get the serverFn

// This code comes from:
// https://github.com/TanStack/router/blob/266f5cc863cd1a99809d1af2669e58b6b6db9a67/packages/start-server-functions-handler/src/index.tsx#L83-L87
fnModule = await (globalThis as any).app
.getRouter("server-fns")
.internals.devServer.ssrLoadModule(serverFnInfo.extractedFilename);
} else {
fnModule = await serverFnInfo.importer();
}
const serverFunction = fnModule![serverFnInfo.functionName];

const serverFunction = (
await import.meta.env.MANIFEST[import.meta.env.ROUTER_NAME]!.chunks[filepath!]!.import()
)[name!];
let parsed: any[] = [];

// grab bound arguments from url when no JS
Expand Down Expand Up @@ -176,7 +193,7 @@ async function handleServerFunction(h3Event: HTTPEvent) {
/* @ts-ignore */
sharedConfig.context = { event };
event.locals.serverFunctionMeta = {
id: filepath + "#" + name
id: functionId + "#" + name
};
return serverFunction(...parsed);
});
Expand Down
Loading

0 comments on commit 5a166a4

Please sign in to comment.