Bugfix catch all page renaming bundler error
This commit is contained in:
parent
12de7ff891
commit
05154bb758
2
index.ts
2
index.ts
@ -30,12 +30,14 @@ declare global {
|
|||||||
var BUNDLER_CTX: BuildContext | undefined;
|
var BUNDLER_CTX: BuildContext | undefined;
|
||||||
var BUNDLER_CTX_MAP: BundlerCTXMap[] | undefined;
|
var BUNDLER_CTX_MAP: BundlerCTXMap[] | undefined;
|
||||||
var IS_FIRST_BUNDLE_READY: boolean;
|
var IS_FIRST_BUNDLE_READY: boolean;
|
||||||
|
var BUNDLER_REBUILDS: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
global.ORA_SPINNER = ora();
|
global.ORA_SPINNER = ora();
|
||||||
global.ORA_SPINNER.clear();
|
global.ORA_SPINNER.clear();
|
||||||
global.HMR_CONTROLLERS = [];
|
global.HMR_CONTROLLERS = [];
|
||||||
global.IS_FIRST_BUNDLE_READY = false;
|
global.IS_FIRST_BUNDLE_READY = false;
|
||||||
|
global.BUNDLER_REBUILDS = 0;
|
||||||
|
|
||||||
await init();
|
await init();
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import isDevelopment from "../../utils/is-development";
|
|||||||
import type { BundlerCTXMap } from "../../types";
|
import type { BundlerCTXMap } from "../../types";
|
||||||
import { execSync } from "child_process";
|
import { execSync } from "child_process";
|
||||||
import grabConstants from "../../utils/grab-constants";
|
import grabConstants from "../../utils/grab-constants";
|
||||||
|
import rebuildBundler from "../server/rebuild-bundler";
|
||||||
|
|
||||||
const { HYDRATION_DST_DIR, PAGES_DIR, HYDRATION_DST_DIR_MAP_JSON_FILE } =
|
const { HYDRATION_DST_DIR, PAGES_DIR, HYDRATION_DST_DIR_MAP_JSON_FILE } =
|
||||||
grabDirNames();
|
grabDirNames();
|
||||||
@ -40,9 +41,15 @@ type Params = {
|
|||||||
|
|
||||||
export default async function allPagesBundler(params?: Params) {
|
export default async function allPagesBundler(params?: Params) {
|
||||||
const pages = grabAllPages({ exclude_api: true });
|
const pages = grabAllPages({ exclude_api: true });
|
||||||
const { ClientRootElementIDName, ClientRootComponentWindowName } =
|
const {
|
||||||
await grabConstants();
|
ClientRootElementIDName,
|
||||||
|
ClientRootComponentWindowName,
|
||||||
|
MaxBundlerRebuilds,
|
||||||
|
} = await grabConstants();
|
||||||
|
|
||||||
|
// Use index-based keys so bracket paths (e.g. [[...catch_all]]) never
|
||||||
|
// appear in any path that esbuild's binary tracks internally. The actual
|
||||||
|
// file path is only ever used inside our JS plugin callbacks.
|
||||||
const virtualEntries: Record<string, string> = {};
|
const virtualEntries: Record<string, string> = {};
|
||||||
const dev = isDevelopment();
|
const dev = isDevelopment();
|
||||||
|
|
||||||
@ -53,15 +60,16 @@ export default async function allPagesBundler(params?: Params) {
|
|||||||
|
|
||||||
const does_root_exist = existsSync(root_component_path);
|
const does_root_exist = existsSync(root_component_path);
|
||||||
|
|
||||||
for (const page of pages) {
|
for (let i = 0; i < pages.length; i++) {
|
||||||
const key = page.local_path;
|
const page = pages[i];
|
||||||
|
const virtualKey = `page-${i}`;
|
||||||
|
|
||||||
let txt = ``;
|
let txt = ``;
|
||||||
txt += `import { hydrateRoot } from "react-dom/client";\n`;
|
txt += `import { hydrateRoot } from "react-dom/client";\n`;
|
||||||
if (does_root_exist) {
|
if (does_root_exist) {
|
||||||
txt += `import Root from "${root_component_path}";\n`;
|
txt += `import Root from "${root_component_path}";\n`;
|
||||||
}
|
}
|
||||||
txt += `import Page from "${page.local_path}";\n\n`;
|
txt += `import Page from "page-entry:${i}";\n\n`;
|
||||||
txt += `const pageProps = window.__PAGE_PROPS__ || {};\n`;
|
txt += `const pageProps = window.__PAGE_PROPS__ || {};\n`;
|
||||||
|
|
||||||
if (does_root_exist) {
|
if (does_root_exist) {
|
||||||
@ -72,7 +80,7 @@ export default async function allPagesBundler(params?: Params) {
|
|||||||
txt += `const root = hydrateRoot(document.getElementById("${ClientRootElementIDName}"), component);\n\n`;
|
txt += `const root = hydrateRoot(document.getElementById("${ClientRootElementIDName}"), component);\n\n`;
|
||||||
txt += `window.${ClientRootComponentWindowName} = root;\n`;
|
txt += `window.${ClientRootComponentWindowName} = root;\n`;
|
||||||
|
|
||||||
virtualEntries[key] = txt;
|
virtualEntries[virtualKey] = txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
const virtualPlugin: esbuild.Plugin = {
|
const virtualPlugin: esbuild.Plugin = {
|
||||||
@ -83,11 +91,33 @@ export default async function allPagesBundler(params?: Params) {
|
|||||||
namespace: "virtual",
|
namespace: "virtual",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
build.onResolve({ filter: /^page-entry:/ }, (args) => ({
|
||||||
|
path: args.path.replace("page-entry:", ""),
|
||||||
|
namespace: "page-entry",
|
||||||
|
}));
|
||||||
|
|
||||||
build.onLoad({ filter: /.*/, namespace: "virtual" }, (args) => ({
|
build.onLoad({ filter: /.*/, namespace: "virtual" }, (args) => ({
|
||||||
contents: virtualEntries[args.path],
|
contents: virtualEntries[args.path],
|
||||||
loader: "tsx",
|
loader: "tsx",
|
||||||
resolveDir: process.cwd(),
|
resolveDir: process.cwd(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
build.onLoad(
|
||||||
|
{ filter: /.*/, namespace: "page-entry" },
|
||||||
|
async (args) => {
|
||||||
|
const page = pages[parseInt(args.path)];
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
contents: await readFile(page.local_path, "utf-8"),
|
||||||
|
loader: "tsx" as const,
|
||||||
|
resolveDir: path.dirname(page.local_path),
|
||||||
|
watchFiles: [page.local_path],
|
||||||
|
};
|
||||||
|
} catch (e: any) {
|
||||||
|
return { errors: [{ text: e.message }] };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,19 +128,38 @@ export default async function allPagesBundler(params?: Params) {
|
|||||||
console.time("build");
|
console.time("build");
|
||||||
});
|
});
|
||||||
|
|
||||||
build.onEnd((result) => {
|
build.onEnd(async (result) => {
|
||||||
if (result.errors.length > 0) return;
|
if (result.errors.length > 0) {
|
||||||
|
const messages = await esbuild.formatMessages(
|
||||||
|
result.errors,
|
||||||
|
{ kind: "error", color: true },
|
||||||
|
);
|
||||||
|
for (const msg of messages) {
|
||||||
|
process.stderr.write(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
global.BUNDLER_REBUILDS++;
|
||||||
|
|
||||||
|
if (global.BUNDLER_REBUILDS > MaxBundlerRebuilds) {
|
||||||
|
console.error(`Max Rebuilds all failed.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await rebuildBundler();
|
||||||
|
console.timeEnd("build");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const artifacts: (BundlerCTXMap | undefined)[] = Object.entries(
|
const artifacts: (BundlerCTXMap | undefined)[] = Object.entries(
|
||||||
result.metafile!.outputs,
|
result.metafile!.outputs,
|
||||||
)
|
)
|
||||||
.filter(([, meta]) => meta.entryPoint)
|
.filter(([, meta]) => meta.entryPoint)
|
||||||
.map(([outputPath, meta]) => {
|
.map(([outputPath, meta]) => {
|
||||||
const target_page = pages.find((p) => {
|
const indexMatch =
|
||||||
return (
|
meta.entryPoint?.match(/^virtual:page-(\d+)$/);
|
||||||
meta.entryPoint === `virtual:${p.local_path}`
|
const target_page = indexMatch
|
||||||
);
|
? pages[parseInt(indexMatch[1])]
|
||||||
});
|
: undefined;
|
||||||
|
|
||||||
if (!target_page || !meta.entryPoint) {
|
if (!target_page || !meta.entryPoint) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -147,6 +196,7 @@ export default async function allPagesBundler(params?: Params) {
|
|||||||
// );
|
// );
|
||||||
|
|
||||||
global.BUNDLER_CTX_MAP = final_artifacts;
|
global.BUNDLER_CTX_MAP = final_artifacts;
|
||||||
|
global.BUNDLER_REBUILDS = 0;
|
||||||
params?.post_build_fn?.({ artifacts: final_artifacts });
|
params?.post_build_fn?.({ artifacts: final_artifacts });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +221,7 @@ export default async function allPagesBundler(params?: Params) {
|
|||||||
execSync(`rm -rf ${HYDRATION_DST_DIR}`);
|
execSync(`rm -rf ${HYDRATION_DST_DIR}`);
|
||||||
|
|
||||||
const ctx = await esbuild.context({
|
const ctx = await esbuild.context({
|
||||||
entryPoints: Object.keys(virtualEntries).map((k) => `virtual:${k}`),
|
entryPoints: Object.keys(virtualEntries).map((k) => `virtual:${k}`), // ["virtual:page-0", ...]
|
||||||
outdir: HYDRATION_DST_DIR,
|
outdir: HYDRATION_DST_DIR,
|
||||||
bundle: true,
|
bundle: true,
|
||||||
minify: !dev,
|
minify: !dev,
|
||||||
@ -190,7 +240,9 @@ export default async function allPagesBundler(params?: Params) {
|
|||||||
jsx: "automatic",
|
jsx: "automatic",
|
||||||
});
|
});
|
||||||
|
|
||||||
await ctx.rebuild();
|
await ctx.rebuild().catch((error: any) => {
|
||||||
|
console.error(`Build failed:`, error.message);
|
||||||
|
});
|
||||||
|
|
||||||
if (params?.watch) {
|
if (params?.watch) {
|
||||||
global.BUNDLER_CTX = ctx;
|
global.BUNDLER_CTX = ctx;
|
||||||
|
|||||||
18
src/functions/server/rebuild-bundler.tsx
Normal file
18
src/functions/server/rebuild-bundler.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import allPagesBundler from "../bundler/all-pages-bundler";
|
||||||
|
import serverPostBuildFn from "./server-post-build-fn";
|
||||||
|
|
||||||
|
export default async function rebuildBundler() {
|
||||||
|
try {
|
||||||
|
global.ROUTER.reload();
|
||||||
|
|
||||||
|
await global.BUNDLER_CTX?.dispose();
|
||||||
|
global.BUNDLER_CTX = undefined;
|
||||||
|
|
||||||
|
await allPagesBundler({
|
||||||
|
watch: true,
|
||||||
|
post_build_fn: serverPostBuildFn,
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,18 +1,15 @@
|
|||||||
import { watch, existsSync } from "fs";
|
import { watch, existsSync } from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import grabDirNames from "../../utils/grab-dir-names";
|
import grabDirNames from "../../utils/grab-dir-names";
|
||||||
import serverParamsGen from "./server-params-gen";
|
import rebuildBundler from "./rebuild-bundler";
|
||||||
import allPagesBundler from "../bundler/all-pages-bundler";
|
|
||||||
import serverPostBuildFn from "./server-post-build-fn";
|
|
||||||
import refreshRouter from "../../utils/refresh-router";
|
|
||||||
|
|
||||||
const { PAGES_DIR } = grabDirNames();
|
const { SRC_DIR } = grabDirNames();
|
||||||
|
|
||||||
const PAGE_FILE_RE = /\.(tsx?|jsx?)$/;
|
const PAGE_FILE_RE = /\.(tsx?|jsx?|css)$/;
|
||||||
|
|
||||||
export default function watcher() {
|
export default function watcher() {
|
||||||
watch(
|
watch(
|
||||||
PAGES_DIR,
|
SRC_DIR,
|
||||||
{
|
{
|
||||||
recursive: true,
|
recursive: true,
|
||||||
persistent: true,
|
persistent: true,
|
||||||
@ -28,7 +25,7 @@ export default function watcher() {
|
|||||||
|
|
||||||
if (global.RECOMPILING) return;
|
if (global.RECOMPILING) return;
|
||||||
|
|
||||||
const fullPath = path.join(PAGES_DIR, filename);
|
const fullPath = path.join(SRC_DIR, filename);
|
||||||
const action = existsSync(fullPath) ? "created" : "deleted";
|
const action = existsSync(fullPath) ? "created" : "deleted";
|
||||||
|
|
||||||
clearTimeout(global.WATCHER_TIMEOUT);
|
clearTimeout(global.WATCHER_TIMEOUT);
|
||||||
@ -38,15 +35,7 @@ export default function watcher() {
|
|||||||
|
|
||||||
console.log(`Page ${action}: ${filename}. Rebuilding ...`);
|
console.log(`Page ${action}: ${filename}. Rebuilding ...`);
|
||||||
|
|
||||||
global.ROUTER.reload();
|
await rebuildBundler();
|
||||||
|
|
||||||
await global.BUNDLER_CTX?.dispose();
|
|
||||||
global.BUNDLER_CTX = undefined;
|
|
||||||
|
|
||||||
await allPagesBundler({
|
|
||||||
watch: true,
|
|
||||||
post_build_fn: serverPostBuildFn,
|
|
||||||
});
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
} finally {
|
} finally {
|
||||||
@ -55,46 +44,4 @@ export default function watcher() {
|
|||||||
}, 150);
|
}, 150);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// watch(BUNX_HYDRATION_SRC_DIR, async (event, filename) => {
|
|
||||||
// if (!filename) return;
|
|
||||||
|
|
||||||
// const targetFile = path.join(BUNX_HYDRATION_SRC_DIR, filename);
|
|
||||||
|
|
||||||
// await Bun.build({
|
|
||||||
// entrypoints: [targetFile],
|
|
||||||
// outdir: HYDRATION_DST_DIR,
|
|
||||||
// minify: true,
|
|
||||||
// target: "browser",
|
|
||||||
// format: "esm",
|
|
||||||
// });
|
|
||||||
|
|
||||||
// global.SERVER?.publish("__bun_hmr", "update");
|
|
||||||
|
|
||||||
// setTimeout(() => {
|
|
||||||
// global.RECOMPILING = false;
|
|
||||||
// }, 200);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// watch(HYDRATION_DST_DIR, async (event, filename) => {
|
|
||||||
// const encoder = new TextEncoder();
|
|
||||||
// global.HMR_CONTROLLER?.enqueue(encoder.encode(`event: update\ndata: reload\n\n`));
|
|
||||||
// global.RECOMPILING = false;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// let cmd = `bun build`;
|
|
||||||
|
|
||||||
// cmd += ` ${BUNX_HYDRATION_SRC_DIR}/*.tsx --outdir ${HYDRATION_DST_DIR}`;
|
|
||||||
// cmd += ` --watch --minify`;
|
|
||||||
|
|
||||||
// execSync(cmd, { stdio: "inherit" });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function reloadServer() {
|
|
||||||
const serverParams = await serverParamsGen();
|
|
||||||
|
|
||||||
console.log(`Reloading Server ...`);
|
|
||||||
|
|
||||||
global.SERVER?.stop();
|
|
||||||
global.SERVER = Bun.serve(serverParams);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,11 +11,14 @@ export default async function grabConstants() {
|
|||||||
|
|
||||||
const ServerDefaultRequestBodyLimitBytes = MB_IN_BYTES * 10;
|
const ServerDefaultRequestBodyLimitBytes = MB_IN_BYTES * 10;
|
||||||
|
|
||||||
|
const MaxBundlerRebuilds = 5;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ClientRootElementIDName,
|
ClientRootElementIDName,
|
||||||
ClientWindowPagePropsName,
|
ClientWindowPagePropsName,
|
||||||
MBInBytes: MB_IN_BYTES,
|
MBInBytes: MB_IN_BYTES,
|
||||||
ServerDefaultRequestBodyLimitBytes,
|
ServerDefaultRequestBodyLimitBytes,
|
||||||
ClientRootComponentWindowName,
|
ClientRootComponentWindowName,
|
||||||
|
MaxBundlerRebuilds,
|
||||||
} as const;
|
} as const;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user