Skip to content

Commit

Permalink
refactor: simplify custom serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa committed Apr 15, 2024
1 parent 64d4c14 commit b9a7fce
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 33 deletions.
5 changes: 5 additions & 0 deletions examples/react-ssr-workerd/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export default defineConfig((_env) => ({
"react/jsx-runtime",
"react/jsx-dev-runtime",
"react-dom/server.edge",
// [feedback]: esm also needs to be optimized? otherwise I get a following error:
// Error: Vite Internal Error: registerMissingImport is not supported in dev workerd
// at Object.registerMissingImport (file:///home/hiroshi/code/personal/vite-environment-examples/node_modules/.pnpm/[email protected]_@[email protected]/node_modules/vite/dist/node/chunks/dep-gq9_cnPm.js:57557:19)
"seroval",
"seroval-plugins/web",
],
},
},
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
"lint": "prettier -w --cache .",
"lint-check": "prettier -c --cache ."
},
"dependencies": {
"miniflare": "^3.20240404.0",
"seroval": "^1.0.5",
"seroval-plugins": "^1.0.5",
"vite": "6.0.0-alpha.1"
},
"devDependencies": {
"@hattip/adapter-node": "^0.0.44",
"@hiogawa/utils": "1.6.4-pre.1",
Expand All @@ -17,12 +23,10 @@
"@types/node": "^20.11.30",
"@vitejs/plugin-react": "^4.2.1",
"esbuild": "^0.20.2",
"miniflare": "^3.20240404.0",
"prettier": "^3.2.5",
"tsup": "^8.0.2",
"tsx": "^4.7.1",
"typescript": "^5.4.3",
"vite": "6.0.0-alpha.1"
"typescript": "^5.4.3"
},
"packageManager": "[email protected]+sha256.4b4efa12490e5055d59b9b9fc9438b7d581a6b7af3b5675eb5c5f447cee1a589",
"volta": {
Expand Down
49 changes: 39 additions & 10 deletions packages/workerd/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
RUNNER_EVAL_PATH,
type EvalApi,
type EvalMetadata,
jsonEvalSerializer,
} from "./shared";
import {
DevEnvironment,
Expand Down Expand Up @@ -66,6 +65,17 @@ export function vitePluginWorkerd(pluginOptions: WorkerdPluginOptions): Plugin {

// implement dispatchFetch based on eval
const dispatchFetch = async (request: Request): Promise<Response> => {
// TODO: serializer can setup outside?
const seroval = await import("seroval");
const serovalPlugins = await import("seroval-plugins/web");

if (0) {
const requestEncoded = await seroval.toJSONAsync(request, {
plugins: [serovalPlugins.RequestPlugin],
});
requestEncoded;
}

const result = await devEnv.api.eval({
entry,
data: {
Expand All @@ -76,7 +86,19 @@ export function vitePluginWorkerd(pluginOptions: WorkerdPluginOptions): Plugin {
? null
: await request.text(),
},
fn: async ({ mod, data: { url, method, headers, body }, env }) => {
fn: async ({
mod,
data: { url, method, headers, body },
env,
runner,
}) => {
const seroval = await runner.import("seroval");
const serovalPlugins = await runner.import("seroval-plugins/web");
if (0) {
console.log(seroval);
console.log(serovalPlugins);
}

const request = new Request(url, { method, headers, body });
const response: Response = await mod.default.fetch(request, env);
return {
Expand Down Expand Up @@ -143,8 +165,13 @@ export async function createWorkerdDevEnvironment(
const devEnv = server.environments["workerd"];
tinyassert(devEnv);
const args = await request.json();
const result = await devEnv.fetchModule(...(args as [any, any]));
return new MiniflareResponse(JSON.stringify(result));
try {
const result = await devEnv.fetchModule(...(args as [any, any]));
return new MiniflareResponse(JSON.stringify(result));
} catch (e) {
console.error(e);
throw e;
}
},
},
bindings: {
Expand Down Expand Up @@ -241,10 +268,11 @@ export async function createWorkerdDevEnvironment(
const meta: EvalMetadata = {
entry: ctx.entry,
fnString: ctx.fn.toString(),
serializerEntry: ctx.serializerEntry,
cusotmSerialize: ctx.cusotmSerialize,
};
const serde = ctx.serializer ?? jsonEvalSerializer();
const body = await serde.serialize(ctx.data);
const body: any = meta.cusotmSerialize
? ctx.data
: JSON.stringify(ctx.data as any);
const fetch_ = runnerObject.fetch as any as typeof fetch; // fix web/undici types
const response = await fetch_(ANY_URL + RUNNER_EVAL_PATH, {
method: "POST",
Expand All @@ -256,9 +284,10 @@ export async function createWorkerdDevEnvironment(
duplex: "half",
});
tinyassert(response.ok);
tinyassert(response.body);
const result = await serde.deserialize(response.body);
return result;
const result = meta.cusotmSerialize
? response.body
: await response.json();
return result as any;
},
};

Expand Down
8 changes: 4 additions & 4 deletions packages/workerd/src/shared.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { tinyassert } from "@hiogawa/utils";
import type { ModuleRunner } from "vite/module-runner";

export const RUNNER_INIT_PATH = "/__viteInit";
export const RUNNER_EVAL_PATH = "/__viteEval";
Expand Down Expand Up @@ -35,25 +36,24 @@ export function getRunnerFetchOptions(headers: Headers): RunnerFetchOptions {
return JSON.parse(decodeURIComponent(raw));
}

// TODO: infer Args and Return
export type EvalFn<In = any, Out = any> = (ctx: {
mod: any;
data: In;
env: any;
runner: ModuleRunner;
}) => Promise<Out> | Out;

export type EvalApi = <In = any, Out = any>(request: {
entry: string;
fn: EvalFn<In, Out>;
data: In;
serializerEntry?: string;
serializer?: EvalSerializer;
cusotmSerialize?: boolean;
}) => Promise<Awaited<Out>>;

export type EvalMetadata = {
entry: string;
fnString: string;
serializerEntry?: string;
cusotmSerialize?: boolean;
};

export type EvalSerializer = {
Expand Down
12 changes: 3 additions & 9 deletions packages/workerd/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
RUNNER_EVAL_PATH,
type EvalMetadata,
type EvalFn,
jsonEvalSerializer,
} from "./shared";
import { ModuleRunner } from "vite/module-runner";

Expand Down Expand Up @@ -49,18 +48,13 @@ export class RunnerObject implements DurableObject {
tinyassert(metaRaw);
const meta = JSON.parse(metaRaw) as EvalMetadata;
const mod = await this.#runner.import(meta.entry);
let serde = jsonEvalSerializer();
if (meta.serializerEntry) {
serde = await this.#runner.import(meta.serializerEntry);
}
tinyassert(request.body);
const data = await serde.deserialize(request.body);
const data = meta.cusotmSerialize ? request.body : await request.json();
const env = objectPickBy(this.#env, (_v, k) => !k.startsWith("__vite"));
const fn: EvalFn = this.#env.__viteUnsafeEval.eval(
`() => ${meta.fnString}`,
)();
const result = await fn({ mod, data, env });
const body = await serde.serialize(result);
const result = await fn({ mod, data, env, runner: this.#runner });
const body = meta.cusotmSerialize ? result : JSON.stringify(result);
return new Response(body);
}

Expand Down
1 change: 0 additions & 1 deletion packages/workerd/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ export default [
format: ["esm"],
platform: "node",
dts: true,
external: ["vite", "miniflare"],
}),
];
Loading

0 comments on commit b9a7fce

Please sign in to comment.