From c4f7cf9164e68fe57376bfe8bc3731965eddb042 Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Sat, 11 Apr 2026 10:00:24 +0100 Subject: [PATCH] Fix api route caching issue --- dist/commands/index.js | 2 - dist/commands/rewrite-pages/index.d.ts | 2 - dist/commands/rewrite-pages/index.js | 16 -- .../bundler/all-pages-bun-bundler.d.ts | 7 - .../bundler/all-pages-bun-bundler.js | 107 ---------- dist/functions/bundler/all-pages-bundler.d.ts | 8 - dist/functions/bundler/all-pages-bundler.js | 142 -------------- ...l-pages-esbuild-context-bundler-files.d.ts | 7 - ...all-pages-esbuild-context-bundler-files.js | 58 ------ .../bundler/build-on-start-error-handler.d.ts | 3 + .../bundler/build-on-start-error-handler.js | 14 ++ dist/functions/bundler/init-pages.d.ts | 7 - dist/functions/bundler/init-pages.js | 44 ----- .../bundler/pages-ssr-context-bundler.js | 9 +- .../plugins/esbuild-ctx-artifact-tracker.js | 39 +--- .../plugins/ssr-ctx-artifact-tracker.js | 10 +- .../functions/server/clear-require-cache.d.ts | 1 + dist/functions/server/clear-require-cache.js | 10 + dist/functions/server/handle-routes.js | 16 +- dist/functions/server/rebuild-bundler.d.ts | 5 - dist/functions/server/rebuild-bundler.js | 19 -- dist/functions/server/watcher-esbuild-ctx.js | 5 +- dist/functions/server/watcher.d.ts | 1 - dist/functions/server/watcher.js | 81 -------- dist/utils/rewrite-pages-module.d.ts | 5 - dist/utils/rewrite-pages-module.js | 37 ---- package.json | 2 +- src/commands/index.ts | 2 - src/commands/rewrite-pages/index.ts | 20 -- .../bundler/all-pages-bun-bundler.ts | 135 ------------- src/functions/bundler/all-pages-bundler.ts | 183 ------------------ ...all-pages-esbuild-context-bundler-files.ts | 81 -------- .../bundler/build-on-start-error-handler.ts | 21 ++ src/functions/bundler/init-pages.ts | 65 ------- .../bundler/pages-ssr-context-bundler.ts | 10 +- .../plugins/esbuild-ctx-artifact-tracker.ts | 47 +---- .../plugins/ssr-ctx-artifact-tracker.ts | 11 +- src/functions/server/clear-require-cache.ts | 10 + src/functions/server/handle-routes.ts | 21 +- src/functions/server/rebuild-bundler.tsx | 26 --- src/functions/server/watcher-esbuild-ctx.ts | 7 +- src/functions/server/watcher.ts | 104 ---------- src/utils/rewrite-pages-module.ts | 48 ----- 43 files changed, 132 insertions(+), 1316 deletions(-) delete mode 100644 dist/commands/rewrite-pages/index.d.ts delete mode 100644 dist/commands/rewrite-pages/index.js delete mode 100644 dist/functions/bundler/all-pages-bun-bundler.d.ts delete mode 100644 dist/functions/bundler/all-pages-bun-bundler.js delete mode 100644 dist/functions/bundler/all-pages-bundler.d.ts delete mode 100644 dist/functions/bundler/all-pages-bundler.js delete mode 100644 dist/functions/bundler/all-pages-esbuild-context-bundler-files.d.ts delete mode 100644 dist/functions/bundler/all-pages-esbuild-context-bundler-files.js create mode 100644 dist/functions/bundler/build-on-start-error-handler.d.ts create mode 100644 dist/functions/bundler/build-on-start-error-handler.js delete mode 100644 dist/functions/bundler/init-pages.d.ts delete mode 100644 dist/functions/bundler/init-pages.js create mode 100644 dist/functions/server/clear-require-cache.d.ts create mode 100644 dist/functions/server/clear-require-cache.js delete mode 100644 dist/functions/server/rebuild-bundler.d.ts delete mode 100644 dist/functions/server/rebuild-bundler.js delete mode 100644 dist/functions/server/watcher.d.ts delete mode 100644 dist/functions/server/watcher.js delete mode 100644 dist/utils/rewrite-pages-module.d.ts delete mode 100644 dist/utils/rewrite-pages-module.js delete mode 100644 src/commands/rewrite-pages/index.ts delete mode 100644 src/functions/bundler/all-pages-bun-bundler.ts delete mode 100644 src/functions/bundler/all-pages-bundler.ts delete mode 100644 src/functions/bundler/all-pages-esbuild-context-bundler-files.ts create mode 100644 src/functions/bundler/build-on-start-error-handler.ts delete mode 100644 src/functions/bundler/init-pages.ts create mode 100644 src/functions/server/clear-require-cache.ts delete mode 100644 src/functions/server/rebuild-bundler.tsx delete mode 100644 src/functions/server/watcher.ts delete mode 100644 src/utils/rewrite-pages-module.ts diff --git a/dist/commands/index.js b/dist/commands/index.js index 4e2b5f2..52c6c7b 100644 --- a/dist/commands/index.js +++ b/dist/commands/index.js @@ -4,7 +4,6 @@ import start from "./start"; import dev from "./dev"; import build from "./build"; import { log } from "../utils/log"; -import rewritePages from "./rewrite-pages"; /** * # Describe Program */ @@ -18,7 +17,6 @@ program program.addCommand(dev()); program.addCommand(start()); program.addCommand(build()); -program.addCommand(rewritePages()); /** * # Handle Unavailable Commands */ diff --git a/dist/commands/rewrite-pages/index.d.ts b/dist/commands/rewrite-pages/index.d.ts deleted file mode 100644 index f202e7d..0000000 --- a/dist/commands/rewrite-pages/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { Command } from "commander"; -export default function (): Command; diff --git a/dist/commands/rewrite-pages/index.js b/dist/commands/rewrite-pages/index.js deleted file mode 100644 index df83af3..0000000 --- a/dist/commands/rewrite-pages/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Command } from "commander"; -import { log } from "../../utils/log"; -import init from "../../functions/init"; -import rewritePagesModule from "../../utils/rewrite-pages-module"; -export default function () { - return new Command("rewrite-pages") - .description("Rewrite pages from src to .bunext dir") - .action(async () => { - process.env.NODE_ENV = "production"; - process.env.BUILD = "true"; - await init(); - log.banner(); - log.build("Rewriting Pages ..."); - await rewritePagesModule(); - }); -} diff --git a/dist/functions/bundler/all-pages-bun-bundler.d.ts b/dist/functions/bundler/all-pages-bun-bundler.d.ts deleted file mode 100644 index 750a1d8..0000000 --- a/dist/functions/bundler/all-pages-bun-bundler.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { BundlerCTXMap } from "../../types"; -type Params = { - target?: "bun" | "browser"; - page_file_paths?: string[]; -}; -export default function allPagesBunBundler(params?: Params): Promise; -export {}; diff --git a/dist/functions/bundler/all-pages-bun-bundler.js b/dist/functions/bundler/all-pages-bun-bundler.js deleted file mode 100644 index 6e0eae4..0000000 --- a/dist/functions/bundler/all-pages-bun-bundler.js +++ /dev/null @@ -1,107 +0,0 @@ -import grabAllPages from "../../utils/grab-all-pages"; -import grabDirNames from "../../utils/grab-dir-names"; -import isDevelopment from "../../utils/is-development"; -import { log } from "../../utils/log"; -import tailwindcss from "bun-plugin-tailwind"; -import path from "path"; -import grabClientHydrationScript from "./grab-client-hydration-script"; -import { mkdirSync, rmSync } from "fs"; -import recordArtifacts from "./record-artifacts"; -const { HYDRATION_DST_DIR, BUNX_HYDRATION_SRC_DIR } = grabDirNames(); -export default async function allPagesBunBundler(params) { - const { target = "browser", page_file_paths } = params || {}; - const pages = grabAllPages({ exclude_api: true }); - const target_pages = page_file_paths?.[0] - ? pages.filter((p) => page_file_paths.includes(p.local_path)) - : pages; - if (!page_file_paths) { - global.PAGE_FILES = pages; - try { - rmSync(BUNX_HYDRATION_SRC_DIR, { recursive: true }); - } - catch { } - } - mkdirSync(BUNX_HYDRATION_SRC_DIR, { recursive: true }); - const dev = isDevelopment(); - const entryToPage = new Map(); - for (const page of target_pages) { - const txt = await grabClientHydrationScript({ - page_local_path: page.local_path, - }); - if (!txt) - continue; - const entryFile = path.join(BUNX_HYDRATION_SRC_DIR, `${page.url_path}.tsx`); - await Bun.write(entryFile, txt, { createPath: true }); - entryToPage.set(path.resolve(entryFile), page); - } - if (entryToPage.size === 0) - return; - const buildStart = performance.now(); - const define = { - "process.env.NODE_ENV": JSON.stringify(dev ? "development" : "production"), - }; - const result = await Bun.build({ - entrypoints: [...entryToPage.keys()], - outdir: HYDRATION_DST_DIR, - root: BUNX_HYDRATION_SRC_DIR, - minify: !dev, - format: "esm", - define, - naming: { - entry: "[dir]/[hash].[ext]", - chunk: "chunks/[hash].[ext]", - }, - plugins: [tailwindcss], - // plugins: [tailwindcss, BunSkipNonBrowserPlugin], - splitting: true, - target, - metafile: true, - external: [ - "react", - "react-dom", - "react-dom/client", - "react/jsx-runtime", - ], - }); - if (!result.success) { - for (const entry of result.logs) { - log.error(`[Build] ${entry.message}`); - } - return; - } - const artifacts = []; - for (const [outputPath, outputInfo] of Object.entries(result.metafile.outputs)) { - const entryPoint = outputInfo.entryPoint; - const cssBundle = outputInfo.cssBundle; - if (!entryPoint) - continue; - if (outputPath.match(/\.css$/)) - continue; - const page = entryToPage.get(path.resolve(entryPoint)); - if (!page) - continue; - artifacts.push({ - path: path.join(".bunext/public/pages", outputPath), - hash: path.basename(outputPath, path.extname(outputPath)), - type: outputPath.endsWith(".css") ? "text/css" : "text/javascript", - entrypoint: entryPoint, - css_path: cssBundle - ? path.join(".bunext/public/pages", cssBundle) - : undefined, - file_name: page.file_name, - local_path: page.local_path, - url_path: page.url_path, - }); - } - if (artifacts?.[0]) { - await recordArtifacts({ - artifacts, - page_file_paths, - }); - } - const elapsed = (performance.now() - buildStart).toFixed(0); - log.success(`[Built] in ${elapsed}ms`); - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - return artifacts; -} diff --git a/dist/functions/bundler/all-pages-bundler.d.ts b/dist/functions/bundler/all-pages-bundler.d.ts deleted file mode 100644 index 9b6b062..0000000 --- a/dist/functions/bundler/all-pages-bundler.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -type Params = { - /** - * Locations of the pages Files. - */ - page_file_paths?: string[]; -}; -export default function allPagesBundler(params?: Params): Promise; -export {}; diff --git a/dist/functions/bundler/all-pages-bundler.js b/dist/functions/bundler/all-pages-bundler.js deleted file mode 100644 index 3884cbd..0000000 --- a/dist/functions/bundler/all-pages-bundler.js +++ /dev/null @@ -1,142 +0,0 @@ -import * as esbuild from "esbuild"; -import grabAllPages from "../../utils/grab-all-pages"; -import grabDirNames from "../../utils/grab-dir-names"; -import isDevelopment from "../../utils/is-development"; -import { log } from "../../utils/log"; -import tailwindEsbuildPlugin from "../server/web-pages/tailwind-esbuild-plugin"; -import grabClientHydrationScript from "./grab-client-hydration-script"; -import grabArtifactsFromBundledResults from "./grab-artifacts-from-bundled-result"; -import { writeFileSync } from "fs"; -import recordArtifacts from "./record-artifacts"; -import stripServerSideLogic from "./strip-server-side-logic"; -const { HYDRATION_DST_DIR, HYDRATION_DST_DIR_MAP_JSON_FILE } = grabDirNames(); -let build_starts = 0; -const MAX_BUILD_STARTS = 10; -export default async function allPagesBundler(params) { - const { page_file_paths } = params || {}; - const pages = grabAllPages({ exclude_api: true }); - const target_pages = page_file_paths?.[0] - ? pages.filter((p) => page_file_paths.includes(p.local_path)) - : pages; - if (!page_file_paths) { - global.PAGE_FILES = pages; - } - const virtualEntries = {}; - const dev = isDevelopment(); - for (const page of target_pages) { - const key = page.local_path; - const txt = await grabClientHydrationScript({ - page_local_path: page.local_path, - }); - // if (page.url_path == "/index") { - // console.log("txt", txt); - // } - if (!txt) - continue; - // const final_tsx = stripServerSideLogic({ - // txt_code: txt, - // file_path: key, - // }); - // console.log("final_tsx", final_tsx); - virtualEntries[key] = txt; - } - const virtualPlugin = { - name: "virtual-entrypoints", - setup(build) { - build.onResolve({ filter: /^virtual:/ }, (args) => ({ - path: args.path.replace("virtual:", ""), - namespace: "virtual", - })); - build.onLoad({ filter: /.*/, namespace: "virtual" }, (args) => ({ - contents: virtualEntries[args.path], - loader: "tsx", - resolveDir: process.cwd(), - })); - }, - }; - let buildStart = 0; - const artifactTracker = { - name: "artifact-tracker", - setup(build) { - build.onStart(() => { - build_starts++; - buildStart = performance.now(); - if (build_starts == MAX_BUILD_STARTS) { - const error_msg = `Build Failed. Please check all your components and imports.`; - log.error(error_msg); - } - }); - // build.onEnd((result) => { - // }); - }, - }; - const entryPoints = Object.keys(virtualEntries).map((k) => `virtual:${k}`); - // let alias: any = {}; - // const excludes = [ - // "bun:sqlite", - // "path", - // "url", - // "events", - // "util", - // "crypto", - // "net", - // "tls", - // "fs", - // "node:path", - // "node:url", - // "node:process", - // "node:fs", - // "node:timers/promises", - // ]; - // for (let i = 0; i < excludes.length; i++) { - // const exclude = excludes[i]; - // alias[exclude] = "./empty.js"; - // } - // console.log("alias", alias); - const result = await esbuild.build({ - entryPoints, - outdir: HYDRATION_DST_DIR, - bundle: true, - minify: true, - format: "esm", - target: "es2020", - platform: "browser", - define: { - "process.env.NODE_ENV": JSON.stringify(dev ? "development" : "production"), - }, - entryNames: "[dir]/[hash]", - metafile: true, - plugins: [tailwindEsbuildPlugin, virtualPlugin, artifactTracker], - jsx: "automatic", - // splitting: true, - // logLevel: "silent", - external: [ - "react", - "react-dom", - "react-dom/client", - "react/jsx-runtime", - ], - // alias, - }); - if (result.errors.length > 0) { - for (const error of result.errors) { - const loc = error.location; - const location = loc - ? ` ${loc.file}:${loc.line}:${loc.column}` - : ""; - log.error(`[Build]${location} ${error.text}`); - } - return; - } - // const artifacts = grabArtifactsFromBundledResults({ - // result, - // }); - // if (artifacts?.[0]) { - // await recordArtifacts({ artifacts }); - // } - const elapsed = (performance.now() - buildStart).toFixed(0); - log.success(`[Built] in ${elapsed}ms`); - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - build_starts = 0; -} diff --git a/dist/functions/bundler/all-pages-esbuild-context-bundler-files.d.ts b/dist/functions/bundler/all-pages-esbuild-context-bundler-files.d.ts deleted file mode 100644 index 0fc436d..0000000 --- a/dist/functions/bundler/all-pages-esbuild-context-bundler-files.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -type Params = { - post_build_fn?: (params: { - artifacts: any[]; - }) => Promise | void; -}; -export default function allPagesESBuildContextBundlerFiles(params?: Params): Promise; -export {}; diff --git a/dist/functions/bundler/all-pages-esbuild-context-bundler-files.js b/dist/functions/bundler/all-pages-esbuild-context-bundler-files.js deleted file mode 100644 index 040272f..0000000 --- a/dist/functions/bundler/all-pages-esbuild-context-bundler-files.js +++ /dev/null @@ -1,58 +0,0 @@ -import * as esbuild from "esbuild"; -import grabAllPages from "../../utils/grab-all-pages"; -import grabDirNames from "../../utils/grab-dir-names"; -import isDevelopment from "../../utils/is-development"; -import tailwindEsbuildPlugin from "../server/web-pages/tailwind-esbuild-plugin"; -import grabClientHydrationScript from "./grab-client-hydration-script"; -import path from "path"; -import esbuildCTXArtifactTracker from "./plugins/esbuild-ctx-artifact-tracker"; -const { HYDRATION_DST_DIR, BUNX_HYDRATION_SRC_DIR } = grabDirNames(); -export default async function allPagesESBuildContextBundlerFiles(params) { - const pages = grabAllPages({ exclude_api: true }); - global.PAGE_FILES = pages; - const dev = isDevelopment(); - const entryToPage = new Map(); - for (const page of pages) { - const tsx = await grabClientHydrationScript({ - page_local_path: page.local_path, - }); - if (!tsx) - continue; - const entryFile = path.join(BUNX_HYDRATION_SRC_DIR, `${page.url_path}.tsx`); - await Bun.write(entryFile, tsx, { createPath: true }); - entryToPage.set(entryFile, { ...page, tsx }); - } - const entryPoints = [...entryToPage.keys()]; - const ctx = await esbuild.context({ - entryPoints, - outdir: HYDRATION_DST_DIR, - bundle: true, - minify: !dev, - format: "esm", - target: "es2020", - platform: "browser", - define: { - "process.env.NODE_ENV": JSON.stringify(dev ? "development" : "production"), - }, - entryNames: "[dir]/[hash]", - metafile: true, - plugins: [ - tailwindEsbuildPlugin, - esbuildCTXArtifactTracker({ - entryToPage, - post_build_fn: params?.post_build_fn, - }), - ], - jsx: "automatic", - splitting: true, - logLevel: "silent", - external: [ - "react", - "react-dom", - "react-dom/client", - "react/jsx-runtime", - ], - }); - await ctx.rebuild(); - global.BUNDLER_CTX = ctx; -} diff --git a/dist/functions/bundler/build-on-start-error-handler.d.ts b/dist/functions/bundler/build-on-start-error-handler.d.ts new file mode 100644 index 0000000..39e49be --- /dev/null +++ b/dist/functions/bundler/build-on-start-error-handler.d.ts @@ -0,0 +1,3 @@ +type Params = {}; +export default function buildOnstartErrorHandler(params?: Params): Promise; +export {}; diff --git a/dist/functions/bundler/build-on-start-error-handler.js b/dist/functions/bundler/build-on-start-error-handler.js new file mode 100644 index 0000000..1b2ca02 --- /dev/null +++ b/dist/functions/bundler/build-on-start-error-handler.js @@ -0,0 +1,14 @@ +import { log } from "../../utils/log"; +export default async function buildOnstartErrorHandler(params) { + // const error_msg = `Build Failed. Please check all your components and imports.`; + // log.error(error_msg); + global.BUNDLER_CTX_DISPOSED = true; + global.RECOMPILING = false; + global.IS_SERVER_COMPONENT = false; + await Promise.all([ + global.SSR_BUNDLER_CTX?.dispose(), + global.BUNDLER_CTX?.dispose(), + ]); + global.SSR_BUNDLER_CTX = undefined; + global.BUNDLER_CTX = undefined; +} diff --git a/dist/functions/bundler/init-pages.d.ts b/dist/functions/bundler/init-pages.d.ts deleted file mode 100644 index cd8502b..0000000 --- a/dist/functions/bundler/init-pages.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -type Params = { - log_time?: boolean; - debug?: boolean; - target_page_file?: string; -}; -export default function initPages(params?: Params): Promise; -export {}; diff --git a/dist/functions/bundler/init-pages.js b/dist/functions/bundler/init-pages.js deleted file mode 100644 index 4740397..0000000 --- a/dist/functions/bundler/init-pages.js +++ /dev/null @@ -1,44 +0,0 @@ -import grabDirNames from "../../utils/grab-dir-names"; -import isDevelopment from "../../utils/is-development"; -import grabAllPages from "../../utils/grab-all-pages"; -import { log } from "../../utils/log"; -import grabPageBundledReactComponent from "../server/web-pages/grab-page-bundled-react-component"; -import grabTsxStringModule from "../server/web-pages/grab-tsx-string-module"; -const {} = grabDirNames(); -export default async function initPages(params) { - const buildStart = performance.now(); - const dev = isDevelopment(); - const pages = grabAllPages({ - exclude_api: true, - }); - if (params?.log_time) { - log.build(`Compiling SSR for ${pages.length} pages ...`); - } - const tsx_map = []; - try { - for (let i = 0; i < pages.length; i++) { - const page = pages[i]; - if (params?.target_page_file && - page.local_path !== params.target_page_file) { - continue; - } - const { tsx } = (await grabPageBundledReactComponent({ - file_path: page.local_path, - return_tsx_only: true, - })) || {}; - if (!tsx) { - continue; - } - tsx_map.push({ - tsx, - page_file_path: page.local_path, - }); - } - await grabTsxStringModule({ tsx_map }); - } - catch (error) { } - const elapsed = (performance.now() - buildStart).toFixed(0); - if (params?.log_time) { - log.success(`[SSR Compiled] in ${elapsed}ms`); - } -} diff --git a/dist/functions/bundler/pages-ssr-context-bundler.js b/dist/functions/bundler/pages-ssr-context-bundler.js index e5f3a1d..a5be8e5 100644 --- a/dist/functions/bundler/pages-ssr-context-bundler.js +++ b/dist/functions/bundler/pages-ssr-context-bundler.js @@ -9,7 +9,7 @@ import ssrVirtualFilesPlugin from "./plugins/ssr-virtual-files-plugin"; import ssrCTXArtifactTracker from "./plugins/ssr-ctx-artifact-tracker"; const { BUNX_CWD_MODULE_CACHE_DIR } = grabDirNames(); export default async function pagesSSRContextBundler(params) { - const pages = grabAllPages({ exclude_api: true }); + const pages = grabAllPages(); const dev = isDevelopment(); if (global.SSR_BUNDLER_CTX) { await global.SSR_BUNDLER_CTX.dispose(); @@ -18,6 +18,11 @@ export default async function pagesSSRContextBundler(params) { const entryToPage = new Map(); const { root_file_path } = grabRootFilePath(); for (const page of pages) { + if (page.local_path.match(/\/pages\/api\//)) { + const ts = await Bun.file(page.local_path).text(); + entryToPage.set(page.local_path, { ...page, tsx: ts }); + continue; + } const tsx = grabPageReactComponentString({ file_path: page.local_path, root_file_path, @@ -57,7 +62,7 @@ export default async function pagesSSRContextBundler(params) { "react/jsx-runtime", "react/jsx-dev-runtime", ], - logLevel: "silent", + // logLevel: "silent", }); await global.SSR_BUNDLER_CTX.rebuild(); } diff --git a/dist/functions/bundler/plugins/esbuild-ctx-artifact-tracker.js b/dist/functions/bundler/plugins/esbuild-ctx-artifact-tracker.js index c3061be..f84d8e8 100644 --- a/dist/functions/bundler/plugins/esbuild-ctx-artifact-tracker.js +++ b/dist/functions/bundler/plugins/esbuild-ctx-artifact-tracker.js @@ -2,7 +2,8 @@ import {} from "esbuild"; import { log } from "../../../utils/log"; import grabArtifactsFromBundledResults from "../grab-artifacts-from-bundled-result"; import pagesSSRContextBundler from "../pages-ssr-context-bundler"; -let buildStart = 0; +import buildOnstartErrorHandler from "../build-on-start-error-handler"; +let build_start = 0; let build_starts = 0; const MAX_BUILD_STARTS = 2; export default function esbuildCTXArtifactTracker({ entryToPage, post_build_fn, }) { @@ -11,49 +12,19 @@ export default function esbuildCTXArtifactTracker({ entryToPage, post_build_fn, setup(build) { build.onStart(async () => { build_starts++; - buildStart = performance.now(); + build_start = performance.now(); if (build_starts == MAX_BUILD_STARTS) { - const error_msg = `Build Failed. Please check all your components and imports.`; - log.error(error_msg); - global.BUNDLER_CTX_DISPOSED = true; - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - await global.SSR_BUNDLER_CTX?.dispose(); - global.SSR_BUNDLER_CTX = undefined; - await global.BUNDLER_CTX?.dispose(); - global.BUNDLER_CTX = undefined; + await buildOnstartErrorHandler(); } }); build.onEnd((result) => { if (result.errors.length > 0) { - // for (const error of result.errors) { - // const loc = error.location; - // const location = loc - // ? ` ${loc.file}:${loc.line}:${loc.column}` - // : ""; - // log.error(`[Build]${location} ${error.text}`); - // } return; } - // if (result.errors.length) { - // console.error( - // esbuild.formatMessagesSync(result.errors, { - // kind: "error", - // }), - // ); - // } - // if (result.warnings.length) { - // console.warn( - // esbuild.formatMessagesSync(result.warnings, { - // kind: "warning", - // }), - // ); - // } const artifacts = grabArtifactsFromBundledResults({ result, entryToPage, }); - // console.log("artifacts", artifacts); if (artifacts?.[0] && artifacts.length > 0) { for (let i = 0; i < artifacts.length; i++) { const artifact = artifacts[i]; @@ -64,7 +35,7 @@ export default function esbuildCTXArtifactTracker({ entryToPage, post_build_fn, } post_build_fn?.({ artifacts }); } - const elapsed = (performance.now() - buildStart).toFixed(0); + const elapsed = (performance.now() - build_start).toFixed(0); log.success(`[Built] in ${elapsed}ms`); global.RECOMPILING = false; global.IS_SERVER_COMPONENT = false; diff --git a/dist/functions/bundler/plugins/ssr-ctx-artifact-tracker.js b/dist/functions/bundler/plugins/ssr-ctx-artifact-tracker.js index cdfa6e7..08fc1b9 100644 --- a/dist/functions/bundler/plugins/ssr-ctx-artifact-tracker.js +++ b/dist/functions/bundler/plugins/ssr-ctx-artifact-tracker.js @@ -1,7 +1,7 @@ import {} from "esbuild"; -import { log } from "../../../utils/log"; import grabArtifactsFromBundledResults from "../grab-artifacts-from-bundled-result"; -let buildStart = 0; +import buildOnstartErrorHandler from "../build-on-start-error-handler"; +let build_start = 0; let build_starts = 0; const MAX_BUILD_STARTS = 2; export default function ssrCTXArtifactTracker({ entryToPage, post_build_fn, }) { @@ -10,14 +10,14 @@ export default function ssrCTXArtifactTracker({ entryToPage, post_build_fn, }) { setup(build) { build.onStart(async () => { build_starts++; - buildStart = performance.now(); + build_start = performance.now(); if (build_starts == MAX_BUILD_STARTS) { - // const error_msg = `SSR Build Failed. Please check all your components and imports.`; - // log.error(error_msg); + await buildOnstartErrorHandler(); } }); build.onEnd((result) => { if (result.errors.length > 0) { + console.log("result.errors", result.errors); return; } const artifacts = grabArtifactsFromBundledResults({ diff --git a/dist/functions/server/clear-require-cache.d.ts b/dist/functions/server/clear-require-cache.d.ts new file mode 100644 index 0000000..98bb2e9 --- /dev/null +++ b/dist/functions/server/clear-require-cache.d.ts @@ -0,0 +1 @@ +export default function clearRequireCache(modulePath: string): void; diff --git a/dist/functions/server/clear-require-cache.js b/dist/functions/server/clear-require-cache.js new file mode 100644 index 0000000..63a9300 --- /dev/null +++ b/dist/functions/server/clear-require-cache.js @@ -0,0 +1,10 @@ +export default function clearRequireCache(modulePath) { + const resolved = require.resolve(modulePath); + const mod = require.cache[resolved]; + if (mod) { + mod.children?.forEach((child) => { + clearRequireCache(child.id); + }); + delete require.cache[resolved]; + } +} diff --git a/dist/functions/server/handle-routes.js b/dist/functions/server/handle-routes.js index a584311..17fd046 100644 --- a/dist/functions/server/handle-routes.js +++ b/dist/functions/server/handle-routes.js @@ -3,6 +3,9 @@ import grabConstants from "../../utils/grab-constants"; import grabRouter from "../../utils/grab-router"; import isDevelopment from "../../utils/is-development"; import _ from "lodash"; +import path from "path"; +import grabDirNames from "../../utils/grab-dir-names"; +const { ROOT_DIR } = grabDirNames(); export default async function ({ req }) { const url = new URL(req.url); const is_dev = isDevelopment(); @@ -22,9 +25,18 @@ export default async function ({ req }) { }); } const routeParams = await grabRouteParams({ req }); + let module; const now = Date.now(); - const import_path = is_dev ? `${match.filePath}?t=${now}` : match.filePath; - const module = await import(import_path); + if (global.SSR_BUNDLER_CTX_MAP?.[match.filePath]?.path) { + const target_import = path.join(ROOT_DIR, global.SSR_BUNDLER_CTX_MAP[match.filePath].path); + module = await import(`${target_import}?t=${now}`); + } + else { + const import_path = is_dev + ? `${match.filePath}?t=${now}` + : match.filePath; + module = await import(import_path); + } const config = module.config; const contentLength = req.headers.get("content-length"); if (contentLength) { diff --git a/dist/functions/server/rebuild-bundler.d.ts b/dist/functions/server/rebuild-bundler.d.ts deleted file mode 100644 index 3963a72..0000000 --- a/dist/functions/server/rebuild-bundler.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -type Params = { - target_file_paths?: string[]; -}; -export default function rebuildBundler(params?: Params): Promise; -export {}; diff --git a/dist/functions/server/rebuild-bundler.js b/dist/functions/server/rebuild-bundler.js deleted file mode 100644 index 6869d84..0000000 --- a/dist/functions/server/rebuild-bundler.js +++ /dev/null @@ -1,19 +0,0 @@ -import serverPostBuildFn from "./server-post-build-fn"; -import { log } from "../../utils/log"; -import allPagesBunBundler from "../bundler/all-pages-bun-bundler"; -import cleanupArtifacts from "./cleanup-artifacts"; -export default async function rebuildBundler(params) { - try { - global.ROUTER.reload(); - const new_artifacts = await allPagesBunBundler({ - page_file_paths: params?.target_file_paths, - }); - await serverPostBuildFn(); - if (new_artifacts?.[0]) { - cleanupArtifacts({ new_artifacts }); - } - } - catch (error) { - log.error(error); - } -} diff --git a/dist/functions/server/watcher-esbuild-ctx.js b/dist/functions/server/watcher-esbuild-ctx.js index bdb274c..38e5660 100644 --- a/dist/functions/server/watcher-esbuild-ctx.js +++ b/dist/functions/server/watcher-esbuild-ctx.js @@ -39,10 +39,9 @@ export default async function watcherEsbuildCTX() { return; } const target_files_match = /\.(tsx?|jsx?|css)$/; - const rebuild_skip_paths = /\/pages\/api\//; + // const rebuild_skip_paths = /\/pages\/api\//; if (event !== "rename") { - if (filename.match(target_files_match) && - !filename.match(rebuild_skip_paths)) { + if (filename.match(target_files_match)) { if (global.RECOMPILING) return; global.RECOMPILING = true; diff --git a/dist/functions/server/watcher.d.ts b/dist/functions/server/watcher.d.ts deleted file mode 100644 index 2d397af..0000000 --- a/dist/functions/server/watcher.d.ts +++ /dev/null @@ -1 +0,0 @@ -export default function watcher(): Promise; diff --git a/dist/functions/server/watcher.js b/dist/functions/server/watcher.js deleted file mode 100644 index 44d1469..0000000 --- a/dist/functions/server/watcher.js +++ /dev/null @@ -1,81 +0,0 @@ -import { watch, existsSync } from "fs"; -import path from "path"; -import grabDirNames from "../../utils/grab-dir-names"; -import rebuildBundler from "./rebuild-bundler"; -import { log } from "../../utils/log"; -const { ROOT_DIR } = grabDirNames(); -export default async function watcher() { - const pages_src_watcher = watch(ROOT_DIR, { - recursive: true, - persistent: true, - }, async (event, filename) => { - if (!filename) - return; - const full_file_path = path.join(ROOT_DIR, filename); - if (full_file_path.match(/\/styles$/)) { - global.RECOMPILING = true; - await Bun.sleep(1000); - await fullRebuild({ - msg: `Detected new \`styles\` directory. Rebuilding ...`, - }); - return; - } - const excluded_match = /node_modules\/|^public\/|^\.bunext\/|^\.git\/|^dist\/|bun\.lockb$/; - if (filename.match(excluded_match)) - return; - if (filename.match(/bunext.config\.ts/)) { - await fullRebuild({ - msg: `bunext.config.ts file changed. Rebuilding server ...`, - }); - return; - } - const target_files_match = /\.(tsx?|jsx?|css)$/; - if (event !== "rename") { - if (filename.match(target_files_match)) { - if (global.RECOMPILING) - return; - global.RECOMPILING = true; - await fullRebuild(); - } - return; - } - const is_file_of_interest = Boolean(filename.match(target_files_match)); - if (!is_file_of_interest) { - return; - } - if (!filename.match(/^src\/pages\/|\.css$/)) - return; - if (filename.match(/\/(--|\(| )/)) - return; - if (global.RECOMPILING) - return; - const action = existsSync(full_file_path) ? "created" : "deleted"; - const type = filename.match(/\.css$/) ? "Sylesheet" : "Page"; - await fullRebuild({ - msg: `${type} ${action}: ${filename}. Rebuilding ...`, - }); - }); - global.PAGES_SRC_WATCHER = pages_src_watcher; -} -async function fullRebuild(params) { - try { - const { msg } = params || {}; - global.RECOMPILING = true; - const target_file_paths = global.HMR_CONTROLLERS.map((hmr) => hmr.target_map?.local_path).filter((f) => typeof f == "string"); - if (msg) { - log.watch(msg); - } - await rebuildBundler({ target_file_paths }); - } - catch (error) { - log.error(error); - } - finally { - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - } - if (global.PAGES_SRC_WATCHER) { - global.PAGES_SRC_WATCHER.close(); - watcher(); - } -} diff --git a/dist/utils/rewrite-pages-module.d.ts b/dist/utils/rewrite-pages-module.d.ts deleted file mode 100644 index 2987a1b..0000000 --- a/dist/utils/rewrite-pages-module.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -type Params = { - page_file_path?: string | string[]; -}; -export default function rewritePagesModule(params?: Params): Promise; -export {}; diff --git a/dist/utils/rewrite-pages-module.js b/dist/utils/rewrite-pages-module.js deleted file mode 100644 index 16b7815..0000000 --- a/dist/utils/rewrite-pages-module.js +++ /dev/null @@ -1,37 +0,0 @@ -import grabAllPages from "./grab-all-pages"; -import pagePathTransform from "./page-path-transform"; -import stripServerSideLogic from "../functions/bundler/strip-server-side-logic"; -import grabRootFilePath from "../functions/server/web-pages/grab-root-file-path"; -import { existsSync } from "fs"; -export default async function rewritePagesModule(params) { - const { page_file_path } = params || {}; - let target_pages; - if (page_file_path) { - target_pages = Array.isArray(page_file_path) - ? page_file_path - : [page_file_path]; - } - else { - const pages = grabAllPages({ exclude_api: true }); - target_pages = pages.map((p) => p.local_path); - } - for (let i = 0; i < target_pages.length; i++) { - const page_path = target_pages[i]; - await transformFile(page_path); - } - const { root_file_path } = grabRootFilePath(); - if (root_file_path && existsSync(root_file_path)) { - await transformFile(root_file_path); - } -} -async function transformFile(page_path) { - const dst_path = pagePathTransform({ page_path }); - const origin_page_content = await Bun.file(page_path).text(); - const dst_page_content = stripServerSideLogic({ - txt_code: origin_page_content, - file_path: page_path, - }); - await Bun.write(dst_path, dst_page_content, { - createPath: true, - }); -} diff --git a/package.json b/package.json index 40050c9..2f0eb7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@moduletrace/bunext", - "version": "1.0.70", + "version": "1.0.71", "main": "dist/index.js", "module": "index.ts", "dependencies": { diff --git a/src/commands/index.ts b/src/commands/index.ts index 999a48b..f96d67b 100755 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -5,7 +5,6 @@ import start from "./start"; import dev from "./dev"; import build from "./build"; import { log } from "../utils/log"; -import rewritePages from "./rewrite-pages"; /** * # Describe Program @@ -21,7 +20,6 @@ program program.addCommand(dev()); program.addCommand(start()); program.addCommand(build()); -program.addCommand(rewritePages()); /** * # Handle Unavailable Commands diff --git a/src/commands/rewrite-pages/index.ts b/src/commands/rewrite-pages/index.ts deleted file mode 100644 index 4060709..0000000 --- a/src/commands/rewrite-pages/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Command } from "commander"; -import { log } from "../../utils/log"; -import init from "../../functions/init"; -import rewritePagesModule from "../../utils/rewrite-pages-module"; - -export default function () { - return new Command("rewrite-pages") - .description("Rewrite pages from src to .bunext dir") - .action(async () => { - process.env.NODE_ENV = "production"; - process.env.BUILD = "true"; - - await init(); - - log.banner(); - log.build("Rewriting Pages ..."); - - await rewritePagesModule(); - }); -} diff --git a/src/functions/bundler/all-pages-bun-bundler.ts b/src/functions/bundler/all-pages-bun-bundler.ts deleted file mode 100644 index 0fba1c3..0000000 --- a/src/functions/bundler/all-pages-bun-bundler.ts +++ /dev/null @@ -1,135 +0,0 @@ -import grabAllPages from "../../utils/grab-all-pages"; -import grabDirNames from "../../utils/grab-dir-names"; -import isDevelopment from "../../utils/is-development"; -import { log } from "../../utils/log"; -import tailwindcss from "bun-plugin-tailwind"; -import type { BundlerCTXMap, PageFiles } from "../../types"; -import path from "path"; -import grabClientHydrationScript from "./grab-client-hydration-script"; -import { mkdirSync, rmSync } from "fs"; -import recordArtifacts from "./record-artifacts"; - -const { HYDRATION_DST_DIR, BUNX_HYDRATION_SRC_DIR } = grabDirNames(); - -type Params = { - target?: "bun" | "browser"; - page_file_paths?: string[]; -}; - -export default async function allPagesBunBundler(params?: Params) { - const { target = "browser", page_file_paths } = params || {}; - const pages = grabAllPages({ exclude_api: true }); - - const target_pages = page_file_paths?.[0] - ? pages.filter((p) => page_file_paths.includes(p.local_path)) - : pages; - - if (!page_file_paths) { - global.PAGE_FILES = pages; - try { - rmSync(BUNX_HYDRATION_SRC_DIR, { recursive: true }); - } catch {} - } - mkdirSync(BUNX_HYDRATION_SRC_DIR, { recursive: true }); - - const dev = isDevelopment(); - - const entryToPage = new Map(); - - for (const page of target_pages) { - const txt = await grabClientHydrationScript({ - page_local_path: page.local_path, - }); - if (!txt) continue; - - const entryFile = path.join( - BUNX_HYDRATION_SRC_DIR, - `${page.url_path}.tsx`, - ); - await Bun.write(entryFile, txt, { createPath: true }); - entryToPage.set(path.resolve(entryFile), page); - } - - if (entryToPage.size === 0) return; - - const buildStart = performance.now(); - - const define = { - "process.env.NODE_ENV": JSON.stringify( - dev ? "development" : "production", - ), - }; - - const result = await Bun.build({ - entrypoints: [...entryToPage.keys()], - outdir: HYDRATION_DST_DIR, - root: BUNX_HYDRATION_SRC_DIR, - minify: !dev, - format: "esm", - define, - naming: { - entry: "[dir]/[hash].[ext]", - chunk: "chunks/[hash].[ext]", - }, - plugins: [tailwindcss], - // plugins: [tailwindcss, BunSkipNonBrowserPlugin], - splitting: true, - target, - metafile: true, - external: [ - "react", - "react-dom", - "react-dom/client", - "react/jsx-runtime", - ], - }); - - if (!result.success) { - for (const entry of result.logs) { - log.error(`[Build] ${entry.message}`); - } - return; - } - - const artifacts: BundlerCTXMap[] = []; - - for (const [outputPath, outputInfo] of Object.entries( - result.metafile!.outputs, - )) { - const entryPoint = outputInfo.entryPoint; - const cssBundle = outputInfo.cssBundle; - if (!entryPoint) continue; - if (outputPath.match(/\.css$/)) continue; - - const page = entryToPage.get(path.resolve(entryPoint)); - if (!page) continue; - - artifacts.push({ - path: path.join(".bunext/public/pages", outputPath), - hash: path.basename(outputPath, path.extname(outputPath)), - type: outputPath.endsWith(".css") ? "text/css" : "text/javascript", - entrypoint: entryPoint, - css_path: cssBundle - ? path.join(".bunext/public/pages", cssBundle) - : undefined, - file_name: page.file_name, - local_path: page.local_path, - url_path: page.url_path, - }); - } - - if (artifacts?.[0]) { - await recordArtifacts({ - artifacts, - page_file_paths, - }); - } - - const elapsed = (performance.now() - buildStart).toFixed(0); - log.success(`[Built] in ${elapsed}ms`); - - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - - return artifacts; -} diff --git a/src/functions/bundler/all-pages-bundler.ts b/src/functions/bundler/all-pages-bundler.ts deleted file mode 100644 index 518c6f8..0000000 --- a/src/functions/bundler/all-pages-bundler.ts +++ /dev/null @@ -1,183 +0,0 @@ -import * as esbuild from "esbuild"; -import grabAllPages from "../../utils/grab-all-pages"; -import grabDirNames from "../../utils/grab-dir-names"; -import isDevelopment from "../../utils/is-development"; -import { log } from "../../utils/log"; -import tailwindEsbuildPlugin from "../server/web-pages/tailwind-esbuild-plugin"; -import grabClientHydrationScript from "./grab-client-hydration-script"; -import grabArtifactsFromBundledResults from "./grab-artifacts-from-bundled-result"; -import { writeFileSync } from "fs"; -import type { BundlerCTXMap } from "../../types"; -import recordArtifacts from "./record-artifacts"; -import stripServerSideLogic from "./strip-server-side-logic"; - -const { HYDRATION_DST_DIR, HYDRATION_DST_DIR_MAP_JSON_FILE } = grabDirNames(); - -let build_starts = 0; -const MAX_BUILD_STARTS = 10; - -type Params = { - /** - * Locations of the pages Files. - */ - page_file_paths?: string[]; -}; - -export default async function allPagesBundler(params?: Params) { - const { page_file_paths } = params || {}; - - const pages = grabAllPages({ exclude_api: true }); - - const target_pages = page_file_paths?.[0] - ? pages.filter((p) => page_file_paths.includes(p.local_path)) - : pages; - - if (!page_file_paths) { - global.PAGE_FILES = pages; - } - - const virtualEntries: Record = {}; - const dev = isDevelopment(); - - for (const page of target_pages) { - const key = page.local_path; - - const txt = await grabClientHydrationScript({ - page_local_path: page.local_path, - }); - - // if (page.url_path == "/index") { - // console.log("txt", txt); - // } - - if (!txt) continue; - - // const final_tsx = stripServerSideLogic({ - // txt_code: txt, - // file_path: key, - // }); - - // console.log("final_tsx", final_tsx); - - virtualEntries[key] = txt; - } - - const virtualPlugin: esbuild.Plugin = { - name: "virtual-entrypoints", - setup(build) { - build.onResolve({ filter: /^virtual:/ }, (args) => ({ - path: args.path.replace("virtual:", ""), - namespace: "virtual", - })); - - build.onLoad({ filter: /.*/, namespace: "virtual" }, (args) => ({ - contents: virtualEntries[args.path], - loader: "tsx", - resolveDir: process.cwd(), - })); - }, - }; - - let buildStart = 0; - - const artifactTracker: esbuild.Plugin = { - name: "artifact-tracker", - setup(build) { - build.onStart(() => { - build_starts++; - buildStart = performance.now(); - - if (build_starts == MAX_BUILD_STARTS) { - const error_msg = `Build Failed. Please check all your components and imports.`; - log.error(error_msg); - } - }); - - // build.onEnd((result) => { - - // }); - }, - }; - - const entryPoints = Object.keys(virtualEntries).map((k) => `virtual:${k}`); - - // let alias: any = {}; - // const excludes = [ - // "bun:sqlite", - // "path", - // "url", - // "events", - // "util", - // "crypto", - // "net", - // "tls", - // "fs", - // "node:path", - // "node:url", - // "node:process", - // "node:fs", - // "node:timers/promises", - // ]; - - // for (let i = 0; i < excludes.length; i++) { - // const exclude = excludes[i]; - // alias[exclude] = "./empty.js"; - // } - - // console.log("alias", alias); - - const result = await esbuild.build({ - entryPoints, - outdir: HYDRATION_DST_DIR, - bundle: true, - minify: true, - format: "esm", - target: "es2020", - platform: "browser", - define: { - "process.env.NODE_ENV": JSON.stringify( - dev ? "development" : "production", - ), - }, - entryNames: "[dir]/[hash]", - metafile: true, - plugins: [tailwindEsbuildPlugin, virtualPlugin, artifactTracker], - jsx: "automatic", - // splitting: true, - // logLevel: "silent", - external: [ - "react", - "react-dom", - "react-dom/client", - "react/jsx-runtime", - ], - // alias, - }); - - if (result.errors.length > 0) { - for (const error of result.errors) { - const loc = error.location; - const location = loc - ? ` ${loc.file}:${loc.line}:${loc.column}` - : ""; - log.error(`[Build]${location} ${error.text}`); - } - return; - } - - // const artifacts = grabArtifactsFromBundledResults({ - // result, - // }); - - // if (artifacts?.[0]) { - // await recordArtifacts({ artifacts }); - // } - - const elapsed = (performance.now() - buildStart).toFixed(0); - log.success(`[Built] in ${elapsed}ms`); - - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - - build_starts = 0; -} diff --git a/src/functions/bundler/all-pages-esbuild-context-bundler-files.ts b/src/functions/bundler/all-pages-esbuild-context-bundler-files.ts deleted file mode 100644 index 4616f35..0000000 --- a/src/functions/bundler/all-pages-esbuild-context-bundler-files.ts +++ /dev/null @@ -1,81 +0,0 @@ -import * as esbuild from "esbuild"; -import grabAllPages from "../../utils/grab-all-pages"; -import grabDirNames from "../../utils/grab-dir-names"; -import isDevelopment from "../../utils/is-development"; -import tailwindEsbuildPlugin from "../server/web-pages/tailwind-esbuild-plugin"; -import grabClientHydrationScript from "./grab-client-hydration-script"; -import type { PageFiles } from "../../types"; -import path from "path"; -import esbuildCTXArtifactTracker from "./plugins/esbuild-ctx-artifact-tracker"; - -const { HYDRATION_DST_DIR, BUNX_HYDRATION_SRC_DIR } = grabDirNames(); - -type Params = { - post_build_fn?: (params: { artifacts: any[] }) => Promise | void; -}; - -export default async function allPagesESBuildContextBundlerFiles( - params?: Params, -) { - const pages = grabAllPages({ exclude_api: true }); - - global.PAGE_FILES = pages; - - const dev = isDevelopment(); - - const entryToPage = new Map(); - - for (const page of pages) { - const tsx = await grabClientHydrationScript({ - page_local_path: page.local_path, - }); - if (!tsx) continue; - - const entryFile = path.join( - BUNX_HYDRATION_SRC_DIR, - `${page.url_path}.tsx`, - ); - - await Bun.write(entryFile, tsx, { createPath: true }); - entryToPage.set(entryFile, { ...page, tsx }); - } - - const entryPoints = [...entryToPage.keys()]; - - const ctx = await esbuild.context({ - entryPoints, - outdir: HYDRATION_DST_DIR, - bundle: true, - minify: !dev, - format: "esm", - target: "es2020", - platform: "browser", - define: { - "process.env.NODE_ENV": JSON.stringify( - dev ? "development" : "production", - ), - }, - entryNames: "[dir]/[hash]", - metafile: true, - plugins: [ - tailwindEsbuildPlugin, - esbuildCTXArtifactTracker({ - entryToPage, - post_build_fn: params?.post_build_fn, - }), - ], - jsx: "automatic", - splitting: true, - logLevel: "silent", - external: [ - "react", - "react-dom", - "react-dom/client", - "react/jsx-runtime", - ], - }); - - await ctx.rebuild(); - - global.BUNDLER_CTX = ctx; -} diff --git a/src/functions/bundler/build-on-start-error-handler.ts b/src/functions/bundler/build-on-start-error-handler.ts new file mode 100644 index 0000000..88674e5 --- /dev/null +++ b/src/functions/bundler/build-on-start-error-handler.ts @@ -0,0 +1,21 @@ +import { log } from "../../utils/log"; + +type Params = {}; + +export default async function buildOnstartErrorHandler(params?: Params) { + // const error_msg = `Build Failed. Please check all your components and imports.`; + // log.error(error_msg); + + global.BUNDLER_CTX_DISPOSED = true; + + global.RECOMPILING = false; + global.IS_SERVER_COMPONENT = false; + + await Promise.all([ + global.SSR_BUNDLER_CTX?.dispose(), + global.BUNDLER_CTX?.dispose(), + ]); + + global.SSR_BUNDLER_CTX = undefined; + global.BUNDLER_CTX = undefined; +} diff --git a/src/functions/bundler/init-pages.ts b/src/functions/bundler/init-pages.ts deleted file mode 100644 index 8ec7225..0000000 --- a/src/functions/bundler/init-pages.ts +++ /dev/null @@ -1,65 +0,0 @@ -import grabDirNames from "../../utils/grab-dir-names"; -import isDevelopment from "../../utils/is-development"; -import grabAllPages from "../../utils/grab-all-pages"; -import { log } from "../../utils/log"; -import type { GrabTSXModuleBatchMap } from "../../types"; -import grabPageBundledReactComponent from "../server/web-pages/grab-page-bundled-react-component"; -import grabTsxStringModule from "../server/web-pages/grab-tsx-string-module"; - -const {} = grabDirNames(); - -type Params = { - log_time?: boolean; - debug?: boolean; - target_page_file?: string; -}; - -export default async function initPages(params?: Params) { - const buildStart = performance.now(); - - const dev = isDevelopment(); - const pages = grabAllPages({ - exclude_api: true, - }); - - if (params?.log_time) { - log.build(`Compiling SSR for ${pages.length} pages ...`); - } - - const tsx_map: GrabTSXModuleBatchMap[] = []; - - try { - for (let i = 0; i < pages.length; i++) { - const page = pages[i]; - if ( - params?.target_page_file && - page.local_path !== params.target_page_file - ) { - continue; - } - - const { tsx } = - (await grabPageBundledReactComponent({ - file_path: page.local_path, - return_tsx_only: true, - })) || {}; - - if (!tsx) { - continue; - } - - tsx_map.push({ - tsx, - page_file_path: page.local_path, - }); - } - - await grabTsxStringModule({ tsx_map }); - } catch (error) {} - - const elapsed = (performance.now() - buildStart).toFixed(0); - - if (params?.log_time) { - log.success(`[SSR Compiled] in ${elapsed}ms`); - } -} diff --git a/src/functions/bundler/pages-ssr-context-bundler.ts b/src/functions/bundler/pages-ssr-context-bundler.ts index eb4155c..09cb180 100644 --- a/src/functions/bundler/pages-ssr-context-bundler.ts +++ b/src/functions/bundler/pages-ssr-context-bundler.ts @@ -16,7 +16,7 @@ type Params = { }; export default async function pagesSSRContextBundler(params?: Params) { - const pages = grabAllPages({ exclude_api: true }); + const pages = grabAllPages(); const dev = isDevelopment(); if (global.SSR_BUNDLER_CTX) { @@ -28,6 +28,12 @@ export default async function pagesSSRContextBundler(params?: Params) { const { root_file_path } = grabRootFilePath(); for (const page of pages) { + if (page.local_path.match(/\/pages\/api\//)) { + const ts = await Bun.file(page.local_path).text(); + entryToPage.set(page.local_path, { ...page, tsx: ts }); + continue; + } + const tsx = grabPageReactComponentString({ file_path: page.local_path, root_file_path, @@ -72,7 +78,7 @@ export default async function pagesSSRContextBundler(params?: Params) { "react/jsx-runtime", "react/jsx-dev-runtime", ], - logLevel: "silent", + // logLevel: "silent", }); await global.SSR_BUNDLER_CTX.rebuild(); diff --git a/src/functions/bundler/plugins/esbuild-ctx-artifact-tracker.ts b/src/functions/bundler/plugins/esbuild-ctx-artifact-tracker.ts index cdc353a..55bcdbb 100644 --- a/src/functions/bundler/plugins/esbuild-ctx-artifact-tracker.ts +++ b/src/functions/bundler/plugins/esbuild-ctx-artifact-tracker.ts @@ -3,8 +3,9 @@ import type { PageFiles } from "../../../types"; import { log } from "../../../utils/log"; import grabArtifactsFromBundledResults from "../grab-artifacts-from-bundled-result"; import pagesSSRContextBundler from "../pages-ssr-context-bundler"; +import buildOnstartErrorHandler from "../build-on-start-error-handler"; -let buildStart = 0; +let build_start = 0; let build_starts = 0; const MAX_BUILD_STARTS = 2; @@ -27,60 +28,22 @@ export default function esbuildCTXArtifactTracker({ setup(build) { build.onStart(async () => { build_starts++; - buildStart = performance.now(); - + build_start = performance.now(); if (build_starts == MAX_BUILD_STARTS) { - const error_msg = `Build Failed. Please check all your components and imports.`; - log.error(error_msg); - - global.BUNDLER_CTX_DISPOSED = true; - - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - - await global.SSR_BUNDLER_CTX?.dispose(); - global.SSR_BUNDLER_CTX = undefined; - - await global.BUNDLER_CTX?.dispose(); - global.BUNDLER_CTX = undefined; + await buildOnstartErrorHandler(); } }); build.onEnd((result) => { if (result.errors.length > 0) { - // for (const error of result.errors) { - // const loc = error.location; - // const location = loc - // ? ` ${loc.file}:${loc.line}:${loc.column}` - // : ""; - // log.error(`[Build]${location} ${error.text}`); - // } return; } - // if (result.errors.length) { - // console.error( - // esbuild.formatMessagesSync(result.errors, { - // kind: "error", - // }), - // ); - // } - - // if (result.warnings.length) { - // console.warn( - // esbuild.formatMessagesSync(result.warnings, { - // kind: "warning", - // }), - // ); - // } - const artifacts = grabArtifactsFromBundledResults({ result, entryToPage, }); - // console.log("artifacts", artifacts); - if (artifacts?.[0] && artifacts.length > 0) { for (let i = 0; i < artifacts.length; i++) { const artifact = artifacts[i]; @@ -93,7 +56,7 @@ export default function esbuildCTXArtifactTracker({ post_build_fn?.({ artifacts }); } - const elapsed = (performance.now() - buildStart).toFixed(0); + const elapsed = (performance.now() - build_start).toFixed(0); log.success(`[Built] in ${elapsed}ms`); global.RECOMPILING = false; diff --git a/src/functions/bundler/plugins/ssr-ctx-artifact-tracker.ts b/src/functions/bundler/plugins/ssr-ctx-artifact-tracker.ts index 79678f8..4c300d8 100644 --- a/src/functions/bundler/plugins/ssr-ctx-artifact-tracker.ts +++ b/src/functions/bundler/plugins/ssr-ctx-artifact-tracker.ts @@ -1,9 +1,9 @@ import { type Plugin } from "esbuild"; import type { PageFiles } from "../../../types"; -import { log } from "../../../utils/log"; import grabArtifactsFromBundledResults from "../grab-artifacts-from-bundled-result"; +import buildOnstartErrorHandler from "../build-on-start-error-handler"; -let buildStart = 0; +let build_start = 0; let build_starts = 0; const MAX_BUILD_STARTS = 2; @@ -26,16 +26,15 @@ export default function ssrCTXArtifactTracker({ setup(build) { build.onStart(async () => { build_starts++; - buildStart = performance.now(); - + build_start = performance.now(); if (build_starts == MAX_BUILD_STARTS) { - // const error_msg = `SSR Build Failed. Please check all your components and imports.`; - // log.error(error_msg); + await buildOnstartErrorHandler(); } }); build.onEnd((result) => { if (result.errors.length > 0) { + console.log("result.errors", result.errors); return; } diff --git a/src/functions/server/clear-require-cache.ts b/src/functions/server/clear-require-cache.ts new file mode 100644 index 0000000..e3eba61 --- /dev/null +++ b/src/functions/server/clear-require-cache.ts @@ -0,0 +1,10 @@ +export default function clearRequireCache(modulePath: string) { + const resolved = require.resolve(modulePath); + const mod = require.cache[resolved]; + if (mod) { + mod.children?.forEach((child) => { + clearRequireCache(child.id); + }); + delete require.cache[resolved]; + } +} diff --git a/src/functions/server/handle-routes.ts b/src/functions/server/handle-routes.ts index 5708d7a..469c4f5 100644 --- a/src/functions/server/handle-routes.ts +++ b/src/functions/server/handle-routes.ts @@ -8,6 +8,10 @@ import grabConstants from "../../utils/grab-constants"; import grabRouter from "../../utils/grab-router"; import isDevelopment from "../../utils/is-development"; import _ from "lodash"; +import path from "path"; +import grabDirNames from "../../utils/grab-dir-names"; + +const { ROOT_DIR } = grabDirNames(); type Params = { req: Request; @@ -42,10 +46,23 @@ export default async function ({ req }: Params): Promise { const routeParams: BunxRouteParams = await grabRouteParams({ req }); + let module: any; const now = Date.now(); - const import_path = is_dev ? `${match.filePath}?t=${now}` : match.filePath; - const module = await import(import_path); + if (global.SSR_BUNDLER_CTX_MAP?.[match.filePath]?.path) { + const target_import = path.join( + ROOT_DIR, + global.SSR_BUNDLER_CTX_MAP[match.filePath].path, + ); + + module = await import(`${target_import}?t=${now}`); + } else { + const import_path = is_dev + ? `${match.filePath}?t=${now}` + : match.filePath; + module = await import(import_path); + } + const config = module.config as BunextServerRouteConfig | undefined; const contentLength = req.headers.get("content-length"); diff --git a/src/functions/server/rebuild-bundler.tsx b/src/functions/server/rebuild-bundler.tsx deleted file mode 100644 index 71f38f7..0000000 --- a/src/functions/server/rebuild-bundler.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import serverPostBuildFn from "./server-post-build-fn"; -import { log } from "../../utils/log"; -import allPagesBunBundler from "../bundler/all-pages-bun-bundler"; -import cleanupArtifacts from "./cleanup-artifacts"; - -type Params = { - target_file_paths?: string[]; -}; - -export default async function rebuildBundler(params?: Params) { - try { - global.ROUTER.reload(); - - const new_artifacts = await allPagesBunBundler({ - page_file_paths: params?.target_file_paths, - }); - - await serverPostBuildFn(); - - if (new_artifacts?.[0]) { - cleanupArtifacts({ new_artifacts }); - } - } catch (error: any) { - log.error(error); - } -} diff --git a/src/functions/server/watcher-esbuild-ctx.ts b/src/functions/server/watcher-esbuild-ctx.ts index 7bb3f6f..3b703ce 100644 --- a/src/functions/server/watcher-esbuild-ctx.ts +++ b/src/functions/server/watcher-esbuild-ctx.ts @@ -50,13 +50,10 @@ export default async function watcherEsbuildCTX() { } const target_files_match = /\.(tsx?|jsx?|css)$/; - const rebuild_skip_paths = /\/pages\/api\//; + // const rebuild_skip_paths = /\/pages\/api\//; if (event !== "rename") { - if ( - filename.match(target_files_match) && - !filename.match(rebuild_skip_paths) - ) { + if (filename.match(target_files_match)) { if (global.RECOMPILING) return; global.RECOMPILING = true; diff --git a/src/functions/server/watcher.ts b/src/functions/server/watcher.ts deleted file mode 100644 index e194e52..0000000 --- a/src/functions/server/watcher.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { watch, existsSync } from "fs"; -import path from "path"; -import grabDirNames from "../../utils/grab-dir-names"; -import rebuildBundler from "./rebuild-bundler"; -import { log } from "../../utils/log"; - -const { ROOT_DIR } = grabDirNames(); - -export default async function watcher() { - const pages_src_watcher = watch( - ROOT_DIR, - { - recursive: true, - persistent: true, - }, - async (event, filename) => { - if (!filename) return; - - const full_file_path = path.join(ROOT_DIR, filename); - - if (full_file_path.match(/\/styles$/)) { - global.RECOMPILING = true; - await Bun.sleep(1000); - await fullRebuild({ - msg: `Detected new \`styles\` directory. Rebuilding ...`, - }); - return; - } - - const excluded_match = - /node_modules\/|^public\/|^\.bunext\/|^\.git\/|^dist\/|bun\.lockb$/; - - if (filename.match(excluded_match)) return; - - if (filename.match(/bunext.config\.ts/)) { - await fullRebuild({ - msg: `bunext.config.ts file changed. Rebuilding server ...`, - }); - return; - } - - const target_files_match = /\.(tsx?|jsx?|css)$/; - - if (event !== "rename") { - if (filename.match(target_files_match)) { - if (global.RECOMPILING) return; - global.RECOMPILING = true; - await fullRebuild(); - } - return; - } - - const is_file_of_interest = Boolean( - filename.match(target_files_match), - ); - - if (!is_file_of_interest) { - return; - } - - if (!filename.match(/^src\/pages\/|\.css$/)) return; - if (filename.match(/\/(--|\(| )/)) return; - - if (global.RECOMPILING) return; - - const action = existsSync(full_file_path) ? "created" : "deleted"; - const type = filename.match(/\.css$/) ? "Sylesheet" : "Page"; - - await fullRebuild({ - msg: `${type} ${action}: ${filename}. Rebuilding ...`, - }); - }, - ); - - global.PAGES_SRC_WATCHER = pages_src_watcher; -} - -async function fullRebuild(params?: { msg?: string }) { - try { - const { msg } = params || {}; - - global.RECOMPILING = true; - - const target_file_paths = global.HMR_CONTROLLERS.map( - (hmr) => hmr.target_map?.local_path, - ).filter((f) => typeof f == "string"); - - if (msg) { - log.watch(msg); - } - - await rebuildBundler({ target_file_paths }); - } catch (error: any) { - log.error(error); - } finally { - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - } - - if (global.PAGES_SRC_WATCHER) { - global.PAGES_SRC_WATCHER.close(); - watcher(); - } -} diff --git a/src/utils/rewrite-pages-module.ts b/src/utils/rewrite-pages-module.ts deleted file mode 100644 index c6ee863..0000000 --- a/src/utils/rewrite-pages-module.ts +++ /dev/null @@ -1,48 +0,0 @@ -import grabAllPages from "./grab-all-pages"; -import pagePathTransform from "./page-path-transform"; -import stripServerSideLogic from "../functions/bundler/strip-server-side-logic"; -import grabRootFilePath from "../functions/server/web-pages/grab-root-file-path"; -import { existsSync } from "fs"; - -type Params = { - page_file_path?: string | string[]; -}; - -export default async function rewritePagesModule(params?: Params) { - const { page_file_path } = params || {}; - let target_pages: string[] | undefined; - - if (page_file_path) { - target_pages = Array.isArray(page_file_path) - ? page_file_path - : [page_file_path]; - } else { - const pages = grabAllPages({ exclude_api: true }); - target_pages = pages.map((p) => p.local_path); - } - - for (let i = 0; i < target_pages.length; i++) { - const page_path = target_pages[i]; - await transformFile(page_path); - } - - const { root_file_path } = grabRootFilePath(); - - if (root_file_path && existsSync(root_file_path)) { - await transformFile(root_file_path); - } -} - -async function transformFile(page_path: string) { - const dst_path = pagePathTransform({ page_path }); - - const origin_page_content = await Bun.file(page_path).text(); - const dst_page_content = stripServerSideLogic({ - txt_code: origin_page_content, - file_path: page_path, - }); - - await Bun.write(dst_path, dst_page_content, { - createPath: true, - }); -}