[remix] Allow runtime to be defined from a parent route (#9473)

Make it so that the `export const config = { runtime }` value is "inherited" from a parent route, if it is defined.

For example, "edge" can be defined in `app/root.tsx`, and so all routes will use the Edge runtime by default, unless `"runtime": "nodejs"` is used more specifically in a route deeper in the route hierarchy.
This commit is contained in:
Nathan Rajlich
2023-02-22 12:35:12 -08:00
committed by GitHub
parent 1f51e04387
commit 4da176d26f
6 changed files with 80 additions and 18 deletions

View File

@@ -18,7 +18,7 @@ import {
scanParentDirs,
walkParentDirs,
} from '@vercel/build-utils';
import { getConfig } from '@vercel/static-config';
import { getConfig, BaseFunctionConfig } from '@vercel/static-config';
import { nodeFileTrace } from '@vercel/nft';
import { readConfig, RemixConfig } from '@remix-run/dev/dist/config';
import type {
@@ -33,6 +33,7 @@ import {
findConfig,
getPathFromRoute,
getRegExpFromPath,
getRouteIterator,
isLayoutRoute,
} from './utils';
@@ -181,16 +182,17 @@ module.exports = config;`;
const remixRoutes = Object.values(remixConfig.routes);
// Figure out which pages should be edge functions
const edgePages = new Set<ConfigRoute>();
let hasEdgeRoute = false;
const staticConfigsMap = new Map<ConfigRoute, BaseFunctionConfig>();
const project = new Project();
for (const route of remixRoutes) {
const routePath = join(remixConfig.appDirectory, route.file);
const staticConfig = getConfig(project, routePath);
const isEdge =
staticConfig?.runtime === 'edge' ||
staticConfig?.runtime === 'experimental-edge';
if (isEdge) {
edgePages.add(route);
if (staticConfig) {
staticConfigsMap.set(route, staticConfig);
}
if (staticConfig?.runtime && isEdgeRuntime(staticConfig.runtime)) {
hasEdgeRoute = true;
}
}
@@ -212,7 +214,7 @@ module.exports = config;`;
serverBuildPath,
nodeVersion
),
edgePages.size > 0
hasEdgeRoute
? createRenderEdgeFunction(
entrypointFsDirname,
repoRootPath,
@@ -238,7 +240,16 @@ module.exports = config;`;
if (isLayoutRoute(route.id, remixRoutes)) continue;
const path = getPathFromRoute(route, remixConfig.routes);
const isEdge = edgePages.has(route);
let isEdge = false;
for (const currentRoute of getRouteIterator(route, remixConfig.routes)) {
const staticConfig = staticConfigsMap.get(currentRoute);
if (staticConfig?.runtime) {
isEdge = isEdgeRuntime(staticConfig.runtime);
break;
}
}
const fn =
isEdge && edgeFunction
? // `EdgeFunction` currently requires the "name" property to be set.
@@ -461,3 +472,7 @@ async function ensureResolvable(start: string, base: string, pkgName: string) {
`Failed to resolve "${pkgName}". To fix this error, add "${pkgName}" to "dependencies" in your \`package.json\` file.`
);
}
function isEdgeRuntime(runtime: string): boolean {
return runtime === 'edge' || runtime === 'experimental-edge';
}

View File

@@ -25,21 +25,27 @@ export function isLayoutRoute(
return routes.some(r => r.parentId === routeId);
}
export function* getRouteIterator(route: ConfigRoute, routes: RouteManifest) {
let currentRoute: ConfigRoute = route;
do {
yield currentRoute;
if (currentRoute.parentId) {
currentRoute = routes[currentRoute.parentId];
} else {
break;
}
} while (currentRoute);
}
export function getPathFromRoute(
route: ConfigRoute,
routes: RouteManifest
): string {
let currentRoute: ConfigRoute | undefined = route;
const pathParts: string[] = [];
do {
for (const currentRoute of getRouteIterator(route, routes)) {
if (currentRoute.index) pathParts.push('index');
if (currentRoute.path) pathParts.push(currentRoute.path);
if (currentRoute.parentId) {
currentRoute = routes[currentRoute.parentId];
} else {
currentRoute = undefined;
}
} while (currentRoute);
}
const path = pathParts.reverse().join('/');
return path;
}