Skip to content

Commit

Permalink
Support for getStaticPaths.fallback = false (vercel/turborepo#3600)
Browse files Browse the repository at this point in the history
Adds support for `getStaticPaths` returning `{ fallback: false }` by
building out all static paths and checking whether the resolved path is
included in that list.

`buildStaticPaths` requires the `next.config.js` path, as well as other
config options such as locale. I created WEB-546 to track being able to
pass them to the handlers.
  • Loading branch information
alexkirsz committed Feb 6, 2023
1 parent 4ae77fc commit cf2ed6f
Showing 1 changed file with 46 additions and 17 deletions.
63 changes: 46 additions & 17 deletions crates/next-core/js/src/internal/page-server-handler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
import { renderToHTML, RenderOpts } from "next/dist/server/render";
import { getRedirectStatus } from "next/dist/lib/redirect-status";
import { PERMANENT_REDIRECT_STATUS } from "next/dist/shared/lib/constants";
import { buildStaticPaths } from "next/dist/build/utils";
import type { BuildManifest } from "next/dist/server/get-page-files";
import type { ReactLoadableManifest } from "next/dist/server/load-components";

Expand Down Expand Up @@ -79,6 +80,30 @@ export default function startHandler({
async function runOperation(
renderData: RenderData
): Promise<IpcOutgoingMessage> {
if ("getStaticPaths" in otherExports) {
const {
paths: prerenderRoutes,
fallback: prerenderFallback,
encodedPaths: _encodedPrerenderRoutes,
} = await buildStaticPaths({
page: renderData.path,
getStaticPaths: otherExports.getStaticPaths,
// TODO(alexkirsz) Provide the correct next.config.js path.
configFileName: "next.config.js",
});

// We provide a dummy base URL to the URL constructor so that it doesn't
// throw when we pass a relative URL.
const resolvedPath = new URL(renderData.url, "next://").pathname;
if (
prerenderFallback === false &&
// TODO(alexkirsz) Strip basePath.
!prerenderRoutes.includes(resolvedPath)
) {
return createNotFoundResponse(isDataReq);
}
}

// TODO(alexkirsz) This is missing *a lot* of data, but it's enough to get a
// basic render working.

Expand Down Expand Up @@ -203,23 +228,7 @@ export default function startHandler({
const isNotFound = (renderOpts as any).isNotFound;

if (isNotFound) {
if (isDataReq) {
return {
type: "response",
// Returning a 404 status code is required for the client-side router
// to redirect to the error page.
statusCode: 404,
body: '{"notFound":true}',
headers: [["Content-Type", MIME_APPLICATION_JAVASCRIPT]],
};
}

return {
type: "rewrite",
// _next/404 is a Turbopack-internal route that will always redirect to
// the 404 page.
path: "/_next/404",
};
return createNotFoundResponse(isDataReq);
}

// Set when `getStaticProps` returns `redirect: { destination, permanent, statusCode }`.
Expand Down Expand Up @@ -290,6 +299,26 @@ export default function startHandler({
}
}

function createNotFoundResponse(isDataReq: boolean): IpcOutgoingMessage {
if (isDataReq) {
return {
type: "response",
// Returning a 404 status code is required for the client-side router
// to redirect to the error page.
statusCode: 404,
body: '{"notFound":true}',
headers: [["Content-Type", MIME_APPLICATION_JAVASCRIPT]],
};
}

return {
type: "rewrite",
// /_next/404 is a Turbopack-internal route that will always redirect to
// the 404 page.
path: "/_next/404",
};
}

type ManifestItem = {
id: string;
chunks: string[];
Expand Down

0 comments on commit cf2ed6f

Please sign in to comment.