UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

656 lines (640 loc) 31.1 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: !0 }); }, __copyProps = (to, from, except, desc) => { if (from && typeof from == "object" || typeof from == "function") for (let key of __getOwnPropNames(from)) !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target, mod )), __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod); var build_exports = {}; __export(build_exports, { build: () => build }); module.exports = __toCommonJS(build_exports); var import_node_module = require("node:module"), import_node_os = require("node:os"), import_node_path = __toESM(require("node:path"), 1), import_fs_extra = __toESM(require("fs-extra"), 1), import_micromatch = __toESM(require("micromatch"), 1), import_vite = require("vite"), import_vxrn = require("vxrn"), constants = __toESM(require("../constants"), 1), import_setServerGlobals = require("../server/setServerGlobals"), import_getPathnameFromFilePath = require("../utils/getPathnameFromFilePath"), import_getRouterRootFromOneOptions = require("../utils/getRouterRootFromOneOptions"), import_isRolldown = require("../utils/isRolldown"), import_toAbsolute = require("../utils/toAbsolute"), import_buildVercelOutputDirectory = require("../vercel/build/buildVercelOutputDirectory"), import_getManifest = require("../vite/getManifest"), import_loadConfig = require("../vite/loadConfig"), import_one_server_only = require("../vite/one-server-only"), import_buildPage = require("./buildPage"), import_checkNodeVersion = require("./checkNodeVersion"), import_workerPool = require("./workerPool"), import_generateSitemap = require("./generateSitemap"), import_label_process = require("./label-process"), import_pLimit = require("../utils/pLimit"); const import_meta = {}, { ensureDir, writeJSON } = import_fs_extra.default, BUILD_CONCURRENCY = process.env.ONE_BUILD_CONCURRENCY ? Math.max(1, parseInt(process.env.ONE_BUILD_CONCURRENCY, 10)) : Math.max(1, Math.min((0, import_node_os.cpus)().length, 8)); function shouldUseWorkers(oneOptions) { return process.env.ONE_BUILD_WORKERS === "0" ? !1 : process.env.ONE_BUILD_WORKERS === "1" ? !0 : oneOptions?.build?.workers !== !1; } process.on("uncaughtException", (err) => { console.error(err?.message || err); }); async function build(args) { process.env.IS_VXRN_CLI = "true", process.env.NODE_ENV ? process.env.NODE_ENV !== "production" && console.warn( ` \u26A0\uFE0F Warning: NODE_ENV is set to "${process.env.NODE_ENV}" (builds default to "production") ` ) : process.env.NODE_ENV = "production", (0, import_label_process.labelProcess)("build"), (0, import_checkNodeVersion.checkNodeVersion)(), (0, import_setServerGlobals.setServerGlobals)(); const { oneOptions } = await (0, import_loadConfig.loadUserOneOptions)("build"), routerRoot = (0, import_getRouterRootFromOneOptions.getRouterRootFromOneOptions)(oneOptions); oneOptions.web?.defaultRenderMode && (process.env.ONE_DEFAULT_RENDER_MODE = oneOptions.web.defaultRenderMode); const manifest = (0, import_getManifest.getManifest)({ routerRoot }), serverOutputFormat = oneOptions.build?.server === !1 ? "esm" : oneOptions.build?.server?.outputFormat ?? "esm", buildStartTime = performance.now(), vxrnOutput = await (0, import_vxrn.build)( { skipEnv: args.skipEnv ?? oneOptions.skipEnv, server: oneOptions.server, build: { analyze: !0, server: oneOptions.build?.server === !1 ? !1 : { outputFormat: serverOutputFormat } } }, args ), bundleTime = performance.now() - buildStartTime; if (console.info(` \u23F1\uFE0F vite bundle: ${(bundleTime / 1e3).toFixed(2)}s `), !vxrnOutput || args.platform !== "web") return; const options = await (0, import_vxrn.fillOptions)(vxrnOutput.options, { mode: "prod" }), { optimizeDeps } = (0, import_vxrn.getOptimizeDeps)("build"), apiBuildConfig = (0, import_vite.mergeConfig)( // feels like this should build off the *server* build config not web vxrnOutput.webBuildConfig, { configFile: !1, appType: "custom", optimizeDeps } ); async function buildCustomRoutes(subFolder, routes) { const input = routes.reduce((entries, { page, file }) => (entries[page.slice(1) + ".js"] = (0, import_node_path.join)(routerRoot, file), entries), {}), outputFormat = oneOptions?.build?.api?.outputFormat ?? serverOutputFormat, treeshake = oneOptions?.build?.api?.treeshake, mergedConfig = (0, import_vite.mergeConfig)(apiBuildConfig, { appType: "custom", configFile: !1, // plugins: [ // nodeExternals({ // exclude: optimizeDeps.include, // }) as any, // ], define: { ...vxrnOutput.processEnvDefines }, ssr: { noExternal: !0, external: ["react", "react-dom"], optimizeDeps }, build: { ssr: !0, emptyOutDir: !1, outDir: `dist/${subFolder}`, copyPublicDir: !1, minify: !1, rollupOptions: { treeshake: treeshake ?? { moduleSideEffects: !1 }, plugins: [ // otherwise rollup is leaving commonjs-only top level imports... outputFormat === "esm" ? import_vxrn.rollupRemoveUnusedImportsPlugin : null ].filter(Boolean), // too many issues // treeshake: { // moduleSideEffects: false, // }, // prevents it from shaking out the exports preserveEntrySignatures: "strict", input, external: (id) => !1, output: { entryFileNames: "[name]", exports: "auto", ...outputFormat === "esm" ? { format: "esm", esModule: !0 } : { format: "cjs", // Preserve folder structure and use .cjs extension entryFileNames: (chunkInfo) => chunkInfo.name.replace(/\.js$/, ".cjs"), chunkFileNames: (chunkInfo) => { const dir = import_node_path.default.dirname(chunkInfo.name), name = import_node_path.default.basename( chunkInfo.name, import_node_path.default.extname(chunkInfo.name) ); return import_node_path.default.join(dir, `${name}-[hash].cjs`); }, assetFileNames: (assetInfo) => { const name = assetInfo.name ?? "", dir = import_node_path.default.dirname(name), baseName = import_node_path.default.basename(name, import_node_path.default.extname(name)), ext = import_node_path.default.extname(name); return import_node_path.default.join(dir, `${baseName}-[hash]${ext}`); } } } } } }), userApiBuildConf = oneOptions.build?.api?.config, finalApiBuildConf = userApiBuildConf ? (0, import_vite.mergeConfig)(mergedConfig, userApiBuildConf) : mergedConfig; return await (0, import_vite.build)( // allow user merging api build config finalApiBuildConf ); } const builtMiddlewares = {}, apiPromise = manifest.apiRoutes.length ? (console.info(` \u{1F528} build api routes `), buildCustomRoutes("api", manifest.apiRoutes)) : Promise.resolve(null), middlewarePromise = manifest.middlewareRoutes.length ? (console.info(` \u{1F528} build middlewares `), buildCustomRoutes("middlewares", manifest.middlewareRoutes)) : Promise.resolve(null), [apiOutput, middlewareBuildInfo] = await Promise.all([ apiPromise, middlewarePromise ]); if (middlewareBuildInfo) for (const middleware of manifest.middlewareRoutes) { const absoluteRoot = (0, import_node_path.resolve)(process.cwd(), options.root), fullPath = (0, import_node_path.join)(absoluteRoot, routerRoot, middleware.file), chunk = middlewareBuildInfo.output.filter((x) => x.type === "chunk").find((x) => x.facadeModuleId === fullPath); if (!chunk) throw new Error("internal err finding middleware"); builtMiddlewares[middleware.file] = (0, import_node_path.join)("dist", "middlewares", chunk.fileName); } globalThis.require = (0, import_node_module.createRequire)((0, import_node_path.join)(import_meta.url, "..")); const assets = [], builtRoutes = [], sitemapData = [], collectImportsCache = /* @__PURE__ */ new Map(), cssFileContentsCache = /* @__PURE__ */ new Map(), limit = (0, import_pLimit.pLimit)(BUILD_CONCURRENCY), useWorkers = shouldUseWorkers(oneOptions), workerPool = useWorkers ? (0, import_workerPool.getWorkerPool)(BUILD_CONCURRENCY) : null; workerPool && await workerPool.initialize(); const staticStartTime = performance.now(), modeLabel = useWorkers ? `workers: ${workerPool?.size}` : `concurrency: ${BUILD_CONCURRENCY}`; console.info(` \u{1F528} build static routes (${modeLabel}) `); const staticDir = (0, import_node_path.join)("dist/static"), clientDir = (0, import_node_path.join)("dist/client"); if (await ensureDir(staticDir), !vxrnOutput.serverOutput) throw new Error("No server output"); const clientChunksBySource = /* @__PURE__ */ new Map(); if (vxrnOutput.clientOutput) for (const chunk of vxrnOutput.clientOutput) chunk.type === "chunk" && chunk.facadeModuleId && clientChunksBySource.set(chunk.facadeModuleId, { fileName: chunk.fileName, imports: chunk.imports || [] }); const outputEntries = [...vxrnOutput.serverOutput.entries()], layoutServerPaths = /* @__PURE__ */ new Map(); for (const [, output] of outputEntries) { if (output.type === "asset") continue; const id = output.facadeModuleId || ""; if (import_node_path.default.basename(id).startsWith("_layout") && id.includes(`/${routerRoot}/`)) { const contextKey = `./${(0, import_node_path.relative)(process.cwd(), id).replace(`${routerRoot}/`, "")}`; layoutServerPaths.set(contextKey, output.fileName); } } const routeByPath = /* @__PURE__ */ new Map(); for (const route of manifest.pageRoutes) if (route.file) { const routePath = `${routerRoot}${route.file.slice(1)}`; routeByPath.set(routePath, route); } for (const [index, output] of outputEntries) { let collectImports = function(entry, { type = "js" } = {}) { const { imports = [], css } = entry, cacheKey = `${entry.file || imports.join(",")}:${type}`, cached = collectImportsCache.get(cacheKey); if (cached) return cached; const result = [ ...new Set( [ ...type === "js" ? imports : css || [], ...imports.flatMap((name) => { const found = vxrnOutput.clientManifest[name]; return found || console.warn("No found imports", name, vxrnOutput.clientManifest), collectImports(found, { type }); }) ].flat().filter((x) => x && (type === "css" || x.endsWith(".js"))).map( (x) => type === "css" || x.startsWith("assets/") ? x : `assets/${x.slice(1)}` ) ) ]; return collectImportsCache.set(cacheKey, result), result; }; if (output.type === "asset") { assets.push(output); continue; } const id = output.facadeModuleId || "", file = import_node_path.default.basename(id); if (!id || file[0] === "_" || file.includes("entry-server") || id.includes("+api") || !id.includes(`/${routerRoot}/`)) continue; const relativeId = (0, import_node_path.relative)(process.cwd(), id).replace(`${routerRoot}/`, "/"), onlyBuild = vxrnOutput.buildArgs?.only; if (onlyBuild && !import_micromatch.default.contains(relativeId, onlyBuild)) continue; let foundRoute; for (const [routePath, route] of routeByPath) if (id.endsWith(routePath)) { foundRoute = route; break; } if (!foundRoute) continue; const clientChunk = clientChunksBySource.get(id), manifestKey = `${routerRoot}${foundRoute.file.slice(1)}`, clientManifestEntry = vxrnOutput.clientManifest[manifestKey]; if (!clientChunk && foundRoute.type !== "spa" && foundRoute.type !== "ssg") { console.warn(`No client chunk found for route: ${id}`); continue; } if (foundRoute.loaderServerPath = output.fileName, foundRoute.layouts) for (const layout of foundRoute.layouts) { const serverPath = layoutServerPaths.get(layout.contextKey); serverPath && (layout.loaderServerPath = serverPath); } const entryImports = collectImports(clientManifestEntry || {}), layoutEntries = foundRoute.layouts?.flatMap((layout) => { const clientKey = `${routerRoot}${layout.contextKey.slice(1)}`, found = vxrnOutput.clientManifest[clientKey]; return found || []; }) ?? [], layoutImports = layoutEntries.flatMap((entry) => [entry.file, ...collectImports(entry)]), routePreloads = {}, rootLayoutKey = `${routerRoot}/_layout.tsx`, rootLayoutEntry = vxrnOutput.clientManifest[rootLayoutKey]; if (rootLayoutEntry && (routePreloads[`/${rootLayoutKey}`] = `/${rootLayoutEntry.file}`), foundRoute.layouts) for (const layout of foundRoute.layouts) { const clientKey = `${routerRoot}${layout.contextKey.slice(1)}`, entry = vxrnOutput.clientManifest[clientKey]; entry && (routePreloads[`/${clientKey}`] = `/${entry.file}`); } if (clientChunk) { const routeKey = `/${routerRoot}${foundRoute.file.slice(1)}`; routePreloads[routeKey] = `/${clientChunk.fileName}`; } else if (clientManifestEntry) { const routeKey = `/${routerRoot}${foundRoute.file.slice(1)}`; routePreloads[routeKey] = `/${clientManifestEntry.file}`; } const preloadSetupFilePreloads = (() => { if (!oneOptions.setupFile) return []; const clientSetupFile = typeof oneOptions.setupFile == "string" ? oneOptions.setupFile : oneOptions.setupFile.client; if (!clientSetupFile) return []; const needle = clientSetupFile.replace(/^\.\//, ""); for (const file2 in vxrnOutput.clientManifest) if (file2 === needle) return [ vxrnOutput.clientManifest[file2].file // getting 404s for preloading the imports as well? // ...(entry.imports as string[]) ]; return []; })(), allPreloads = [ .../* @__PURE__ */ new Set([ ...preloadSetupFilePreloads, // add the route entry js (like ./app/index.ts) - prefer direct chunk lookup ...clientChunk ? [clientChunk.fileName] : clientManifestEntry ? [clientManifestEntry.file] : [], // add the virtual entry vxrnOutput.clientManifest["virtual:one-entry"].file, ...entryImports, ...layoutImports ]) ].map((path) => `/${path}`), scriptLoadingMode = oneOptions.web?.experimental_scriptLoading, needsSeparatedPreloads = scriptLoadingMode === "defer-non-critical" || scriptLoadingMode === "after-lcp-aggressive", criticalPreloads = needsSeparatedPreloads ? [ .../* @__PURE__ */ new Set([ ...preloadSetupFilePreloads, // add the virtual entry (framework bootstrap) vxrnOutput.clientManifest["virtual:one-entry"].file, // add the route entry js (like ./app/index.ts) - prefer direct chunk lookup ...clientChunk ? [clientChunk.fileName] : clientManifestEntry ? [clientManifestEntry.file] : [], // add layout files (but not their deep imports) ...layoutEntries.map((entry) => entry.file) ]) ].map((path) => `/${path}`) : void 0, deferredPreloads = needsSeparatedPreloads ? [ .../* @__PURE__ */ new Set([ ...entryImports, ...layoutEntries.flatMap((entry) => collectImports(entry)) ]) ].filter((path) => !criticalPreloads.includes(`/${path}`)).map((path) => `/${path}`) : void 0, preloads2 = needsSeparatedPreloads ? [...criticalPreloads, ...deferredPreloads] : allPreloads, allEntries = [clientManifestEntry, ...layoutEntries].filter(Boolean), allCSS = [ .../* @__PURE__ */ new Set([ // css from entry imports ...allEntries.flatMap((entry) => collectImports(entry, { type: "css" })).map((path) => `/${path}`), // root-level css (handles cssCodeSplit: false) ...Object.entries(vxrnOutput.clientManifest).filter(([key]) => key.endsWith(".css")).map(([, entry]) => `/${entry.file}`) ]) ]; let allCSSContents; oneOptions.web?.inlineLayoutCSS && (allCSSContents = await Promise.all( allCSS.map(async (cssPath) => { const cached = cssFileContentsCache.get(cssPath); if (cached !== void 0) return cached; const filePath = (0, import_node_path.join)(clientDir, cssPath); try { const content = await import_fs_extra.default.readFile(filePath, "utf-8"); return cssFileContentsCache.set(cssPath, content), content; } catch { return console.warn(`[one] Warning: Could not read CSS file ${filePath}`), cssFileContentsCache.set(cssPath, ""), ""; } }) )), process.env.DEBUG && console.info("[one] building routes", { foundRoute, layoutEntries, allEntries, allCSS }); const serverJsPath = (0, import_node_path.join)("dist/server", output.fileName); let exported; try { exported = await import((0, import_toAbsolute.toAbsolute)(serverJsPath)); } catch (err) { throw console.error("Error importing page (original error)", err), new Error(`Error importing page: ${serverJsPath}`, { cause: err }); } const isDynamic = !!Object.keys(foundRoute.routeKeys).length; if (foundRoute.type === "ssg" && isDynamic && !foundRoute.page.includes("+not-found") && !foundRoute.page.includes("_sitemap") && !exported.generateStaticParams) throw new Error(`[one] Error: Missing generateStaticParams Route ${foundRoute.page} of type ${foundRoute.type} must export generateStaticParams so build can complete. See docs on generateStaticParams: https://onestack.dev/docs/routing-exports#generatestaticparams `); const paramsList = await exported.generateStaticParams?.() ?? [{}]; console.info(` [build] page ${relativeId} (with ${paramsList.length} routes) `), process.env.DEBUG && console.info("paramsList", JSON.stringify(paramsList, null, 2)); const routeSitemapExport = exported.sitemap, isAfterLCPMode = scriptLoadingMode === "after-lcp" || scriptLoadingMode === "after-lcp-aggressive", useAfterLCP = foundRoute.type === "ssg" && isAfterLCPMode, useAfterLCPAggressive = foundRoute.type === "ssg" && scriptLoadingMode === "after-lcp-aggressive", shouldCollectSitemap = foundRoute.type !== "api" && foundRoute.type !== "layout" && !foundRoute.isNotFound && !foundRoute.page.includes("+not-found") && !foundRoute.page.includes("_sitemap"), pageBuilds = paramsList.map((params) => { const path = (0, import_getPathnameFromFilePath.getPathnameFromFilePath)(relativeId, params, foundRoute.type === "ssg"); return workerPool ? (console.info(` \u21A6 route ${path}`), workerPool.buildPage({ serverEntry: vxrnOutput.serverEntry, path, relativeId, params, foundRoute, clientManifestEntry, staticDir, clientDir, builtMiddlewares, serverJsPath, preloads: preloads2, allCSS, routePreloads, allCSSContents, criticalPreloads, deferredPreloads, useAfterLCP, useAfterLCPAggressive }).then((built) => ({ built, path }))) : limit(async () => (console.info(` \u21A6 route ${path}`), { built: await (0, import_one_server_only.runWithAsyncLocalContext)(async () => await (0, import_buildPage.buildPage)( vxrnOutput.serverEntry, path, relativeId, params, foundRoute, clientManifestEntry, staticDir, clientDir, builtMiddlewares, serverJsPath, preloads2, allCSS, routePreloads, allCSSContents, criticalPreloads, deferredPreloads, useAfterLCP, useAfterLCPAggressive )), path })); }), results = await Promise.all(pageBuilds); for (const { built, path } of results) builtRoutes.push(built), shouldCollectSitemap && sitemapData.push({ path, routeExport: routeSitemapExport }); } workerPool && await (0, import_workerPool.terminateWorkerPool)(); const staticTime = performance.now() - staticStartTime; console.info( ` \u23F1\uFE0F static routes: ${(staticTime / 1e3).toFixed(2)}s (${builtRoutes.length} pages) ` ), (0, import_buildPage.printBuildTimings)(), await moveAllFiles(staticDir, clientDir), await import_fs_extra.default.rm(staticDir, { force: !0, recursive: !0 }); const routeMap = {}, routeToBuildInfo = {}, pathToRoute = {}, preloads = {}, cssPreloads = {}, loaders = {}; for (const route of builtRoutes) { route.cleanPath.includes("*") || (routeMap[route.cleanPath] = route.htmlPath); const { // dont include loaderData it can be huge loaderData: _loaderData, ...rest } = route; routeToBuildInfo[route.routeFile] = rest; for (const p of getCleanPaths([route.path, route.cleanPath])) pathToRoute[p] = route.routeFile; preloads[route.preloadPath] = !0, cssPreloads[route.cssPreloadPath] = !0, loaders[route.loaderPath] = !0; } function createBuildManifestRoute(route) { const { layouts, ...built } = route; layouts?.length && (built.layouts = layouts.map((layout) => ({ contextKey: layout.contextKey, loaderServerPath: layout.loaderServerPath }))); const buildInfo = builtRoutes.find((x) => x.routeFile === route.file); if (built.middlewares && buildInfo?.middlewares) for (const [index, mw] of built.middlewares.entries()) mw.contextKey = buildInfo.middlewares[index]; return buildInfo && (built.loaderPath = buildInfo.loaderPath), built; } const buildInfoForWriting = { oneOptions, routeToBuildInfo, pathToRoute, manifest: { pageRoutes: manifest.pageRoutes.map(createBuildManifestRoute), apiRoutes: manifest.apiRoutes.map(createBuildManifestRoute), allRoutes: manifest.allRoutes.map(createBuildManifestRoute) }, routeMap, constants: JSON.parse(JSON.stringify({ ...constants })), preloads, cssPreloads, loaders, useRolldown: await (0, import_isRolldown.isRolldown)() }; await writeJSON((0, import_toAbsolute.toAbsolute)("dist/buildInfo.json"), buildInfoForWriting); const sitemapConfig = oneOptions.web?.sitemap; if (sitemapConfig) { const sitemapXml = (0, import_generateSitemap.generateSitemap)(sitemapData, typeof sitemapConfig == "boolean" ? {} : sitemapConfig), sitemapPath = (0, import_node_path.join)(clientDir, "sitemap.xml"); await import_fs_extra.default.writeFile(sitemapPath, sitemapXml), console.info(` \u{1F4C4} generated sitemap.xml (${sitemapData.length} URLs) `); } const postBuildLogs = [], platform = oneOptions.web?.deploy; switch (platform && postBuildLogs.push(`[one.build] platform ${platform}`), platform) { case "vercel": { const vercelJsonPath = (0, import_node_path.join)(options.root, "vercel.json"); if (import_fs_extra.default.existsSync(vercelJsonPath)) try { JSON.parse(import_fs_extra.default.readFileSync(vercelJsonPath, "utf-8")).cleanUrls || (console.warn(` \u26A0\uFE0F Warning: Your vercel.json is missing "cleanUrls": true`), console.warn(" Without this, direct navigation to SSG pages will 404."), console.warn(` Add "cleanUrls": true to your vercel.json to fix this. `)); } catch { } await (0, import_buildVercelOutputDirectory.buildVercelOutputDirectory)({ apiOutput, buildInfoForWriting, clientDir, oneOptionsRoot: options.root, postBuildLogs }); break; } case "cloudflare": { const pageRouteMap = [], apiRouteMap = [], middlewareRouteMap = []; for (const [routeFile, info] of Object.entries( buildInfoForWriting.routeToBuildInfo )) if (info.serverJsPath) { const importPath = "./" + info.serverJsPath.replace(/^dist\//, ""); pageRouteMap.push(` '${routeFile}': () => import('${importPath}')`); } for (const route of buildInfoForWriting.manifest.apiRoutes) if (route.file) { const importPath = `./api/${route.page.slice(1).replace(/\[/g, "_").replace(/\]/g, "_")}.js`; apiRouteMap.push(` '${route.page}': () => import('${importPath}')`); } for (const [middlewareFile, builtPath] of Object.entries(builtMiddlewares)) { const importPath = "./" + builtPath.replace(/^dist\//, ""); middlewareRouteMap.push(` '${builtPath}': () => import('${importPath}')`); } const workerSrcPath = (0, import_node_path.join)(options.root, "dist", "_worker-src.js"), workerCode = `// Polyfill MessageChannel for React SSR (not available in Cloudflare Workers by default) if (typeof MessageChannel === 'undefined') { globalThis.MessageChannel = class MessageChannel { constructor() { this.port1 = { postMessage: () => {}, onmessage: null, close: () => {} } this.port2 = { postMessage: () => {}, onmessage: null, close: () => {} } } } } import { serve, setFetchStaticHtml } from 'one/serve-worker' // Lazy import map - modules load on-demand when route is matched const lazyRoutes = { serverEntry: () => import('./server/_virtual_one-entry.js'), pages: { ${pageRouteMap.join(`, `)} }, api: { ${apiRouteMap.join(`, `)} }, middlewares: { ${middlewareRouteMap.join(`, `)} } } const buildInfo = ${JSON.stringify(buildInfoForWriting)} let app export default { async fetch(request, env, ctx) { if (!app) { app = await serve(buildInfo, lazyRoutes) } // Set up static HTML fetcher for this request (uses ASSETS binding) if (env.ASSETS) { setFetchStaticHtml(async (path) => { try { const url = new URL(request.url) url.pathname = path const assetResponse = await env.ASSETS.fetch(new Request(url)) if (assetResponse && assetResponse.ok) { return await assetResponse.text() } } catch (e) { // Asset not found } return null }) } try { // Try the app first const response = await app.fetch(request, env, ctx) // If no route matched (404) or no response, try serving static assets if (!response || response.status === 404) { if (env.ASSETS) { try { const assetResponse = await env.ASSETS.fetch(request) // If asset exists, return it if (assetResponse && assetResponse.status !== 404) { return assetResponse } } catch (e) { // Asset not found, continue with original response } } } return response } finally { // Clean up per-request state setFetchStaticHtml(null) } } } `; await import_fs_extra.default.writeFile(workerSrcPath, workerCode), console.info(` [cloudflare] Bundling worker...`), await (0, import_vite.build)({ root: options.root, logLevel: "warn", build: { outDir: "dist", emptyOutDir: !1, // Use SSR mode with node target for proper Node.js module resolution ssr: workerSrcPath, rollupOptions: { external: [ // React Native dev tools - not needed in production "@react-native/dev-middleware", "@react-native/debugger-shell", "metro", "metro-core", "metro-runtime", // Native modules that can't run in workers /\.node$/ ], output: { entryFileNames: "worker.js", format: "es", // Keep dynamic imports separate for lazy loading inlineDynamicImports: !1 } }, minify: !0, target: "esnext" }, define: { "process.env.NODE_ENV": JSON.stringify("production"), "process.env.VITE_ENVIRONMENT": JSON.stringify("ssr") }, resolve: { conditions: ["workerd", "worker", "node", "module", "default"] }, ssr: { target: "node", noExternal: !0 } }), await import_fs_extra.default.remove(workerSrcPath), await import_fs_extra.default.writeFile( (0, import_node_path.join)(options.root, "dist", "wrangler.jsonc"), `{ "name": "one-app", "main": "worker.js", "compatibility_date": "2024-12-05", "compatibility_flags": ["nodejs_compat"], "find_additional_modules": true, "rules": [ { "type": "ESModule", "globs": ["./server/**/*.js"], "fallthrough": true }, { "type": "ESModule", "globs": ["./api/**/*.js"], "fallthrough": true }, { "type": "ESModule", "globs": ["./middlewares/**/*.js"], "fallthrough": true } ], "assets": { "directory": "client", "binding": "ASSETS", "run_worker_first": true } } ` ), postBuildLogs.push("Cloudflare worker bundled at dist/worker.js"), postBuildLogs.push("To deploy: cd dist && wrangler deploy"); break; } } postBuildLogs.length && (console.info(` `), postBuildLogs.forEach((log) => { console.info(` \xB7 ${log}`); })), console.info(` \u{1F49B} build complete `); } const TRAILING_INDEX_REGEX = /\/index(\.(web))?/; function getCleanPaths(possiblePaths) { return Array.from( new Set( Array.from(new Set(possiblePaths)).flatMap((p) => { const paths = [p]; if (p.match(TRAILING_INDEX_REGEX)) { const pathWithTrailingIndexRemoved = p.replace(TRAILING_INDEX_REGEX, ""); paths.push(pathWithTrailingIndexRemoved), paths.push(pathWithTrailingIndexRemoved + "/"); } return paths; }) ) ); } async function moveAllFiles(src, dest) { try { await import_fs_extra.default.copy(src, dest, { overwrite: !0, errorOnExist: !1 }); } catch (err) { console.error("Error moving files:", err); } } //# sourceMappingURL=build.js.map