From b9a7fce95a2493efc434d352174bc7793cb54ede Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 15 Apr 2024 15:50:18 +0900 Subject: [PATCH] refactor: simplify custom serialization --- examples/react-ssr-workerd/vite.config.ts | 5 ++ package.json | 10 ++-- packages/workerd/src/plugin.ts | 49 ++++++++++++++---- packages/workerd/src/shared.ts | 8 +-- packages/workerd/src/worker.ts | 12 ++--- packages/workerd/tsup.config.ts | 1 - pnpm-lock.yaml | 61 ++++++++++++++++++++--- 7 files changed, 113 insertions(+), 33 deletions(-) diff --git a/examples/react-ssr-workerd/vite.config.ts b/examples/react-ssr-workerd/vite.config.ts index c20f473b..fe6c257d 100644 --- a/examples/react-ssr-workerd/vite.config.ts +++ b/examples/react-ssr-workerd/vite.config.ts @@ -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/vite@6.0.0-alpha.1_@types+node@20.11.30/node_modules/vite/dist/node/chunks/dep-gq9_cnPm.js:57557:19) + "seroval", + "seroval-plugins/web", ], }, }, diff --git a/package.json b/package.json index 5f7035cd..234e3e2c 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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": "pnpm@8.15.5+sha256.4b4efa12490e5055d59b9b9fc9438b7d581a6b7af3b5675eb5c5f447cee1a589", "volta": { diff --git a/packages/workerd/src/plugin.ts b/packages/workerd/src/plugin.ts index 68437c58..cac92652 100644 --- a/packages/workerd/src/plugin.ts +++ b/packages/workerd/src/plugin.ts @@ -14,7 +14,6 @@ import { RUNNER_EVAL_PATH, type EvalApi, type EvalMetadata, - jsonEvalSerializer, } from "./shared"; import { DevEnvironment, @@ -66,6 +65,17 @@ export function vitePluginWorkerd(pluginOptions: WorkerdPluginOptions): Plugin { // implement dispatchFetch based on eval const dispatchFetch = async (request: Request): Promise => { + // 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: { @@ -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 { @@ -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: { @@ -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", @@ -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; }, }; diff --git a/packages/workerd/src/shared.ts b/packages/workerd/src/shared.ts index 8ed070d8..dff9181c 100644 --- a/packages/workerd/src/shared.ts +++ b/packages/workerd/src/shared.ts @@ -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"; @@ -35,25 +36,24 @@ export function getRunnerFetchOptions(headers: Headers): RunnerFetchOptions { return JSON.parse(decodeURIComponent(raw)); } -// TODO: infer Args and Return export type EvalFn = (ctx: { mod: any; data: In; env: any; + runner: ModuleRunner; }) => Promise | Out; export type EvalApi = (request: { entry: string; fn: EvalFn; data: In; - serializerEntry?: string; - serializer?: EvalSerializer; + cusotmSerialize?: boolean; }) => Promise>; export type EvalMetadata = { entry: string; fnString: string; - serializerEntry?: string; + cusotmSerialize?: boolean; }; export type EvalSerializer = { diff --git a/packages/workerd/src/worker.ts b/packages/workerd/src/worker.ts index 8357236a..ad8ab5f2 100644 --- a/packages/workerd/src/worker.ts +++ b/packages/workerd/src/worker.ts @@ -7,7 +7,6 @@ import { RUNNER_EVAL_PATH, type EvalMetadata, type EvalFn, - jsonEvalSerializer, } from "./shared"; import { ModuleRunner } from "vite/module-runner"; @@ -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); } diff --git a/packages/workerd/tsup.config.ts b/packages/workerd/tsup.config.ts index ceaf57f5..8748be8d 100644 --- a/packages/workerd/tsup.config.ts +++ b/packages/workerd/tsup.config.ts @@ -12,6 +12,5 @@ export default [ format: ["esm"], platform: "node", dts: true, - external: ["vite", "miniflare"], }), ]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f38273aa..a2bc4420 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,19 @@ overrides: importers: .: + dependencies: + miniflare: + specifier: ^3.20240404.0 + version: 3.20240404.0 + seroval: + specifier: ^1.0.5 + version: 1.0.5 + seroval-plugins: + specifier: ^1.0.5 + version: 1.0.5(seroval@1.0.5) + vite: + specifier: 6.0.0-alpha.1 + version: 6.0.0-alpha.1(@types/node@20.11.30) devDependencies: '@hattip/adapter-node': specifier: ^0.0.44 @@ -32,9 +45,6 @@ importers: esbuild: specifier: ^0.20.2 version: 0.20.2 - miniflare: - specifier: ^3.20240404.0 - version: 3.20240404.0 prettier: specifier: ^3.2.5 version: 3.2.5 @@ -47,9 +57,6 @@ importers: typescript: specifier: ^5.4.3 version: 5.4.3 - vite: - specifier: 6.0.0-alpha.1 - version: 6.0.0-alpha.1(@types/node@20.11.30) examples/custom: dependencies: @@ -388,6 +395,7 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true + dev: false optional: true /@cloudflare/workerd-darwin-arm64@1.20240404.0: @@ -396,6 +404,7 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true + dev: false optional: true /@cloudflare/workerd-linux-64@1.20240404.0: @@ -404,6 +413,7 @@ packages: cpu: [x64] os: [linux] requiresBuild: true + dev: false optional: true /@cloudflare/workerd-linux-arm64@1.20240404.0: @@ -412,6 +422,7 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true + dev: false optional: true /@cloudflare/workerd-windows-64@1.20240404.0: @@ -420,6 +431,7 @@ packages: cpu: [x64] os: [win32] requiresBuild: true + dev: false optional: true /@cloudflare/workers-types@4.20240405.0: @@ -430,6 +442,7 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/trace-mapping': 0.3.9 + dev: false /@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19): resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} @@ -1041,6 +1054,7 @@ packages: /@fastify/busboy@2.1.1: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} + dev: false /@hattip/adapter-node@0.0.44: resolution: {integrity: sha512-Qf0kcrE4yHFrmKgfntrxHGNkk0/9a45aKmAO3ex6OiRKat5DZCFDdFMHV85Z594IohzT7Q+WcWiHQl/b0Jvo7Q==} @@ -1130,6 +1144,7 @@ packages: dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 + dev: false /@kamilkisiela/fast-url-parser@1.1.4: resolution: {integrity: sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==} @@ -1516,11 +1531,13 @@ packages: /acorn-walk@8.3.2: resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} engines: {node: '>=0.4.0'} + dev: false /acorn@8.11.3: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} hasBin: true + dev: false /ajv-keywords@3.5.2(ajv@6.12.6): resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} @@ -1588,6 +1605,7 @@ packages: resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} dependencies: printable-characters: 1.0.42 + dev: false /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1659,6 +1677,7 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - supports-color + dev: false /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1725,6 +1744,7 @@ packages: /cookie@0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} + dev: false /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} @@ -1741,6 +1761,7 @@ packages: /data-uri-to-buffer@2.0.2: resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} + dev: false /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} @@ -1944,6 +1965,7 @@ packages: /exit-hook@2.2.1: resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} engines: {node: '>=6'} + dev: false /fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} @@ -2023,6 +2045,7 @@ packages: dependencies: data-uri-to-buffer: 2.0.2 source-map: 0.6.1 + dev: false /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} @@ -2043,6 +2066,7 @@ packages: /glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: false /glob@10.3.12: resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} @@ -2295,6 +2319,7 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: false /minimatch@9.0.4: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} @@ -2314,6 +2339,7 @@ packages: /mustache@4.2.0: resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} hasBin: true + dev: false /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -2453,6 +2479,7 @@ packages: /printable-characters@1.0.42: resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + dev: false /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} @@ -2627,6 +2654,20 @@ packages: randombytes: 2.1.0 dev: false + /seroval-plugins@1.0.5(seroval@1.0.5): + resolution: {integrity: sha512-8+pDC1vOedPXjKG7oz8o+iiHrtF2WswaMQJ7CKFpccvSYfrzmvKY9zOJWCg+881722wIHfwkdnRmiiDm9ym+zQ==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + dependencies: + seroval: 1.0.5 + dev: false + + /seroval@1.0.5: + resolution: {integrity: sha512-TM+Z11tHHvQVQKeNlOUonOWnsNM+2IBwZ4vwoi4j3zKzIpc5IDw8WPwCfcc8F17wy6cBcJGbZbFOR0UCuTZHQA==} + engines: {node: '>=10'} + dev: false + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2667,6 +2708,7 @@ packages: /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + dev: false /source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} @@ -2685,10 +2727,12 @@ packages: dependencies: as-table: 1.0.55 get-source: 2.0.12 + dev: false /stoppable@1.1.0: resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} engines: {node: '>=4', npm: '>=6'} + dev: false /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} @@ -2912,6 +2956,7 @@ packages: engines: {node: '>=14.0'} dependencies: '@fastify/busboy': 2.1.1 + dev: false /update-browserslist-db@1.0.13(browserslist@4.23.0): resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} @@ -3052,6 +3097,7 @@ packages: '@cloudflare/workerd-linux-64': 1.20240404.0 '@cloudflare/workerd-linux-arm64': 1.20240404.0 '@cloudflare/workerd-windows-64': 1.20240404.0 + dev: false /wrangler@3.48.0(@cloudflare/workers-types@4.20240405.0): resolution: {integrity: sha512-Wv7JS6FyX1j9HkaM6WL3fmTzBMAYc4hPSyZCuxuH55hkJDX/7ts+YAgsaN1U8rKoDrV3FVSgBfI9TyqP9iuM8Q==} @@ -3115,6 +3161,7 @@ packages: optional: true utf-8-validate: optional: true + dev: false /xxhash-wasm@1.0.2: resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==} @@ -3136,6 +3183,8 @@ packages: cookie: 0.5.0 mustache: 4.2.0 stacktracey: 2.1.8 + dev: false /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false