- Server functions can return not_found: true to render the 404 page with status 404. - Page components and window.__PAGE_PROPS__ (and HMR updates) only get props, query, url and error. response_options, redirect, cache settings and res_transform stay on the server, so cookies and private headers no longer end up in the HTML. BunextPageProps is narrowed to match (breaking for code that read server-only fields from component props). - response_options headers go through a Headers object, so repeated headers such as several Set-Cookie survive. - Redirects: status_code wins over permanent; response_options headers and res_transform apply to redirects too. - Gzip for compressible text responses; compress: false to turn it off. - Files the router matches but never bundles (.server.ts, __root, excluded paths and directories) return 404 instead of looping through dev rebuild retries. - Missing public files return 404 rather than 403, so dotted page paths like /users/john.doe fall through to pages again. - importFresh detects rewrites within the filesystem's mtime granularity. - README: self-hosted React (not esm.sh), snake_case option names, static file serving, cache headers, the new options. Co-Authored-By: Claude Opus 5.5 <[email protected]>
55 lines
2.1 KiB
JavaScript
55 lines
2.1 KiB
JavaScript
import grabPageBundledReactComponent from "./grab-page-bundled-react-component";
|
|
import _ from "lodash";
|
|
import { log } from "../../../utils/log";
|
|
import grabRootFilePath from "./grab-root-file-path";
|
|
import grabPageCombinedServerRes from "./grab-page-combined-server-res";
|
|
import importFresh from "../../../utils/import-fresh";
|
|
import grabRedirectResponse from "../../../utils/grab-redirect-response";
|
|
import NotFoundError from "../../../utils/not-found-error";
|
|
export default async function grabPageModules({ file_path, debug, url, query, routeParams, skip_server_res, }) {
|
|
const { serverRes } = skip_server_res
|
|
? {}
|
|
: await grabPageCombinedServerRes({
|
|
file_path,
|
|
debug,
|
|
query,
|
|
routeParams,
|
|
url,
|
|
});
|
|
if (serverRes?.redirect?.destination) {
|
|
return await grabRedirectResponse({ serverRes, routeParams });
|
|
}
|
|
// Rendered as the 404 page by grabPageComponent's error path
|
|
if (serverRes?.not_found) {
|
|
throw new NotFoundError(`Page ${url?.pathname || file_path} not found`);
|
|
}
|
|
const { component, page_module, root_module: bundled_root_module, } = (await grabPageBundledReactComponent({
|
|
file_path,
|
|
})) || {};
|
|
if (!component) {
|
|
throw new Error(`Couldn't grab page component`);
|
|
}
|
|
// Prefer the page/root exports re-exported by the SSR bundle. Importing
|
|
// the raw source with Bun's loader only cache-busts the page file itself:
|
|
// its transitive imports stay in Bun's module registry, so a component
|
|
// that failed to resolve once (e.g. imported before it was created)
|
|
// keeps failing until the server restarts.
|
|
const { root_file_path } = grabRootFilePath();
|
|
const root_module = !root_file_path
|
|
? undefined
|
|
: bundled_root_module || (await importFresh(root_file_path));
|
|
const module = page_module || (await importFresh(file_path));
|
|
if (debug) {
|
|
log.info(`module:`, module);
|
|
}
|
|
if (debug) {
|
|
log.info(`component:`, component);
|
|
}
|
|
return {
|
|
component,
|
|
serverRes,
|
|
module,
|
|
root_module,
|
|
};
|
|
}
|