Skip to content

Commit

Permalink
cache getRouteModuleExports calls
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-ebey committed Jun 16, 2023
1 parent 382edbe commit 1391b1f
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/rude-meals-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/dev": patch
---

cache getRouteModuleExports calls to significantly speed up build and HMR rebuild times
1 change: 1 addition & 0 deletions packages/remix-dev/compiler/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export let create = async (ctx: Context): Promise<Compiler> => {
config: ctx.config,
metafile,
hmr,
fileWatchCache: ctx.fileWatchCache,
});
refs.manifestChannel.ok(manifest);
options.onManifest?.(manifest);
Expand Down
20 changes: 18 additions & 2 deletions packages/remix-dev/compiler/js/plugins/routes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as path from "node:path";
import type esbuild from "esbuild";

import type { RemixConfig } from "../../../config";
Expand All @@ -22,7 +23,7 @@ const browserSafeRouteExports: { [name: string]: boolean } = {
* that re-export only the route module exports that are safe for the browser.
*/
export function browserRouteModulesPlugin(
{ config }: Context,
{ config, fileWatchCache }: Context,
suffixMatcher: RegExp
): esbuild.Plugin {
return {
Expand Down Expand Up @@ -54,7 +55,22 @@ export function browserRouteModulesPlugin(
try {
invariant(route, `Cannot get route by path: ${args.path}`);

theExports = (await getRouteModuleExports(config, route.id)).filter(
let cacheKey = `module-exports:${route.id}`;
let { cacheValue: sourceExports } = await fileWatchCache.getOrSet(
cacheKey,
async () => {
let file = path.resolve(
config.appDirectory,
config.routes[route!.id].file
);
return {
cacheValue: await getRouteModuleExports(config, route!.id),
fileDependencies: new Set([file]),
};
}
);

theExports = sourceExports.filter(
(ex) => !!browserSafeRouteExports[ex]
);
} catch (error: any) {
Expand Down
19 changes: 18 additions & 1 deletion packages/remix-dev/compiler/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ import invariant from "../invariant";
import { type Manifest } from "../manifest";
import { getRouteModuleExports } from "./utils/routeExports";
import { getHash } from "./utils/crypto";
import { type FileWatchCache } from "./fileWatchCache";

type Route = RemixConfig["routes"][string];

export async function create({
config,
metafile,
hmr,
fileWatchCache,
}: {
config: RemixConfig;
metafile: esbuild.Metafile;
hmr?: Manifest["hmr"];
fileWatchCache: FileWatchCache;
}): Promise<Manifest> {
function resolveUrl(outputPath: string): string {
return createUrl(
Expand Down Expand Up @@ -70,7 +73,21 @@ export async function create({
`Cannot get route(s) for entry point ${output.entryPoint}`
);
for (let route of groupedRoute) {
let sourceExports = await getRouteModuleExports(config, route.id);
let cacheKey = `module-exports:${route.id}`;
let { cacheValue: sourceExports } = await fileWatchCache.getOrSet(
cacheKey,
async () => {
let file = path.resolve(
config.appDirectory,
config.routes[route.id].file
);
return {
cacheValue: await getRouteModuleExports(config, route.id),
fileDependencies: new Set([file]),
};
}
);

routes[route.id] = {
id: route.id,
parentId: route.parentId,
Expand Down
19 changes: 18 additions & 1 deletion packages/remix-dev/devServer_unstable/hdr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,24 @@ export let detectLoaderChanges = async (
let file = args.path.replace(filter, "");
let route = routesByFile.get(file);
invariant(route, `Cannot get route by path: ${args.path}`);
let theExports = await getRouteModuleExports(ctx.config, route.id);
let cacheKey = `module-exports:${route.id}`;
let { cacheValue: theExports } = await ctx.fileWatchCache.getOrSet(
cacheKey,
async () => {
let file = path.resolve(
ctx.config.appDirectory,
ctx.config.routes[route!.id].file
);
return {
cacheValue: await getRouteModuleExports(
ctx.config,
route!.id
),
fileDependencies: new Set([file]),
};
}
);

let contents = "module.exports = {};";
if (theExports.includes("loader")) {
contents = `export { loader } from ${JSON.stringify(
Expand Down

0 comments on commit 1391b1f

Please sign in to comment.