diff --git a/packages/vike-node/src/runtime/handler-node-only.ts b/packages/vike-node/src/runtime/handler-node-only.ts index 03c91f1..ffef152 100644 --- a/packages/vike-node/src/runtime/handler-node-only.ts +++ b/packages/vike-node/src/runtime/handler-node-only.ts @@ -95,7 +95,7 @@ function handleViteDevServer(req: IncomingMessage, res: ServerResponse): Promise }) } -function resolveStaticConfig(static_: VikeOptions['static']): false | { root: string; cache: boolean } { +export function resolveStaticConfig(static_: VikeOptions['static']): false | { root: string; cache: boolean } { // Disable static file serving for Vercel // Vercel will serve static files on its own // See vercel.json > outputDirectory diff --git a/packages/vike-node/src/runtime/vike-handler.ts b/packages/vike-node/src/runtime/vike-handler.ts index 9af509c..bb40ed4 100644 --- a/packages/vike-node/src/runtime/vike-handler.ts +++ b/packages/vike-node/src/runtime/vike-handler.ts @@ -1,11 +1,12 @@ import { parseHeaders } from './utils/header-utils.js' import { renderPage as _renderPage } from 'vike/server' -import type { VikeHttpResponse, VikeOptions } from './types.js' +import type { ConnectMiddleware, VikeHttpResponse, VikeOptions } from './types.js' import type { Get, UniversalHandler } from '@universal-middleware/core' import { globalStore } from './globalStore.js' import { assert } from '../utils/assert.js' import type { IncomingMessage, ServerResponse } from 'http' import { connectToWebFallback } from './adapters/connectToWeb.js' +import { isVercel } from '../utils/isVercel.js' export { renderPage, renderPageWeb } @@ -55,8 +56,17 @@ async function renderPageWeb({ } export const renderPageUniversal = ((options?) => async (request, context, runtime: any) => { - if (runtime.req || runtime.env?.incoming) { - globalStore.setupHMRProxy(runtime.req ?? runtime.env?.incoming); + const nodeReq: IncomingMessage | undefined = runtime.req ?? runtime.env?.incoming + let staticConfig: false | { root: string; cache: boolean } = false + let shouldCache = false + const compressionType = options?.compress ?? !isVercel() + let staticMiddleware: ConnectMiddleware | undefined + + if (nodeReq) { + globalStore.setupHMRProxy(nodeReq) + const { resolveStaticConfig } = await import("./handler-node-only.js") + staticConfig = resolveStaticConfig(options?.static) + shouldCache = staticConfig && staticConfig.cache } if (globalStore.isPluginLoaded) { @@ -64,17 +74,32 @@ export const renderPageUniversal = ((options?) => async (request, context, runti // console.log({ url: request.url, handled: Boolean(handled) }) if (handled) return handled - } else { - // const isAsset = req.url?.startsWith('/assets/') - // const shouldCompressResponse = compressionType === true || (compressionType === 'static' && isAsset) + } else if (nodeReq) { + const isAsset = nodeReq.url?.startsWith('/assets/') + const shouldCompressResponse = compressionType === true || (compressionType === 'static' && isAsset) // if (shouldCompressResponse) { // await applyCompression(req, res, shouldCache) // } - // - // if (staticConfig) { - // const handled = await serveStaticFiles(req, res, staticConfig) - // if (handled) return true - // } + + if (staticConfig) { + const handled = await connectToWebFallback(serveStaticFiles)(request); + if (handled) return handled + } + } + + async function serveStaticFiles( + req: IncomingMessage, + res: ServerResponse + ): Promise { + if (!staticMiddleware) { + const { default: sirv } = await import('sirv') + staticMiddleware = sirv((staticConfig as { root: string; cache: boolean }).root, { etag: true }) + } + + return new Promise((resolve) => { + res.once('close', () => resolve(true)) + staticMiddleware!(req, res, () => resolve(false)) + }) } const pageContextInit = { ...context, ...runtime, urlOriginal: request.url, headersOriginal: request.headers } diff --git a/packages/vike-node/src/utils/assert.ts b/packages/vike-node/src/utils/assert.ts index 0a7ed34..3d74a2d 100644 --- a/packages/vike-node/src/utils/assert.ts +++ b/packages/vike-node/src/utils/assert.ts @@ -1,5 +1,3 @@ -import pc from '@brillout/picocolors' - export { assert, assertUsage } function assert(condition: unknown): asserts condition { @@ -9,5 +7,5 @@ function assert(condition: unknown): asserts condition { function assertUsage(condition: unknown, message: string): asserts condition { if (condition) return - throw new Error(`${pc.cyan('[vike-node]')} wrong usage: ${message}`) + throw new Error(`[vike-node] wrong usage: ${message}`) } diff --git a/packages/vike-node/tsup.config.js b/packages/vike-node/tsup.config.js index c73019a..cb1cd2d 100644 --- a/packages/vike-node/tsup.config.js +++ b/packages/vike-node/tsup.config.js @@ -16,7 +16,7 @@ export default defineConfig([ esbuildOptions(opts) { opts.outbase = "src"; }, - external: ["stream", "http", "node:stream", "node:http"], + external: ["stream", "http", "node:stream", "node:http", "path", "url"], dts: true, outDir: 'dist', bundle: true