@vercel/remix-builder 5.0.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,9 +8,13 @@ import * as build from '@remix-run/dev/server-build';
8
8
 
9
9
  installGlobals({
10
10
  nativeFetch:
11
+ // Explicit opt-in to native fetch via runtime env var
11
12
  (parseInt(process.versions.node, 10) >= 20 &&
12
13
  process.env.VERCEL_REMIX_NATIVE_FETCH === '1') ||
13
- build.future.unstable_singleFetch,
14
+ // `unstable_singleFetch` future flag added in Remix v2.9.0
15
+ build.future.unstable_singleFetch ||
16
+ // `v3_singleFetch` future flag stabilized in Remix v2.13.0
17
+ build.future.v3_singleFetch,
14
18
  });
15
19
 
16
20
  const handleRequest = createRemixRequestHandler(
@@ -0,0 +1,3 @@
1
+ import { createRequestHandler } from 'react-router';
2
+ import * as build from 'ENTRYPOINT_PLACEHOLDER';
3
+ export default createRequestHandler(build.default || build);
package/dist/index.js CHANGED
@@ -3066,17 +3066,15 @@ function hasScript(scriptName, pkg) {
3066
3066
  const scripts = pkg?.scripts || {};
3067
3067
  return typeof scripts[scriptName] === "string";
3068
3068
  }
3069
- async function getRemixVersion(dir, base) {
3070
- const resolvedPath = require_.resolve("@remix-run/dev", { paths: [dir] });
3069
+ async function getPackageVersion(name, dir, base) {
3070
+ const resolvedPath = require_.resolve(name, { paths: [dir] });
3071
3071
  const pkgPath = await (0, import_build_utils2.walkParentDirs)({
3072
3072
  base,
3073
3073
  start: (0, import_path.dirname)(resolvedPath),
3074
3074
  filename: "package.json"
3075
3075
  });
3076
3076
  if (!pkgPath) {
3077
- throw new Error(
3078
- `Failed to find \`package.json\` file for "@remix-run/dev"`
3079
- );
3077
+ throw new Error(`Failed to find \`package.json\` file for "${name}"`);
3080
3078
  }
3081
3079
  const { version: version2 } = JSON.parse(
3082
3080
  await import_fs.promises.readFile(pkgPath, "utf8")
@@ -3137,6 +3135,80 @@ var nodeServerSrcPromise = import_fs2.promises.readFile(
3137
3135
  (0, import_path2.join)(DEFAULTS_PATH, "server-node.mjs"),
3138
3136
  "utf-8"
3139
3137
  );
3138
+ var reactRouterServerSrcPromise = import_fs2.promises.readFile(
3139
+ (0, import_path2.join)(DEFAULTS_PATH, "server-react-router.mjs"),
3140
+ "utf-8"
3141
+ );
3142
+ var REMIX_FRAMEWORK_SETTINGS = {
3143
+ primaryPackageName: "@remix-run/dev",
3144
+ buildCommand: "remix build",
3145
+ buildResultFilePath: ".vercel/remix-build-result.json",
3146
+ createRenderFunction({
3147
+ nodeVersion,
3148
+ entrypointDir,
3149
+ rootDir,
3150
+ serverBuildPath,
3151
+ serverEntryPoint,
3152
+ frameworkVersion,
3153
+ config
3154
+ }) {
3155
+ if (config.runtime === "edge") {
3156
+ return createRenderEdgeFunction(
3157
+ entrypointDir,
3158
+ rootDir,
3159
+ serverBuildPath,
3160
+ serverEntryPoint,
3161
+ frameworkVersion,
3162
+ config
3163
+ );
3164
+ }
3165
+ return createRenderNodeFunction(
3166
+ nodeVersion,
3167
+ entrypointDir,
3168
+ rootDir,
3169
+ serverBuildPath,
3170
+ serverEntryPoint,
3171
+ frameworkVersion,
3172
+ config
3173
+ );
3174
+ }
3175
+ };
3176
+ var REACT_ROUTER_FRAMEWORK_SETTINGS = {
3177
+ primaryPackageName: "react-router",
3178
+ buildCommand: "react-router build",
3179
+ buildResultFilePath: ".vercel/react-router-build-result.json",
3180
+ createRenderFunction({
3181
+ nodeVersion,
3182
+ entrypointDir,
3183
+ rootDir,
3184
+ serverBuildPath,
3185
+ serverEntryPoint,
3186
+ frameworkVersion,
3187
+ config
3188
+ }) {
3189
+ return createRenderReactRouterFunction(
3190
+ nodeVersion,
3191
+ entrypointDir,
3192
+ rootDir,
3193
+ serverBuildPath,
3194
+ serverEntryPoint,
3195
+ frameworkVersion,
3196
+ config
3197
+ );
3198
+ }
3199
+ };
3200
+ function determineFrameworkSettings(workPath) {
3201
+ const isReactRouter = findConfig(workPath, "react-router.config", [
3202
+ ".js",
3203
+ ".ts",
3204
+ ".mjs",
3205
+ ".mts"
3206
+ ]);
3207
+ if (isReactRouter) {
3208
+ return REACT_ROUTER_FRAMEWORK_SETTINGS;
3209
+ }
3210
+ return REMIX_FRAMEWORK_SETTINGS;
3211
+ }
3140
3212
  var build = async ({
3141
3213
  entrypoint,
3142
3214
  workPath,
@@ -3147,6 +3219,7 @@ var build = async ({
3147
3219
  const { installCommand, buildCommand } = config;
3148
3220
  const mountpoint = (0, import_path2.dirname)(entrypoint);
3149
3221
  const entrypointFsDirname = (0, import_path2.join)(workPath, mountpoint);
3222
+ const frameworkSettings = determineFrameworkSettings(workPath);
3150
3223
  const nodeVersion = await (0, import_build_utils3.getNodeVersion)(
3151
3224
  entrypointFsDirname,
3152
3225
  void 0,
@@ -3158,8 +3231,7 @@ var build = async ({
3158
3231
  lockfileVersion,
3159
3232
  packageJson,
3160
3233
  packageJsonPackageManager,
3161
- turboSupportsCorepackHome,
3162
- detectedLockfile
3234
+ turboSupportsCorepackHome
3163
3235
  } = await (0, import_build_utils3.scanParentDirs)(entrypointFsDirname, true);
3164
3236
  const spawnOpts = (0, import_build_utils3.getSpawnOptions)(meta, nodeVersion);
3165
3237
  if (!spawnOpts.env) {
@@ -3171,8 +3243,7 @@ var build = async ({
3171
3243
  packageJsonPackageManager,
3172
3244
  nodeVersion,
3173
3245
  env: spawnOpts.env,
3174
- turboSupportsCorepackHome,
3175
- detectedLockfile
3246
+ turboSupportsCorepackHome
3176
3247
  });
3177
3248
  if (typeof installCommand === "string") {
3178
3249
  if (installCommand.trim()) {
@@ -3187,7 +3258,11 @@ var build = async ({
3187
3258
  } else {
3188
3259
  await (0, import_build_utils3.runNpmInstall)(entrypointFsDirname, [], spawnOpts, meta, nodeVersion);
3189
3260
  }
3190
- const remixVersion = await getRemixVersion(entrypointFsDirname, repoRootPath);
3261
+ const frameworkVersion = await getPackageVersion(
3262
+ frameworkSettings.primaryPackageName,
3263
+ entrypointFsDirname,
3264
+ repoRootPath
3265
+ );
3191
3266
  if (buildCommand) {
3192
3267
  (0, import_build_utils3.debug)(`Executing build command "${buildCommand}"`);
3193
3268
  await (0, import_build_utils3.execCommand)(buildCommand, {
@@ -3206,28 +3281,28 @@ var build = async ({
3206
3281
  (0, import_build_utils3.debug)(`Executing "build" script`);
3207
3282
  await (0, import_build_utils3.runPackageJsonScript)(entrypointFsDirname, "build", spawnOpts);
3208
3283
  } else {
3209
- await (0, import_build_utils3.execCommand)("remix build", {
3284
+ await (0, import_build_utils3.execCommand)(frameworkSettings.buildCommand, {
3210
3285
  ...spawnOpts,
3211
3286
  cwd: entrypointFsDirname
3212
3287
  });
3213
3288
  }
3214
3289
  }
3215
- const remixBuildResultPath = (0, import_path2.join)(
3290
+ const buildResultJsonPath = (0, import_path2.join)(
3216
3291
  entrypointFsDirname,
3217
- ".vercel/remix-build-result.json"
3292
+ frameworkSettings.buildResultFilePath
3218
3293
  );
3219
- let remixBuildResult;
3294
+ let buildResult;
3220
3295
  try {
3221
- const remixBuildResultContents = (0, import_fs2.readFileSync)(remixBuildResultPath, "utf8");
3222
- remixBuildResult = JSON.parse(remixBuildResultContents);
3296
+ const buildResultContents = (0, import_fs2.readFileSync)(buildResultJsonPath, "utf8");
3297
+ buildResult = JSON.parse(buildResultContents);
3223
3298
  } catch (err) {
3224
3299
  if (!(0, import_error_utils.isErrnoException)(err) || err.code !== "ENOENT") {
3225
3300
  throw err;
3226
3301
  }
3227
- const buildDirectory = (0, import_path2.join)(entrypointFsDirname, "build");
3228
- if ((0, import_fs2.statSync)(buildDirectory).isDirectory()) {
3302
+ const buildDirectory2 = (0, import_path2.join)(entrypointFsDirname, "build");
3303
+ if ((0, import_fs2.statSync)(buildDirectory2).isDirectory()) {
3229
3304
  console.warn("WARN: The `vercelPreset()` Preset was not detected.");
3230
- remixBuildResult = {
3305
+ buildResult = {
3231
3306
  buildManifest: {
3232
3307
  routes: {
3233
3308
  root: {
@@ -3246,15 +3321,15 @@ var build = async ({
3246
3321
  }
3247
3322
  },
3248
3323
  remixConfig: {
3249
- buildDirectory
3324
+ buildDirectory: buildDirectory2
3250
3325
  }
3251
3326
  };
3252
3327
  const serverPath = "build/server/index.js";
3253
3328
  if ((0, import_fs2.existsSync)((0, import_path2.join)(entrypointFsDirname, serverPath))) {
3254
- remixBuildResult.buildManifest.routeIdToServerBundleId = {
3329
+ buildResult.buildManifest.routeIdToServerBundleId = {
3255
3330
  "routes/_index": ""
3256
3331
  };
3257
- remixBuildResult.buildManifest.serverBundles = {
3332
+ buildResult.buildManifest.serverBundles = {
3258
3333
  "": {
3259
3334
  id: "",
3260
3335
  file: serverPath,
@@ -3264,36 +3339,27 @@ var build = async ({
3264
3339
  }
3265
3340
  }
3266
3341
  }
3267
- if (!remixBuildResult) {
3342
+ if (!buildResult) {
3268
3343
  throw new Error(
3269
3344
  "Could not determine build output directory. Please configure the `vercelPreset()` Preset from the `@vercel/remix` npm package"
3270
3345
  );
3271
3346
  }
3272
- const { buildManifest, remixConfig, viteConfig } = remixBuildResult;
3273
- const staticDir = (0, import_path2.join)(remixConfig.buildDirectory, "client");
3347
+ const { buildManifest, viteConfig } = buildResult;
3348
+ const buildDirectory = "remixConfig" in buildResult ? buildResult.remixConfig.buildDirectory : buildResult.reactRouterConfig.buildDirectory;
3349
+ const staticDir = (0, import_path2.join)(buildDirectory, "client");
3274
3350
  const serverBundles = Object.values(buildManifest.serverBundles ?? {});
3275
3351
  const [staticFiles, ...functions] = await Promise.all([
3276
3352
  (0, import_build_utils3.glob)("**", staticDir),
3277
3353
  ...serverBundles.map((bundle) => {
3278
- if (bundle.config.runtime === "edge") {
3279
- return createRenderEdgeFunction(
3280
- entrypointFsDirname,
3281
- repoRootPath,
3282
- (0, import_path2.join)(entrypointFsDirname, bundle.file),
3283
- void 0,
3284
- remixVersion,
3285
- bundle.config
3286
- );
3287
- }
3288
- return createRenderNodeFunction(
3354
+ return frameworkSettings.createRenderFunction({
3289
3355
  nodeVersion,
3290
- entrypointFsDirname,
3291
- repoRootPath,
3292
- (0, import_path2.join)(entrypointFsDirname, bundle.file),
3293
- void 0,
3294
- remixVersion,
3295
- bundle.config
3296
- );
3356
+ entrypointDir: entrypointFsDirname,
3357
+ rootDir: repoRootPath,
3358
+ serverBuildPath: (0, import_path2.join)(entrypointFsDirname, bundle.file),
3359
+ serverEntryPoint: void 0,
3360
+ frameworkVersion,
3361
+ config: bundle.config
3362
+ });
3297
3363
  })
3298
3364
  ]);
3299
3365
  const functionsMap = /* @__PURE__ */ new Map();
@@ -3337,9 +3403,98 @@ var build = async ({
3337
3403
  src: "/(.*)",
3338
3404
  dest: "/"
3339
3405
  });
3340
- return { routes, output, framework: { version: remixVersion } };
3406
+ return { routes, output, framework: { version: frameworkVersion } };
3341
3407
  };
3342
- async function createRenderNodeFunction(nodeVersion, entrypointDir, rootDir, serverBuildPath, serverEntryPoint, remixVersion, config) {
3408
+ async function createRenderReactRouterFunction(nodeVersion, entrypointDir, rootDir, serverBuildPath, serverEntryPoint, frameworkVersion, config) {
3409
+ const isEdgeFunction = config.runtime === "edge";
3410
+ const files = {};
3411
+ let handler = (0, import_path2.relative)(rootDir, serverBuildPath);
3412
+ let handlerPath = (0, import_path2.join)(rootDir, handler);
3413
+ if (!serverEntryPoint) {
3414
+ const baseServerBuildPath = (0, import_path2.basename)(serverBuildPath, ".js");
3415
+ handler = (0, import_path2.join)((0, import_path2.dirname)(handler), `server-${baseServerBuildPath}.mjs`);
3416
+ handlerPath = (0, import_path2.join)(rootDir, handler);
3417
+ const reactRouterServerSrc = await reactRouterServerSrcPromise;
3418
+ await import_fs2.promises.writeFile(
3419
+ handlerPath,
3420
+ reactRouterServerSrc.replace(
3421
+ "ENTRYPOINT_PLACEHOLDER",
3422
+ `./${baseServerBuildPath}.js`
3423
+ )
3424
+ );
3425
+ }
3426
+ let conditions;
3427
+ let readFile;
3428
+ if (isEdgeFunction) {
3429
+ conditions = ["edge-light", "browser", "module", "import", "require"];
3430
+ readFile = async (fsPath) => {
3431
+ let source;
3432
+ try {
3433
+ source = await import_fs2.promises.readFile(fsPath);
3434
+ } catch (err) {
3435
+ if (err.code === "ENOENT" || err.code === "EISDIR") {
3436
+ return null;
3437
+ }
3438
+ throw err;
3439
+ }
3440
+ if ((0, import_path2.basename)(fsPath) === "package.json") {
3441
+ const pkgJson = JSON.parse(source.toString());
3442
+ for (const prop of ["browser", "module"]) {
3443
+ const val = pkgJson[prop];
3444
+ if (typeof val === "string") {
3445
+ pkgJson.main = val;
3446
+ source = JSON.stringify(pkgJson);
3447
+ break;
3448
+ }
3449
+ }
3450
+ }
3451
+ return source;
3452
+ };
3453
+ }
3454
+ const trace = await (0, import_nft.nodeFileTrace)([handlerPath], {
3455
+ base: rootDir,
3456
+ processCwd: entrypointDir,
3457
+ conditions,
3458
+ readFile
3459
+ });
3460
+ logNftWarnings(trace.warnings, "react-router");
3461
+ for (const file of trace.fileList) {
3462
+ files[file] = await import_build_utils3.FileFsRef.fromFsPath({ fsPath: (0, import_path2.join)(rootDir, file) });
3463
+ }
3464
+ let fn;
3465
+ if (isEdgeFunction) {
3466
+ fn = new import_build_utils3.EdgeFunction({
3467
+ files,
3468
+ deploymentTarget: "v8-worker",
3469
+ entrypoint: handler,
3470
+ regions: config.regions,
3471
+ framework: {
3472
+ slug: "react-router",
3473
+ version: frameworkVersion
3474
+ }
3475
+ });
3476
+ } else {
3477
+ fn = new import_build_utils3.NodejsLambda({
3478
+ files,
3479
+ handler,
3480
+ runtime: nodeVersion.runtime,
3481
+ shouldAddHelpers: false,
3482
+ shouldAddSourcemapSupport: false,
3483
+ operationType: "SSR",
3484
+ supportsResponseStreaming: true,
3485
+ useWebApi: true,
3486
+ regions: config.regions,
3487
+ memory: config.memory,
3488
+ maxDuration: config.maxDuration,
3489
+ framework: {
3490
+ slug: "react-router",
3491
+ version: frameworkVersion
3492
+ }
3493
+ });
3494
+ }
3495
+ return fn;
3496
+ }
3497
+ async function createRenderNodeFunction(nodeVersion, entrypointDir, rootDir, serverBuildPath, serverEntryPoint, frameworkVersion, config) {
3343
3498
  const files = {};
3344
3499
  let handler = (0, import_path2.relative)(rootDir, serverBuildPath);
3345
3500
  let handlerPath = (0, import_path2.join)(rootDir, handler);
@@ -3377,12 +3532,12 @@ async function createRenderNodeFunction(nodeVersion, entrypointDir, rootDir, ser
3377
3532
  maxDuration: config.maxDuration,
3378
3533
  framework: {
3379
3534
  slug: "remix",
3380
- version: remixVersion
3535
+ version: frameworkVersion
3381
3536
  }
3382
3537
  });
3383
3538
  return fn;
3384
3539
  }
3385
- async function createRenderEdgeFunction(entrypointDir, rootDir, serverBuildPath, serverEntryPoint, remixVersion, config) {
3540
+ async function createRenderEdgeFunction(entrypointDir, rootDir, serverBuildPath, serverEntryPoint, frameworkVersion, config) {
3386
3541
  const files = {};
3387
3542
  let handler = (0, import_path2.relative)(rootDir, serverBuildPath);
3388
3543
  let handlerPath = (0, import_path2.join)(rootDir, handler);
@@ -3443,7 +3598,7 @@ async function createRenderEdgeFunction(entrypointDir, rootDir, serverBuildPath,
3443
3598
  regions: config.regions,
3444
3599
  framework: {
3445
3600
  slug: "remix",
3446
- version: remixVersion
3601
+ version: frameworkVersion
3447
3602
  }
3448
3603
  });
3449
3604
  return fn;
@@ -3566,8 +3721,7 @@ var build2 = async ({
3566
3721
  lockfileVersion,
3567
3722
  lockfilePath,
3568
3723
  packageJsonPackageManager,
3569
- turboSupportsCorepackHome,
3570
- detectedLockfile
3724
+ turboSupportsCorepackHome
3571
3725
  } = await (0, import_build_utils4.scanParentDirs)(entrypointFsDirname, true);
3572
3726
  if (!packageJsonPath) {
3573
3727
  throw new Error("Failed to locate `package.json` file in your project");
@@ -3587,8 +3741,7 @@ var build2 = async ({
3587
3741
  packageJsonPackageManager,
3588
3742
  nodeVersion,
3589
3743
  env: spawnOpts.env,
3590
- turboSupportsCorepackHome,
3591
- detectedLockfile
3744
+ turboSupportsCorepackHome
3592
3745
  });
3593
3746
  if (typeof installCommand === "string") {
3594
3747
  if (installCommand.trim()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/remix-builder",
3
- "version": "5.0.1",
3
+ "version": "5.1.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.js",
6
6
  "homepage": "https://vercel.com/docs",
@@ -16,7 +16,7 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "@vercel/error-utils": "2.0.3",
19
- "@vercel/nft": "0.27.3",
19
+ "@vercel/nft": "0.27.10",
20
20
  "@vercel/static-config": "3.0.0",
21
21
  "ts-morph": "12.0.0"
22
22
  },
@@ -24,14 +24,14 @@
24
24
  "@types/jest": "27.5.1",
25
25
  "@types/node": "14.18.33",
26
26
  "@types/semver": "7.3.13",
27
- "@vercel/build-utils": "9.0.0",
27
+ "@vercel/build-utils": "9.1.0",
28
28
  "glob": "10.3.16",
29
29
  "jest-junit": "16.0.0",
30
30
  "path-to-regexp": "6.2.1",
31
31
  "semver": "7.5.2",
32
32
  "vitest": "2.0.1"
33
33
  },
34
- "VERCEL_REMIX_RUN_DEV_MAX_VERSION": "2.15.1",
34
+ "VERCEL_REMIX_RUN_DEV_MAX_VERSION": "2.15.2",
35
35
  "scripts": {
36
36
  "build": "node ../../utils/build-builder.mjs",
37
37
  "test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail --runInBand",