- 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]>
57 lines
2.5 KiB
JavaScript
57 lines
2.5 KiB
JavaScript
import {} from "esbuild";
|
|
import grabArtifactsFromBundledResults from "../grab-artifacts-from-bundled-result";
|
|
import { writeFileSync } from "fs";
|
|
import path from "path";
|
|
import grabDirNames from "../../../utils/grab-dir-names";
|
|
import grabRelativePath from "../../../utils/grab-relative-path";
|
|
import { logBuildErrorsOnce, resetBuildErrorLog, } from "../../../utils/build-error-log";
|
|
import { log } from "../../../utils/log";
|
|
let build_start = 0;
|
|
export default function ssrCTXArtifactTracker({ entryToPage }) {
|
|
const { BUNX_TMP_DIR } = grabDirNames();
|
|
const artifactTracker = {
|
|
name: "ssr-artifact-tracker",
|
|
setup(build) {
|
|
build.onStart(async () => {
|
|
build_start = performance.now();
|
|
});
|
|
build.onEnd(async (result) => {
|
|
if (result.errors.length > 0) {
|
|
global.BUNEXT_BUILD_FAILED = true;
|
|
global.BUNEXT_SSR_BUNDLER_CTX_DISPOSED = true;
|
|
logBuildErrorsOnce(result.errors, (line) => log.error(`SSR Build error: ${line}`));
|
|
return;
|
|
}
|
|
const artifacts = grabArtifactsFromBundledResults({
|
|
result,
|
|
entryToPage,
|
|
virtual_match: `ssr-virtual`,
|
|
});
|
|
if (artifacts?.[0] && artifacts.length > 0) {
|
|
for (let i = 0; i < artifacts.length; i++) {
|
|
const artifact = artifacts[i];
|
|
if (artifact?.local_path &&
|
|
global.BUNEXT_SSR_BUNDLER_CTX_MAP) {
|
|
const relative_path = grabRelativePath(artifact.local_path);
|
|
global.BUNEXT_SSR_BUNDLER_CTX_MAP[relative_path] = {
|
|
...artifact,
|
|
local_path: relative_path,
|
|
};
|
|
}
|
|
}
|
|
}
|
|
try {
|
|
writeFileSync(path.join(BUNX_TMP_DIR, "ctx-map.json"), JSON.stringify(global.BUNEXT_SSR_BUNDLER_CTX_MAP, null, 4));
|
|
}
|
|
catch (error) { }
|
|
// const elapsed = (performance.now() - build_start).toFixed(0);
|
|
// log.success(`SSR [Built] in ${elapsed}ms`);
|
|
global.BUNEXT_SSR_BUNDLER_CTX_DISPOSED = false;
|
|
global.BUNEXT_BUILD_FAILED = false;
|
|
resetBuildErrorLog();
|
|
});
|
|
},
|
|
};
|
|
return artifactTracker;
|
|
}
|