diff --git a/examples/hono-react-cf-pages/package.json b/examples/hono-react-cf-pages/package.json
index 71ac52c..dfede21 100644
--- a/examples/hono-react-cf-pages/package.json
+++ b/examples/hono-react-cf-pages/package.json
@@ -19,7 +19,7 @@
},
"type": "module",
"devDependencies": {
- "vike-cloudflare": "^0.0.6",
+ "telefunc": "^0.1.76",
"wrangler": "^3.71.0"
}
}
diff --git a/examples/hono-react-cf-pages/pages/dynamic/+Page.jsx b/examples/hono-react-cf-pages/pages/dynamic/+Page.jsx
index 7f8d9f7..85b27bb 100644
--- a/examples/hono-react-cf-pages/pages/dynamic/+Page.jsx
+++ b/examples/hono-react-cf-pages/pages/dynamic/+Page.jsx
@@ -1,8 +1,12 @@
export default Page
import React, { useState } from 'react'
+import { useData } from 'vike-react/useData'
+import { getHello } from './page.telefunc'
function Page() {
+ const data = useData()
+
return (
<>
Welcome
@@ -11,8 +15,10 @@ function Page() {
Dynamic
No static html generated
Interactive
+ Server Rendered at: {data.d}
+
>
)
}
@@ -25,3 +31,12 @@ function Counter() {
)
}
+
+function TelefuncTest() {
+ const [response, setResponse] = useState()
+ return (
+
+ )
+}
diff --git a/examples/hono-react-cf-pages/pages/dynamic/+data.js b/examples/hono-react-cf-pages/pages/dynamic/+data.js
new file mode 100644
index 0000000..40568a6
--- /dev/null
+++ b/examples/hono-react-cf-pages/pages/dynamic/+data.js
@@ -0,0 +1,6 @@
+// https://vike.dev/onBeforeRender
+export default function data() {
+ return {
+ d: String(new Date())
+ }
+}
diff --git a/examples/hono-react-cf-pages/pages/dynamic/page.telefunc.js b/examples/hono-react-cf-pages/pages/dynamic/page.telefunc.js
new file mode 100644
index 0000000..d473172
--- /dev/null
+++ b/examples/hono-react-cf-pages/pages/dynamic/page.telefunc.js
@@ -0,0 +1,3 @@
+export async function getHello() {
+ return 'hello'
+}
diff --git a/examples/hono-react-cf-pages/server/app.js b/examples/hono-react-cf-pages/server/app.js
index 2fdfbd2..4ce89cb 100644
--- a/examples/hono-react-cf-pages/server/app.js
+++ b/examples/hono-react-cf-pages/server/app.js
@@ -1,7 +1,16 @@
import { Hono } from 'hono'
import vike from 'vike-node/hono'
+import { telefunc, config } from 'telefunc'
+config.disableNamingConvention = true
const app = new Hono()
+app.post('_telefunc', async (ctx) => {
+ const { url, method } = ctx.req
+ const body = await ctx.req.text()
+ const httpResponse = await telefunc({ url, method, body })
+ return new Response(httpResponse.body, {
+ status: httpResponse.statusCode
+ })
+})
app.use(vike())
export default app
-console.log('import.meta.env.SSR app', import.meta.env.SSR)
diff --git a/examples/hono-react-cf-pages/vite.config.js b/examples/hono-react-cf-pages/vite.config.js
index 2a72041..6bd4ac6 100644
--- a/examples/hono-react-cf-pages/vite.config.js
+++ b/examples/hono-react-cf-pages/vite.config.js
@@ -1,18 +1,22 @@
import react from '@vitejs/plugin-react'
-import vike from 'vike/plugin'
+import { telefunc } from 'telefunc/vite'
import vikeNode from 'vike-node/plugin'
-import { pages } from 'vike-cloudflare'
+import vike from 'vike/plugin'
export default {
plugins: [
- react(),
vike({ prerender: true }),
- vikeNode({ entry: 'server/node-entry.js' }),
- pages({
- server: {
- kind: 'hono',
- entry: 'server/app.js'
+ vikeNode({
+ entry: {
+ index: 'server/node-entry.js',
+ cloudflare: {
+ entry: 'server/app.js',
+ runtime: 'cloudflare',
+ scaffold: 'dist/cloudflare'
+ }
}
- })
+ }),
+ react(),
+ telefunc()
]
}
diff --git a/examples/hono-react-cf-pages/wrangler.toml b/examples/hono-react-cf-pages/wrangler.toml
index c092d8b..ea3cdf6 100644
--- a/examples/hono-react-cf-pages/wrangler.toml
+++ b/examples/hono-react-cf-pages/wrangler.toml
@@ -1,4 +1,3 @@
name = "vike-cloudflare-hono-demo"
compatibility_date = "2024-06-24"
-pages_build_output_dir = "./dist/cloudflare"
-compatibility_flags = [ "nodejs_compat" ]
\ No newline at end of file
+pages_build_output_dir = "./dist/cloudflare"
\ No newline at end of file
diff --git a/examples/hono-react-vercel-edge/vite.config.js b/examples/hono-react-vercel-edge/vite.config.js
index cdaad0a..7d8c786 100644
--- a/examples/hono-react-vercel-edge/vite.config.js
+++ b/examples/hono-react-vercel-edge/vite.config.js
@@ -5,6 +5,7 @@ import vike from 'vike/plugin'
export default {
plugins: [
+ vike({ prerender: true }),
vikeNode({
entry: {
index: 'server/node-entry.js',
@@ -14,7 +15,6 @@ export default {
}
}
}),
- vike({ prerender: true }),
react(),
telefunc()
]
diff --git a/packages/vike-node/src/plugin/constants.ts b/packages/vike-node/src/plugin/constants.ts
index b7422a6..512001a 100644
--- a/packages/vike-node/src/plugin/constants.ts
+++ b/packages/vike-node/src/plugin/constants.ts
@@ -1,3 +1,3 @@
import type { Runtime } from '../types.js'
-export const RUNTIMES: Runtime[] = ['node', 'nodeless', 'deno', 'cloudflare', 'vercel']
+export const RUNTIMES: Runtime[] = ['node', 'nodeless', 'deno', 'cloudflare', 'cloudflare-nodejs-compat', 'vercel']
diff --git a/packages/vike-node/src/plugin/plugins/devServerPlugin.ts b/packages/vike-node/src/plugin/plugins/devServerPlugin.ts
index 1a1e4fc..1be0827 100644
--- a/packages/vike-node/src/plugin/plugins/devServerPlugin.ts
+++ b/packages/vike-node/src/plugin/plugins/devServerPlugin.ts
@@ -91,7 +91,7 @@ export function devServerPlugin(): Plugin {
async function initializeServerEntry(vite: ViteDevServer) {
assert(resolvedConfig.server)
const { index } = resolvedConfig.server.entry
- const indexResolved = await vite.pluginContainer.resolveId(index.path)
+ const indexResolved = await vite.pluginContainer.resolveId(index.entry)
assert(indexResolved?.id)
entryAbs = indexResolved.id
vite.ssrLoadModule(entryAbs).catch(logRestartMessage)
diff --git a/packages/vike-node/src/plugin/plugins/edgePlugin.ts b/packages/vike-node/src/plugin/plugins/edgePlugin.ts
index 175adbb..5e17779 100644
--- a/packages/vike-node/src/plugin/plugins/edgePlugin.ts
+++ b/packages/vike-node/src/plugin/plugins/edgePlugin.ts
@@ -1,24 +1,48 @@
import esbuild from 'esbuild'
+import fs from 'fs/promises'
import { builtinModules } from 'module'
+import { gzip } from 'node:zlib'
import path from 'path'
+import { promisify } from 'util'
+import { prerender } from 'vike/prerender'
import type { Plugin, ResolvedConfig } from 'vite'
-import { ConfigVikeNodeResolved } from '../../types.js'
+import type { ConfigVikeNodeResolved, Runtime } from '../../types.js'
+import { assert } from '../../utils/assert.js'
+import { copyFileOrFolder } from '../utils/copyFileOrFolder.js'
import { toPosixPath } from '../utils/filesystemPathHandling.js'
import { getConfigVikeNode } from '../utils/getConfigVikeNode.js'
import { logVikeNode } from '../utils/logVikeNode.js'
import { unenvPlugin } from './esbuild/unenvPlugin.js'
+const compress = promisify(gzip)
+
+const DEFAULT_CONDITIONS = ['edge-light', 'workerd', 'worker', 'browser', 'module', 'import', 'require']
+
+type Entry = {
+ name: string
+ runtime: Runtime
+ path: string
+ scaffold: string | false
+}
+
+type EntryWithOutFile = Entry & {
+ outFile: string
+}
+
export function edgePlugin(): Plugin[] {
let viteConfig: ResolvedConfig
- let configResolvedVike: ConfigVikeNodeResolved
+ let configResolvedVikeNode: ConfigVikeNodeResolved
+ let configResolvedVike: any
let outDir: string
let outDirAbs: string
let root: string
+ let entries: Entry[]
+ let entriesWithOutFile: EntryWithOutFile[]
- const DEFAULT_CONDITIONS = ['edge-light', 'workerd', 'worker', 'browser', 'module', 'import', 'require']
+ return [createServePlugin(), createBuildPlugin(), createScaffoldPlugin()]
- return [
- {
+ function createServePlugin(): Plugin {
+ return {
name: 'vike-node:edge:serve',
apply: 'serve',
config() {
@@ -28,79 +52,172 @@ export function edgePlugin(): Plugin[] {
}
}
}
- },
- {
+ }
+ }
+
+ function createBuildPlugin(): Plugin {
+ return {
name: 'vike-node:edge:build',
+ enforce: 'pre',
apply(config) {
return !!config.build?.ssr
},
+ config(config) {
+ configResolvedVikeNode = getConfigVikeNode(config)
+ entries = getEntries(configResolvedVikeNode)
+
+ if (entries.length === 0) {
+ return null
+ }
+
+ return {
+ ssr: { target: 'webworker' },
+ build: {
+ rollupOptions: { external: [...builtinModules, /^node:/] },
+ target: 'es2022'
+ },
+ resolve: { conditions: DEFAULT_CONDITIONS }
+ }
+ },
configResolved(config) {
viteConfig = config
- configResolvedVike = getConfigVikeNode(config)
root = toPosixPath(config.root)
outDir = toPosixPath(config.build.outDir)
outDirAbs = path.posix.join(root, outDir)
+
+ // Now that outDirAbs is available, we can create entriesWithOutFile
+ entriesWithOutFile = entries.map((entry) => ({
+ ...entry,
+ outFile: path.posix.join(outDirAbs, `${entry.name}.mjs`)
+ }))
},
- config(config) {
- const resolvedConfig = getConfigVikeNode(config)
- const hasNodelessEntry = Object.values(resolvedConfig.server.entry).some((entry) => entry.runtime !== 'node')
- if (hasNodelessEntry) {
- // TODO: add unenv plugin
- return {
- ssr: {
- target: 'webworker'
- },
- build: {
- rollupOptions: {
- external: [...builtinModules, /^node:/]
- },
- target: 'es2022'
- },
- resolve: {
- // https://github.com/cloudflare/workers-sdk/blob/515de6ab40ed6154a2e6579ff90b14b304809609/packages/wrangler/src/deployment-bundle/bundle.ts#L37
- conditions: DEFAULT_CONDITIONS
- }
+ closeBundle: {
+ order: 'pre',
+ sequential: true,
+ handler: buildEntries
+ }
+ }
+ }
+
+ function createScaffoldPlugin(): Plugin {
+ return {
+ name: 'vike-node:edge:scaffold',
+ enforce: 'post',
+ apply(config) {
+ return !!config.build?.ssr
+ },
+ // @ts-ignore
+ config() {
+ if (!entries.length || entries.some((e) => !e.scaffold)) return
+ return {
+ vitePluginSsr: {
+ prerender: { disableAutoRun: true }
}
}
},
- async closeBundle() {
- const entries = Object.entries(configResolvedVike.server.entry)
- .filter(([_, entry]) => entry.runtime !== 'node')
- .map(([name, entry]) => ({
- name,
- runtime: entry.runtime,
- path: path.posix.join(root, entry.path)
- }))
-
- if (entries.length === 0) return
-
- for (const entry of entries) {
- await esbuild.build({
- entryPoints: [entry.path],
- outdir: outDirAbs,
- format: 'esm',
- target: 'es2022',
- bundle: true,
- minify: viteConfig.build.minify !== false,
- sourcemap: !!viteConfig.build.sourcemap,
- outExtension: { '.js': '.mjs' },
- allowOverwrite: true,
- external: configResolvedVike.server.external,
- define: {
- 'process.env.NODE_ENV': '"production"',
- 'import.meta.env.NODE_ENV': '"production"'
- },
- conditions: DEFAULT_CONDITIONS,
- logLevel: 'info',
- logOverride: {
- 'ignored-bare-import': 'verbose',
- 'require-resolve-not-external': 'verbose'
- },
- plugins: [unenvPlugin(entry.runtime)]
- })
- logVikeNode(`built entry: ${entry.name}`)
- }
+ async configResolved(config) {
+ // @ts-ignore
+ configResolvedVike = await config.configVikePromise
+ },
+ closeBundle: {
+ sequential: true,
+ order: 'post',
+ handler: scaffoldEntries
}
}
- ]
+ }
+
+ function getEntries(config: ConfigVikeNodeResolved): Entry[] {
+ return Object.entries(config.server.entry)
+ .filter(([_, entry]) => entry.runtime !== 'node')
+ .map(([name, entry]) => ({
+ name,
+ runtime: entry.runtime,
+ path: entry.entry,
+ scaffold: ('scaffold' in entry && entry.scaffold) || false
+ }))
+ }
+
+ async function buildEntries() {
+ if (entriesWithOutFile.length === 0) return
+
+ for (const entry of entriesWithOutFile) {
+ const result = await esbuild.build({
+ entryPoints: [path.posix.join(root, entry.path)],
+ outfile: entry.outFile,
+ format: 'esm',
+ target: 'es2022',
+ bundle: true,
+ minify: viteConfig.build.minify !== false,
+ sourcemap: !!viteConfig.build.sourcemap,
+ outExtension: { '.js': '.mjs' },
+ write: false,
+ external: configResolvedVikeNode.server.external,
+ define: {
+ 'process.env.NODE_ENV': '"production"',
+ 'import.meta.env.NODE_ENV': '"production"'
+ },
+ conditions: DEFAULT_CONDITIONS,
+ logLevel: 'info',
+ logOverride: {
+ 'ignored-bare-import': 'verbose',
+ 'require-resolve-not-external': 'verbose'
+ },
+ plugins: [unenvPlugin(entry.runtime)]
+ })
+
+ const content = result.outputFiles[0]!.contents
+ const zipped = await compress(content, { level: 9 })
+ logVikeNode(`built entry: ${entry.name}, gzip: ${(zipped.length / 1024).toFixed(2)} kB`)
+
+ await fs.mkdir(path.dirname(entry.outFile), { recursive: true }).catch(() => {})
+ await fs.writeFile(entry.outFile, content, 'utf-8')
+ }
+ }
+
+ async function scaffoldEntries() {
+ if (!entries.length || entries.some((e) => !e.scaffold)) return
+ const staticRoutes = configResolvedVike.prerender ? await prerenderPages() : []
+ const scaffoldableEntries = entriesWithOutFile.filter((e) => e.scaffold)
+
+ for (const entry of scaffoldableEntries) {
+ if (['cloudflare', 'cloudflare-nodejs-compat'].includes(entry.runtime)) {
+ await scaffoldCf(entry, staticRoutes)
+ }
+ }
+ }
+
+ async function prerenderPages(): Promise {
+ const staticRoutes: string[] = []
+ await prerender({
+ async onPagePrerender(page: any) {
+ const result = page._prerenderResult
+ const isJson = result.filePath.endsWith('.pageContext.json')
+ const route = isJson ? path.posix.join(page.urlOriginal, result.filePath.split('/').pop()) : page.urlOriginal
+ staticRoutes.push(route)
+
+ await fs.mkdir(path.dirname(result.filePath), { recursive: true }).catch(() => {})
+ await fs.writeFile(result.filePath, result.fileContent, 'utf-8')
+ }
+ })
+ return staticRoutes
+ }
+
+ async function scaffoldCf(entry: EntryWithOutFile, staticRoutes: string[]) {
+ assert(entry.scaffold)
+ await fs.rm(entry.scaffold, { recursive: true, force: true }).catch(() => {})
+ await copyFileOrFolder(entry.outFile, path.posix.join(entry.scaffold, '_worker.js'))
+ await copyFileOrFolder('./dist/client', entry.scaffold)
+
+ const routesJson = JSON.stringify(
+ {
+ version: 1,
+ include: ['/*'],
+ exclude: ['/assets/*', ...staticRoutes]
+ },
+ null,
+ 2
+ )
+ await fs.writeFile(path.posix.join(entry.scaffold, '_routes.json'), routesJson, 'utf-8')
+ }
}
diff --git a/packages/vike-node/src/plugin/plugins/esbuild/unenvPlugin.ts b/packages/vike-node/src/plugin/plugins/esbuild/unenvPlugin.ts
index a63b77b..49bebf0 100644
--- a/packages/vike-node/src/plugin/plugins/esbuild/unenvPlugin.ts
+++ b/packages/vike-node/src/plugin/plugins/esbuild/unenvPlugin.ts
@@ -15,10 +15,11 @@ function getEnv(runtime: Runtime) {
case 'node':
return env(node)
case 'nodeless':
+ case 'cloudflare':
return env(nodeless)
case 'deno':
return env(nodeless, deno)
- case 'cloudflare':
+ case 'cloudflare-nodejs-compat':
return env(nodeless, cloudflare)
case 'vercel':
return env(nodeless, vercel)
@@ -54,11 +55,11 @@ function replaceUnenv(value: T): T {
export function unenvPlugin(runtime: Runtime): Plugin {
const { alias, inject, external, polyfill } = replaceUnenv(getEnv(runtime))
- // already included in polyfill
+ // already included in polyfill / broken
delete inject.global
delete inject.process
delete inject.Buffer
- delete inject.performance
+ delete inject.console
return {
name: 'unenv',
@@ -67,6 +68,9 @@ export function unenvPlugin(runtime: Runtime): Plugin {
handleRequireCallsToNodeJSBuiltins(build)
handleAliasedNodeJSPackages(build, alias, external)
handleNodeJSGlobals(build, inject)
+ build.initialOptions.banner = {
+ js: 'globalThis.process ||= {};'
+ }
}
}
}
diff --git a/packages/vike-node/src/plugin/plugins/serverEntryPlugin.ts b/packages/vike-node/src/plugin/plugins/serverEntryPlugin.ts
index 529240d..3244cd6 100644
--- a/packages/vike-node/src/plugin/plugins/serverEntryPlugin.ts
+++ b/packages/vike-node/src/plugin/plugins/serverEntryPlugin.ts
@@ -20,15 +20,15 @@ export function serverEntryPlugin(): Plugin {
assert(entries.length > 0)
const resolvedEntries: EntryResolved = {
- index: { path: '', runtime: 'node' } // Initialize with a placeholder, will be overwritten
+ index: { entry: '', runtime: 'node' } // Initialize with a placeholder, will be overwritten
}
for (const [name, entryInfo] of entries) {
- const { path: entryPath, runtime } = entryInfo
+ const { entry: entryPath, runtime } = entryInfo
let entryFilePath = path.join(config.root, entryPath)
try {
resolvedEntries[name] = {
- path: require_.resolve(entryFilePath),
+ entry: require_.resolve(entryFilePath),
runtime
}
} catch (err) {
@@ -44,7 +44,7 @@ export function serverEntryPlugin(): Plugin {
if (viteIsSSR(config)) {
config.build.rollupOptions.input = injectRollupInputs(
- Object.fromEntries(Object.entries(resolvedEntries).map(([name, { path }]) => [name, path])),
+ Object.fromEntries(Object.entries(resolvedEntries).map(([name, { entry: path }]) => [name, path])),
config
)
}
diff --git a/packages/vike-node/src/plugin/plugins/standalonePlugin.ts b/packages/vike-node/src/plugin/plugins/standalonePlugin.ts
index 833b347..f9795bb 100644
--- a/packages/vike-node/src/plugin/plugins/standalonePlugin.ts
+++ b/packages/vike-node/src/plugin/plugins/standalonePlugin.ts
@@ -216,7 +216,7 @@ function findRollupBundleEntries entry.runtime === 'node')
- .map(([_, entry]) => path.posix.join(root, entry.path))
+ .map(([_, entry]) => path.posix.join(root, entry.entry))
const entries: OutputBundle[string][] = []
for (const key in bundle) {
diff --git a/packages/vike-node/src/plugin/utils/copyFileOrFolder.ts b/packages/vike-node/src/plugin/utils/copyFileOrFolder.ts
new file mode 100644
index 0000000..4752b54
--- /dev/null
+++ b/packages/vike-node/src/plugin/utils/copyFileOrFolder.ts
@@ -0,0 +1,29 @@
+export { copyFileOrFolder }
+
+import fs from 'fs/promises'
+import path from 'path'
+
+async function copyFileOrFolder(source: string, destination: string): Promise {
+ const stats = await fs.stat(source)
+
+ if (stats.isFile()) {
+ // Ensure the destination directory exists
+ await fs.mkdir(path.dirname(destination), { recursive: true }).catch(() => {}) // Ignore if directory already exists
+ await fs.copyFile(source, destination)
+ } else if (stats.isDirectory()) {
+ // Create the destination directory
+ await fs.mkdir(destination, { recursive: true }).catch(() => {}) // Ignore if directory already exists
+
+ // Read the contents of the source directory
+ const entries = await fs.readdir(source, { withFileTypes: true })
+
+ // Recursively copy each entry
+ for (const entry of entries) {
+ const srcPath = path.join(source, entry.name)
+ const destPath = path.join(destination, entry.name)
+ await copyFileOrFolder(srcPath, destPath)
+ }
+ } else {
+ throw new Error(`Unsupported file type: ${source}`)
+ }
+}
diff --git a/packages/vike-node/src/plugin/utils/resolveConfig.ts b/packages/vike-node/src/plugin/utils/resolveConfig.ts
index cd3e495..6ddf2a8 100644
--- a/packages/vike-node/src/plugin/utils/resolveConfig.ts
+++ b/packages/vike-node/src/plugin/utils/resolveConfig.ts
@@ -15,9 +15,9 @@ function resolveConfig(configVike: ConfigVikeNode): ConfigVikeNodeResolved {
(typeof configVike.server.entry === 'object' &&
Object.entries(configVike.server.entry).every(
([, value]) =>
- typeof value === 'string' || (typeof value === 'object' && 'path' in value && 'runtime' in value)
+ typeof value === 'string' || (typeof value === 'object' && 'entry' in value && 'runtime' in value)
)),
- 'server.entry should be a string or an entry mapping { name: string | { path: string, runtime: Runtime } }'
+ 'server.entry should be a string or an entry mapping { name: string | { entry: string, runtime: Runtime } }'
)
assertUsage(
typeof configVike.server.entry !== 'object' ||
@@ -28,7 +28,7 @@ function resolveConfig(configVike: ConfigVikeNode): ConfigVikeNodeResolved {
const entriesProvided: EntryResolved =
typeof configVike.server.entry === 'string'
- ? { index: { path: configVike.server.entry, runtime: 'node' } }
+ ? { index: { entry: configVike.server.entry, runtime: 'node' } }
: Object.entries(configVike.server.entry).reduce((acc, [name, value]) => {
if (typeof value === 'object') {
assertUsage(
@@ -36,7 +36,7 @@ function resolveConfig(configVike: ConfigVikeNode): ConfigVikeNodeResolved {
`Invalid runtime "${value.runtime}" for entry "${name}". Valid runtimes are: ${RUNTIMES.join(', ')}.`
)
}
- acc[name] = typeof value === 'string' ? { path: value, runtime: 'node' } : value
+ acc[name] = typeof value === 'string' ? { entry: value, runtime: 'node' } : value
return acc
}, {} as EntryResolved)
@@ -53,7 +53,7 @@ function resolveConfig(configVike: ConfigVikeNode): ConfigVikeNodeResolved {
assertUsage(typeof configVike.server === 'string', 'config.server should be defined')
return {
server: {
- entry: { index: { path: configVike.server, runtime: 'node' } },
+ entry: { index: { entry: configVike.server, runtime: 'node' } },
standalone: false,
external: nativeDependecies
}
diff --git a/packages/vike-node/src/runtime/vike-handler.ts b/packages/vike-node/src/runtime/vike-handler.ts
index 4924598..af5a98b 100644
--- a/packages/vike-node/src/runtime/vike-handler.ts
+++ b/packages/vike-node/src/runtime/vike-handler.ts
@@ -20,15 +20,8 @@ async function renderPage({
return typeof options.pageContext === 'function' ? options.pageContext(platformRequest) : options.pageContext ?? {}
}
- const fixedUrl = isVercel()
- ? fixUrlVercel({
- url,
- headers
- })
- : url
-
const pageContext = await _renderPage({
- urlOriginal: fixedUrl,
+ urlOriginal: url,
headersOriginal: headers,
...(await getPageContext(platformRequest))
})
@@ -65,26 +58,3 @@ async function renderPageWeb({
const { statusCode, headers: headersOut, getReadableWebStream } = httpResponse
return new Response(getReadableWebStream(), { status: statusCode, headers: headersOut })
}
-
-function fixUrlVercel(request: { url: string; headers: [string, string][] }) {
- const parsedUrl = new URL(request.url, DUMMY_BASE_URL)
- const headers = request.headers
- const search = parsedUrl.searchParams
- const __original_path = search.get('__original_path')
- if (typeof __original_path === 'string') {
- search.delete('__original_path')
- return __original_path + parsedUrl.search
- }
-
- // FIXME: x-now-route-matches is not definitive https://github.com/orgs/vercel/discussions/577#discussioncomment-2769478
- const matchesHeader = headers.find((h) => h[0] === 'x-now-route-matches')?.[1]
- const matches = matchesHeader ? new URLSearchParams(matchesHeader).get('1') : null
-
- if (typeof matches === 'string') {
- const pathnameAndQuery = matches + (parsedUrl.search || '')
- return pathnameAndQuery
- }
-
- const pathnameAndQuery = (parsedUrl.pathname || '') + (parsedUrl.search || '')
- return pathnameAndQuery
-}
diff --git a/packages/vike-node/src/types.ts b/packages/vike-node/src/types.ts
index 4500a30..7f5d2ae 100644
--- a/packages/vike-node/src/types.ts
+++ b/packages/vike-node/src/types.ts
@@ -1,6 +1,6 @@
export type { ConfigVikeNode, ConfigVikeNodeResolved, ConfigVikeNodePlugin, Runtime, EntryResolved }
-type Runtime = 'node' | 'nodeless' | 'deno' | 'cloudflare' | 'vercel'
+type Runtime = 'node' | 'nodeless' | 'deno' | 'cloudflare' | 'cloudflare-nodejs-compat' | 'vercel'
type ConfigVikeNode = {
/** Server entry path.
*
@@ -8,7 +8,9 @@ type ConfigVikeNode = {
server:
| string
| {
- entry: string | { index: string; [name: string]: string | { path: string; runtime: Runtime } }
+ entry:
+ | string
+ | { index: string; [name: string]: string | { entry: string; runtime: Runtime; scaffold?: string } }
/** Enable standalone build.
*
* @default false
@@ -22,7 +24,10 @@ type ConfigVikeNode = {
}
}
-type EntryResolved = { index: { path: string; runtime: Runtime }; [name: string]: { path: string; runtime: Runtime } }
+type EntryResolved = {
+ index: { entry: string; runtime: Runtime }
+ [name: string]: { entry: string; runtime: Runtime; scaffold?: string }
+}
type ConfigVikeNodeResolved = {
server: {
entry: EntryResolved
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 06686e2..fadd373 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -120,9 +120,9 @@ importers:
specifier: ^5.4.0
version: 5.4.0(@types/node@22.2.0)
devDependencies:
- vike-cloudflare:
- specifier: ^0.0.6
- version: 0.0.6(vike@0.4.184(react-streaming@0.3.43(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(vite@5.4.0(@types/node@22.2.0)))(vite@5.4.0(@types/node@22.2.0))
+ telefunc:
+ specifier: ^0.1.76
+ version: 0.1.76(@babel/core@7.25.2)(@babel/parser@7.25.3)(@babel/types@7.25.2)(react-streaming@0.3.43(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
wrangler:
specifier: ^3.71.0
version: 3.71.0(@cloudflare/workers-types@4.20240806.0)
@@ -1084,12 +1084,6 @@ packages:
'@fastify/merge-json-schemas@0.1.1':
resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==}
- '@hattip/adapter-cloudflare-workers@0.0.46':
- resolution: {integrity: sha512-onPh5wcVZQkyaw+T1ckbK/zT7Fl6zD7hdXkkE/IPQZ1EFmJJoFX6Q52UM8DIXZK1tw8NyxFigWtAsQQm25q6tg==}
-
- '@hattip/core@0.0.46':
- resolution: {integrity: sha512-6pk22hPi9qVc6jyROu89T2yV2IcORTJZUq5OdFDfWmu4ynMP4I2avC+hnCJj6o3vlN1Io7zBbdT5OIPxpBIX7A==}
-
'@hono/node-server@1.12.0':
resolution: {integrity: sha512-e6oHjNiErRxsZRZBmc2KucuvY3btlO/XPncIpP2X75bRdTilF9GLjm3NHvKKunpJbbJJj31/FoPTksTf8djAVw==}
engines: {node: '>=18.14.1'}
@@ -3097,12 +3091,6 @@ packages:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
- vike-cloudflare@0.0.6:
- resolution: {integrity: sha512-JNN6NcgYpaDwt8y2kw6ee0OD6pSrutoNbFAL7EBnZybzV95ALnYH9n/U7kmxRX7AmB4Q+qCmw9YhxrrMgAJ7Ew==}
- peerDependencies:
- vike: ^0.4.174
- vite: ^5.3.0
-
vike-react@0.4.18:
resolution: {integrity: sha512-S7HTVvdU138vu7LZw94SUqHsDew4+lSj/jVbvpCgKPL4YEYfuNIo+1SMNxy7747bJ7W/rResc1B80UB9YCiRpw==}
peerDependencies:
@@ -3772,16 +3760,6 @@ snapshots:
dependencies:
fast-deep-equal: 3.1.3
- '@hattip/adapter-cloudflare-workers@0.0.46':
- dependencies:
- '@cloudflare/kv-asset-handler': 0.3.4
- '@cloudflare/workers-types': 4.20240806.0
- '@hattip/core': 0.0.46
- optional: true
-
- '@hattip/core@0.0.46':
- optional: true
-
'@hono/node-server@1.12.0': {}
'@hutson/parse-repository-url@5.0.0': {}
@@ -5861,13 +5839,6 @@ snapshots:
vary@1.1.2: {}
- vike-cloudflare@0.0.6(vike@0.4.184(react-streaming@0.3.43(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(vite@5.4.0(@types/node@22.2.0)))(vite@5.4.0(@types/node@22.2.0)):
- dependencies:
- vike: 0.4.184(react-streaming@0.3.43(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(vite@5.4.0(@types/node@22.2.0))
- vite: 5.4.0(@types/node@22.2.0)
- optionalDependencies:
- '@hattip/adapter-cloudflare-workers': 0.0.46
-
vike-react@0.4.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(vike@0.4.184(react-streaming@0.3.43(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(vite@5.4.0(@types/node@22.2.0)))(vite@5.4.0(@types/node@22.2.0)):
dependencies:
react: 18.3.1