From 7553b572b0fc88af28cd72ab6e02d8a9e20f1773 Mon Sep 17 00:00:00 2001 From: Daishi Kato Date: Sun, 29 Sep 2024 07:36:18 +0900 Subject: [PATCH] prefer getHonoContext to hono/context-storage (#914) at least for now. this reverts #891 and re-introduce #852 and #884. https://github.com/dai-shi/waku/pull/911#issuecomment-2380439350 --- docs/guides/cloudflare.mdx | 8 ++++---- examples/08_cookies/src/components/App.tsx | 4 ++-- packages/waku/src/cli.ts | 3 --- packages/waku/src/lib/builder/build.ts | 1 - packages/waku/src/lib/hono/runner.ts | 18 ++++++++++++++++-- .../waku/src/lib/middleware/dev-server-impl.ts | 1 - .../plugins/vite-plugin-deploy-aws-lambda.ts | 10 +--------- .../plugins/vite-plugin-deploy-cloudflare.ts | 9 +-------- .../src/lib/plugins/vite-plugin-deploy-deno.ts | 7 ------- .../lib/plugins/vite-plugin-deploy-netlify.ts | 13 +------------ .../lib/plugins/vite-plugin-deploy-vercel.ts | 13 +------------ packages/waku/src/unstable_hono.ts | 3 +-- 12 files changed, 27 insertions(+), 63 deletions(-) diff --git a/docs/guides/cloudflare.mdx b/docs/guides/cloudflare.mdx index 78622590f..df553b64d 100644 --- a/docs/guides/cloudflare.mdx +++ b/docs/guides/cloudflare.mdx @@ -36,13 +36,13 @@ You may also want to add `@cloudflare/workers-types` to your dev dependencies an Waku currently uses [Hono](https://hono.dev/) in the [advanced mode worker function](https://developers.cloudflare.com/pages/functions/advanced-mode/) it creates for Cloudflare Pages when you build your project. -Waku uses Hono's [context storage middleware](https://hono.dev/docs/middleware/builtin/context-storage) to make the [Hono context](https://hono.dev/docs/api/context) accessible from anywhere. You can access Cloudflare bindings and execution context from the Hono context: +Waku exposes the [Hono context](https://hono.dev/docs/api/context) with `getHonoContext`. You can access Cloudflare bindings and execution context from the Hono context: ```ts -import { getContext } from 'hono/context-storage'; +import { getHonoContext } from 'waku/unstable_hono'; const getData = async () => { - const c = getContext<{ Bindings: Env }>(); + const c = getHonoContext<{ Bindings: Env }>(); if (!c) { return null; } @@ -76,7 +76,7 @@ You can access static assets from your server code. For example, if you want to ```ts const get404Html = async () => { - const c = getContext<{ Bindings: Env }>(); + const c = getHonoContext<{ Bindings: Env }>(); return c.env.ASSETS ? await (await c.env.ASSETS.fetch('https://example.com/404.html')).text() : ''; diff --git a/examples/08_cookies/src/components/App.tsx b/examples/08_cookies/src/components/App.tsx index d75ad1597..24d50395f 100644 --- a/examples/08_cookies/src/components/App.tsx +++ b/examples/08_cookies/src/components/App.tsx @@ -1,6 +1,6 @@ import { Suspense, cache } from 'react'; import { unstable_getCustomContext as getCustomContext } from 'waku/server'; -import { getContext } from 'hono/context-storage'; +import { getHonoContext } from 'waku/unstable_hono'; import { Counter } from './Counter'; @@ -15,7 +15,7 @@ const InternalAsyncComponent = async () => { } // console.log(getCustomContext()); // fails when it's sent to the browser console.log('waku context', Object.keys(getCustomContext())); - console.log('hono context', Object.keys(getContext())); + console.log('hono context', Object.keys(getHonoContext())); return null; }; diff --git a/packages/waku/src/cli.ts b/packages/waku/src/cli.ts index b52edf0cd..1cd93b7ad 100644 --- a/packages/waku/src/cli.ts +++ b/packages/waku/src/cli.ts @@ -5,7 +5,6 @@ import { parseArgs } from 'node:util'; import { createRequire } from 'node:module'; import { Hono } from 'hono'; import { compress } from 'hono/compress'; -import { contextStorage } from 'hono/context-storage'; import { serve } from '@hono/node-server'; import { serveStatic } from '@hono/node-server/serve-static'; import * as dotenv from 'dotenv'; @@ -101,7 +100,6 @@ async function runDev() { const config = await loadConfig(); const honoEnhancer = config.unstable_honoEnhancer || ((app) => app); const app = new Hono(); - app.use(contextStorage()); if (values['experimental-compress']) { app.use(compress()); } @@ -150,7 +148,6 @@ async function runStart() { const loadEntries = () => import(pathToFileURL(path.resolve(distDir, DIST_ENTRIES_JS)).toString()); const app = new Hono(); - app.use(contextStorage()); if (values['experimental-compress']) { app.use(compress()); } diff --git a/packages/waku/src/lib/builder/build.ts b/packages/waku/src/lib/builder/build.ts index 8c6ee8ac0..dda65be6d 100644 --- a/packages/waku/src/lib/builder/build.ts +++ b/packages/waku/src/lib/builder/build.ts @@ -246,7 +246,6 @@ const buildServerBundle = async ( conditions: ['react-server'], externalConditions: ['react-server'], }, - external: ['hono/context-storage'], noExternal: /^(?!node:)/, }, esbuild: { diff --git a/packages/waku/src/lib/hono/runner.ts b/packages/waku/src/lib/hono/runner.ts index 08cf89c8c..f37aedb15 100644 --- a/packages/waku/src/lib/hono/runner.ts +++ b/packages/waku/src/lib/hono/runner.ts @@ -1,8 +1,12 @@ -import type { MiddlewareHandler } from 'hono'; +import type { Context, Env, MiddlewareHandler } from 'hono'; +import { unstable_getCustomContext } from '../../server.js'; import { resolveConfig } from '../config.js'; import type { HandlerContext, MiddlewareOptions } from '../middleware/types.js'; +// Internal context key +const HONO_CONTEXT = '__hono_context'; + const createEmptyReadableStream = () => new ReadableStream({ start(controller) { @@ -38,7 +42,9 @@ export const runner = (options: MiddlewareOptions): MiddlewareHandler => { headers: c.req.header(), }, res: {}, - context: {}, + context: { + [HONO_CONTEXT]: c, + }, }; const handlers = await handlersPromise; const run = async (index: number) => { @@ -64,3 +70,11 @@ export const runner = (options: MiddlewareOptions): MiddlewareHandler => { await next(); }; }; + +export const getHonoContext = () => { + const c = unstable_getCustomContext()[HONO_CONTEXT]; + if (!c) { + throw new Error('Hono context is not available'); + } + return c as Context; +}; diff --git a/packages/waku/src/lib/middleware/dev-server-impl.ts b/packages/waku/src/lib/middleware/dev-server-impl.ts index f0003abc5..3020e0648 100644 --- a/packages/waku/src/lib/middleware/dev-server-impl.ts +++ b/packages/waku/src/lib/middleware/dev-server-impl.ts @@ -244,7 +244,6 @@ const createRscViteServer = ( conditions: ['react-server'], externalConditions: ['react-server'], }, - external: ['hono/context-storage'], noExternal: /^(?!node:)/, optimizeDeps: { include: [ diff --git a/packages/waku/src/lib/plugins/vite-plugin-deploy-aws-lambda.ts b/packages/waku/src/lib/plugins/vite-plugin-deploy-aws-lambda.ts index 3d7eb779e..cddcf08c3 100644 --- a/packages/waku/src/lib/plugins/vite-plugin-deploy-aws-lambda.ts +++ b/packages/waku/src/lib/plugins/vite-plugin-deploy-aws-lambda.ts @@ -17,10 +17,9 @@ const getServeJsContent = ( ) => ` import path from 'node:path'; import { existsSync, readFileSync } from 'node:fs'; -import { runner, importHono, importHonoContextStorage, importHonoNodeServerServeStatic, importHonoAwsLambda } from 'waku/unstable_hono'; +import { runner, importHono, importHonoNodeServerServeStatic, importHonoAwsLambda } from 'waku/unstable_hono'; const { Hono } = await importHono(); -const { contextStorage } = await importHonoContextStorage(); const { serveStatic } = await importHonoNodeServerServeStatic(); const { ${lambdaStreaming ? 'streamHandle:' : ''}handle } = await importHonoAwsLambda(); @@ -29,7 +28,6 @@ const publicDir = '${distPublic}'; const loadEntries = () => import('${srcEntriesFile}'); const app = new Hono(); -app.use(contextStorage()); app.use('*', serveStatic({ root: distDir + '/' + publicDir })); app.use('*', runner({ cmd: 'start', loadEntries, env: process.env })); app.notFound(async (c) => { @@ -63,12 +61,6 @@ export function deployAwsLambdaPlugin(opts: { }, configResolved(config) { entriesFile = `${config.root}/${opts.srcDir}/${SRC_ENTRIES}`; - const { deploy } = platformObject.buildOptions || {}; - if (deploy === 'aws-lambda' && Array.isArray(config.ssr.external)) { - config.ssr.external = config.ssr.external.filter( - (item) => item !== 'hono/context-storage', - ); - } }, resolveId(source) { if (source === `${opts.srcDir}/${SERVE_JS}`) { diff --git a/packages/waku/src/lib/plugins/vite-plugin-deploy-cloudflare.ts b/packages/waku/src/lib/plugins/vite-plugin-deploy-cloudflare.ts index 077a6c201..2e39fcc44 100644 --- a/packages/waku/src/lib/plugins/vite-plugin-deploy-cloudflare.ts +++ b/packages/waku/src/lib/plugins/vite-plugin-deploy-cloudflare.ts @@ -17,16 +17,14 @@ import { DIST_ENTRIES_JS, DIST_PUBLIC } from '../builder/constants.js'; const SERVE_JS = 'serve-cloudflare.js'; const getServeJsContent = (srcEntriesFile: string) => ` -import { runner, importHono, importHonoContextStorage } from 'waku/unstable_hono'; +import { runner, importHono } from 'waku/unstable_hono'; const { Hono } = await importHono(); -const { contextStorage } = await importHonoContextStorage(); const loadEntries = () => import('${srcEntriesFile}'); let serveWaku; const app = new Hono(); -app.use(contextStorage()); app.use('*', (c, next) => serveWaku(c, next)); app.notFound(async (c) => { const assetsFetcher = c.env.ASSETS; @@ -95,11 +93,6 @@ export function deployCloudflarePlugin(opts: { rootDir = config.root; entriesFile = `${rootDir}/${opts.srcDir}/${SRC_ENTRIES}`; const { deploy, unstable_phase } = platformObject.buildOptions || {}; - if (deploy === 'cloudflare' && Array.isArray(config.ssr.external)) { - config.ssr.external = config.ssr.external.filter( - (item) => item !== 'hono/context-storage', - ); - } if ( (unstable_phase !== 'buildServerBundle' && unstable_phase !== 'buildSsrBundle') || diff --git a/packages/waku/src/lib/plugins/vite-plugin-deploy-deno.ts b/packages/waku/src/lib/plugins/vite-plugin-deploy-deno.ts index e103346cb..40eb68602 100644 --- a/packages/waku/src/lib/plugins/vite-plugin-deploy-deno.ts +++ b/packages/waku/src/lib/plugins/vite-plugin-deploy-deno.ts @@ -13,7 +13,6 @@ const getServeJsContent = ( ) => ` import { Hono } from 'jsr:@hono/hono'; import { serveStatic } from 'jsr:@hono/hono/deno'; -import { contextStorage } from 'jsr:@hono/hono/context-storage'; import { runner } from 'waku/unstable_hono'; const distDir = '${distDir}'; @@ -22,7 +21,6 @@ const loadEntries = () => import('${srcEntriesFile}'); const env = Deno.env.toObject(); const app = new Hono(); -app.use(contextStorage()); app.use('*', serveStatic({ root: distDir + '/' + publicDir })); app.use('*', runner({ cmd: 'start', loadEntries, env })); app.notFound(async (c) => { @@ -61,11 +59,6 @@ export function deployDenoPlugin(opts: { configResolved(config) { entriesFile = `${config.root}/${opts.srcDir}/${SRC_ENTRIES}`; const { deploy, unstable_phase } = platformObject.buildOptions || {}; - if (deploy === 'deno' && Array.isArray(config.ssr.external)) { - config.ssr.external = config.ssr.external.filter( - (item) => item !== 'hono/context-storage', - ); - } if ( (unstable_phase !== 'buildServerBundle' && unstable_phase !== 'buildSsrBundle') || diff --git a/packages/waku/src/lib/plugins/vite-plugin-deploy-netlify.ts b/packages/waku/src/lib/plugins/vite-plugin-deploy-netlify.ts index 18c1b7237..10e82e1e5 100644 --- a/packages/waku/src/lib/plugins/vite-plugin-deploy-netlify.ts +++ b/packages/waku/src/lib/plugins/vite-plugin-deploy-netlify.ts @@ -9,15 +9,13 @@ import { DIST_PUBLIC } from '../builder/constants.js'; const SERVE_JS = 'serve-netlify.js'; const getServeJsContent = (srcEntriesFile: string) => ` -import { runner, importHono, importHonoContextStorage } from 'waku/unstable_hono'; +import { runner, importHono } from 'waku/unstable_hono'; const { Hono } = await importHono(); -const { contextStorage } = await importHonoContextStorage(); const loadEntries = () => import('${srcEntriesFile}'); const app = new Hono(); -app.use(contextStorage()); app.use('*', runner({ cmd: 'start', loadEntries, env: process.env })); app.notFound((c) => { const notFoundHtml = globalThis.__WAKU_NOT_FOUND_HTML__; @@ -56,15 +54,6 @@ export function deployNetlifyPlugin(opts: { configResolved(config) { rootDir = config.root; entriesFile = `${rootDir}/${opts.srcDir}/${SRC_ENTRIES}`; - const { deploy } = platformObject.buildOptions || {}; - if ( - deploy === 'netlify-functions' && - Array.isArray(config.ssr.external) - ) { - config.ssr.external = config.ssr.external.filter( - (item) => item !== 'hono/context-storage', - ); - } }, resolveId(source) { if (source === `${opts.srcDir}/${SERVE_JS}`) { diff --git a/packages/waku/src/lib/plugins/vite-plugin-deploy-vercel.ts b/packages/waku/src/lib/plugins/vite-plugin-deploy-vercel.ts index 1ebef3d87..a259201bb 100644 --- a/packages/waku/src/lib/plugins/vite-plugin-deploy-vercel.ts +++ b/packages/waku/src/lib/plugins/vite-plugin-deploy-vercel.ts @@ -15,10 +15,9 @@ const getServeJsContent = ( ) => ` import path from 'node:path'; import { existsSync, readFileSync } from 'node:fs'; -import { runner, importHono, importHonoContextStorage, importHonoNodeServer } from 'waku/unstable_hono'; +import { runner, importHono, importHonoNodeServer } from 'waku/unstable_hono'; const { Hono } = await importHono(); -const { contextStorage } = await importHonoContextStorage(); const { getRequestListener } = await importHonoNodeServer(); const distDir = '${distDir}'; @@ -26,7 +25,6 @@ const publicDir = '${distPublic}'; const loadEntries = () => import('${srcEntriesFile}'); const app = new Hono(); -app.use(contextStorage()); app.use('*', runner({ cmd: 'start', loadEntries, env: process.env })); app.notFound((c) => { // FIXME better implementation using node stream? @@ -68,15 +66,6 @@ export function deployVercelPlugin(opts: { configResolved(config) { rootDir = config.root; entriesFile = `${rootDir}/${opts.srcDir}/${SRC_ENTRIES}`; - const { deploy } = platformObject.buildOptions || {}; - if ( - deploy === 'vercel-serverless' && - Array.isArray(config.ssr.external) - ) { - config.ssr.external = config.ssr.external.filter( - (item) => item !== 'hono/context-storage', - ); - } }, resolveId(source) { if (source === `${opts.srcDir}/${SERVE_JS}`) { diff --git a/packages/waku/src/unstable_hono.ts b/packages/waku/src/unstable_hono.ts index 1663b81f8..2c0d42f85 100644 --- a/packages/waku/src/unstable_hono.ts +++ b/packages/waku/src/unstable_hono.ts @@ -1,9 +1,8 @@ // These exports are for internal use only and subject to change without notice. -export { runner } from './lib/hono/runner.js'; +export { runner, getHonoContext } from './lib/hono/runner.js'; export const importHono = () => import('hono'); -export const importHonoContextStorage = () => import('hono/context-storage'); export const importHonoNodeServer: any = () => import('@hono/node-server'); export const importHonoNodeServerServeStatic = () => import('@hono/node-server/serve-static');