|
| 1 | +import esbuild from 'esbuild' |
| 2 | +import { readFile, writeFile } from 'node:fs/promises' |
| 3 | +import { join } from 'node:path' |
| 4 | +import { exit } from 'node:process' |
| 5 | +import type { ResolvedConfig } from 'vite' |
| 6 | +import type { NodeVersion } from './types' |
| 7 | + |
| 8 | +type PackageJson = { |
| 9 | + name: string |
| 10 | + type: string |
| 11 | + scripts?: Record<string, string> |
| 12 | + dependencies?: Record<string, string> |
| 13 | +} |
| 14 | + |
| 15 | +type SsrExternal = ResolvedConfig['ssr']['external'] |
| 16 | + |
| 17 | +const getPackageDependencies = (dependencies: Record<string, string | undefined>, ssrExternal: SsrExternal) => { |
| 18 | + const ssrExternalFiltered = Array.isArray(ssrExternal) |
| 19 | + ? ssrExternal.filter( |
| 20 | + (id) => |
| 21 | + ![ |
| 22 | + 'react-router', |
| 23 | + 'react-router-dom', |
| 24 | + '@react-router/architect', |
| 25 | + '@react-router/cloudflare', |
| 26 | + '@react-router/dev', |
| 27 | + '@react-router/express', |
| 28 | + '@react-router/node', |
| 29 | + '@react-router/serve', |
| 30 | + ].includes(id), |
| 31 | + ) |
| 32 | + : ssrExternal |
| 33 | + |
| 34 | + return Object.keys(dependencies) |
| 35 | + .filter((key) => { |
| 36 | + if (ssrExternalFiltered === undefined || ssrExternalFiltered === true) { |
| 37 | + return false |
| 38 | + } |
| 39 | + |
| 40 | + return ssrExternalFiltered.includes(key) |
| 41 | + }) |
| 42 | + .reduce((obj: Record<string, string>, key) => { |
| 43 | + obj[key] = dependencies[key] ?? '' |
| 44 | + |
| 45 | + return obj |
| 46 | + }, {}) |
| 47 | +} |
| 48 | + |
| 49 | +const writePackageJson = async ( |
| 50 | + pkg: PackageJson, |
| 51 | + outputFile: string, |
| 52 | + dependencies: unknown, |
| 53 | + nodeVersion: NodeVersion, |
| 54 | +) => { |
| 55 | + const distPkg = { |
| 56 | + name: pkg.name, |
| 57 | + type: pkg.type, |
| 58 | + scripts: { |
| 59 | + postinstall: pkg.scripts?.['postinstall'] ?? '', |
| 60 | + }, |
| 61 | + dependencies: dependencies, |
| 62 | + engines: { |
| 63 | + node: `${nodeVersion}.x`, |
| 64 | + }, |
| 65 | + } |
| 66 | + |
| 67 | + await writeFile(outputFile, JSON.stringify(distPkg, null, 2), 'utf8') |
| 68 | +} |
| 69 | + |
| 70 | +export const buildEntry = async ( |
| 71 | + appPath: string, |
| 72 | + entryFile: string, |
| 73 | + buildPath: string, |
| 74 | + buildFile: string, |
| 75 | + buildDir: string, |
| 76 | + assetsDir: string, |
| 77 | + serverBundleId: string, |
| 78 | + packageFile: string, |
| 79 | + ssrExternal: string[] | true | undefined, |
| 80 | + nodeVersion: NodeVersion, |
| 81 | +): Promise<string> => { |
| 82 | + console.log(`Bundle Server file for ${serverBundleId}...`) |
| 83 | + |
| 84 | + const pkg = JSON.parse(await readFile(packageFile, 'utf8')) as PackageJson |
| 85 | + const packageDependencies = getPackageDependencies({ ...pkg.dependencies }, ssrExternal) |
| 86 | + |
| 87 | + await writePackageJson(pkg, join(buildPath, 'package.json'), packageDependencies, nodeVersion) |
| 88 | + |
| 89 | + const bundleFile = join(buildPath, 'server.mjs') |
| 90 | + |
| 91 | + await esbuild |
| 92 | + .build({ |
| 93 | + outfile: bundleFile, |
| 94 | + entryPoints: [join(appPath, entryFile)], |
| 95 | + alias: { |
| 96 | + 'virtual:react-router/server-build': buildFile, |
| 97 | + }, |
| 98 | + define: { |
| 99 | + 'process.env.NODE_ENV': "'production'", |
| 100 | + 'import.meta.env.PIZZAJS_BUILD_DIR': `'${buildDir}'`, |
| 101 | + 'import.meta.env.PIZZAJS_ASSETS_DIR': `'${assetsDir}'`, |
| 102 | + }, |
| 103 | + banner: { js: "import { createRequire } from 'module';const require = createRequire(import.meta.url);" }, |
| 104 | + platform: 'node', |
| 105 | + target: `node${nodeVersion}`, |
| 106 | + format: 'esm', |
| 107 | + external: ['vite', ...Object.keys(packageDependencies)], |
| 108 | + bundle: true, |
| 109 | + charset: 'utf8', |
| 110 | + legalComments: 'none', |
| 111 | + minify: false, |
| 112 | + }) |
| 113 | + .catch((error: unknown) => { |
| 114 | + console.error(error) |
| 115 | + exit(1) |
| 116 | + }) |
| 117 | + |
| 118 | + return bundleFile |
| 119 | +} |
0 commit comments