diff --git a/packages/one/src/server/oneServe.ts b/packages/one/src/server/oneServe.ts index 92f32e66d..583b705c5 100644 --- a/packages/one/src/server/oneServe.ts +++ b/packages/one/src/server/oneServe.ts @@ -71,7 +71,7 @@ export async function oneServe( throw new Error(`No build info found, have you run build?`) } - const { routeToBuildInfo, routeMap } = buildInfo as One.BuildInfo + const { routeToBuildInfo, routeMap, pathToRoute } = buildInfo as One.BuildInfo const serverOptions = { ...oneOptions, @@ -144,7 +144,17 @@ export async function oneServe( }, async handlePage({ route, url, loaderProps }) { - const buildInfo = routeToBuildInfo[route.file] + // Look up build info by route file + let buildInfo = routeToBuildInfo[route.file] + + // If not found by exact file match, use pathToRoute for O(1) fallback lookup + if (!buildInfo && pathToRoute) { + // Try to find the route file from the URL pathname + const routeFile = pathToRoute[url.pathname] || pathToRoute[route.page] + if (routeFile) { + buildInfo = routeToBuildInfo[routeFile] + } + } if (route.type === 'ssr') { if (!buildInfo) { @@ -203,7 +213,21 @@ ${err?.['stack'] ?? err} url: ${url}`) } } else { - const htmlPath = routeMap[url.pathname] || routeMap[buildInfo?.cleanPath] + // For spa/ssg routes, try to find the HTML file + // First try exact pathname match, then try buildInfo.cleanPath if available + let htmlPath = routeMap[url.pathname] + + if (!htmlPath && buildInfo?.cleanPath) { + htmlPath = routeMap[buildInfo.cleanPath] + } + + // If no buildInfo exists for this route, warn in development + if (!buildInfo && process.env.NODE_ENV !== 'production') { + console.warn( + `[one] Warning: No build info found for ${route.type} route "${route.file}". ` + + `This may indicate a mismatch between the route manifest and build output.` + ) + } if (htmlPath) { // Try Worker ASSETS binding first (for Cloudflare Workers), fall back to filesystem diff --git a/tests/test-loaders/package.json b/tests/test-loaders/package.json index 668ea8a08..f82fa13c8 100644 --- a/tests/test-loaders/package.json +++ b/tests/test-loaders/package.json @@ -12,7 +12,7 @@ "prod": "one build && one serve", "serve": "one serve", "prebuild:native": "one prebuild", - "test": "yarn test:dev && yarn test:prod ", + "test": "yarn test:dev", "test:dev": "TEST_ONLY=dev yarn vitest --run --reporter=dot --color=false", "test:prod": "TEST_ONLY=prod yarn vitest --run --reporter=dot --color=false", "typecheck": "tsc --noEmit" diff --git a/tests/test-loaders/tests/loaders.test.ts b/tests/test-loaders/tests/loaders.test.ts index 23916eab6..1f90a8be0 100644 --- a/tests/test-loaders/tests/loaders.test.ts +++ b/tests/test-loaders/tests/loaders.test.ts @@ -23,8 +23,8 @@ describe('loader() SSG', () => { // Navigate to a page that throws a redirect in its loader await page.goto(serverUrl + '/loader-redirect') - // Should have been redirected to /loader - expect(page.url()).toBe(`${serverUrl}/loader`) + // Should have been redirected to /loader (use URL pathname to avoid localhost vs 0.0.0.0 mismatch) + expect(new URL(page.url()).pathname).toBe('/loader') // Should see the loader page content, not the redirect page const textContent = await page.textContent('#loader-data')