Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
pcattori committed May 4, 2023
1 parent 0b6bc2c commit e9edd8c
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 1 deletion.
18 changes: 17 additions & 1 deletion packages/remix-dev/compiler/compiler.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as path from "path";
import type esbuild from "esbuild";

import type { Context } from "./context";
import * as CSS from "./css";
import * as JS from "./js";
import * as Server from "./server";
import * as Channel from "../channel";
import * as HMR from "./hmr/compiler";
import type { Manifest } from "../manifest";
import { create as createManifest, write as writeManifest } from "./manifest";
import { err, ok } from "../result";
Expand All @@ -31,7 +33,11 @@ export let create = async (ctx: Context): Promise<Compiler> => {
css: await CSS.createCompiler(ctx),
js: await JS.createCompiler(ctx, channels),
server: await Server.createCompiler(ctx, channels),
hmr: undefined as esbuild.BuildContext | undefined,
};
if (ctx.options.mode === "development") {
subcompiler.hmr = await HMR.create(ctx);
}
let cancel = async () => {
// resolve channels with error so that downstream tasks don't hang waiting for results from upstream tasks
channels.cssBundleHref.err();
Expand Down Expand Up @@ -66,6 +72,7 @@ export let create = async (ctx: Context): Promise<Compiler> => {
css: subcompiler.css.compile().then(ok, errCancel),
js: subcompiler.js.compile().then(ok, errCancel),
server: subcompiler.server.compile().then(ok, errCancel),
hmr: subcompiler.hmr?.rebuild().then(ok, errCancel),
};

// keep track of manually written artifacts
Expand Down Expand Up @@ -115,14 +122,23 @@ export let create = async (ctx: Context): Promise<Compiler> => {
// artifacts/server
writes.server = Server.write(ctx.config, server.value);

if (ctx.options.mode === "development" && tasks.hmr) {
let hmr = await tasks.hmr;
if (!hmr.ok) throw hmr.error;
console.log("HMR_RESULTS:");
console.log(hmr.value.metafile?.outputs);
}

await Promise.all(Object.values(writes));
return manifest;
};
return {
compile,
cancel,
dispose: async () => {
await Promise.all(Object.values(subcompiler).map((sub) => sub.dispose()));
await Promise.all(
Object.values(subcompiler).map((sub) => sub?.dispose())
);
},
};
};
98 changes: 98 additions & 0 deletions packages/remix-dev/compiler/hmr/compiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import * as path from "node:path";
import esbuild from "esbuild";

import type { Context } from "../context";
import { externalPlugin } from "../plugins/external";
import { emptyModulesPlugin } from "../plugins/emptyModules";
import { createMatchPath } from "../utils/tsconfig";
import invariant from "../../invariant";
import { getRouteModuleExports } from "../utils/routeExports";

function isBareModuleId(id: string): boolean {
return !id.startsWith("node:") && !id.startsWith(".") && !path.isAbsolute(id);
}

type Route = Context["config"]["routes"][string];

export let create = async (ctx: Context) => {
let entryPoints: Record<string, string> = {};
for (let id of Object.keys(ctx.config.routes)) {
entryPoints[id] = ctx.config.routes[id].file + "?loader";
}
let compiler = await esbuild.context({
bundle: true,
entryPoints: entryPoints,
treeShaking: true,
metafile: true,
outdir: "blah",
write: false,
entryNames: "[dir]/[name]-[hash]",
plugins: [
{
name: "hmr-loader",
setup(build) {
let routesByFile: Map<string, Route> = Object.keys(
ctx.config.routes
).reduce((map, key) => {
let route = ctx.config.routes[key];
map.set(route.file, route);
return map;
}, new Map());
let filter = /\?loader$/;
build.onResolve({ filter }, (args) => {
return { path: args.path, namespace: "hmr-loader" };
});
build.onLoad({ filter, namespace: "hmr-loader" }, async (args) => {
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 contents = "module.exports = {};";
if (theExports.includes("loader")) {
contents = `export { loader } from ${JSON.stringify(
`./${file}`
)};`;
}
return {
contents,
resolveDir: ctx.config.appDirectory,
loader: "js",
};
});
},
},
externalPlugin(/^node:.*/, { sideEffects: false }),
externalPlugin(/\.css$/, { sideEffects: false }),
externalPlugin(/^https?:\/\//, { sideEffects: false }),
emptyModulesPlugin(ctx, /\.client(\.[jt]sx?)?$/),
{
name: "hmr-bare-modules",
setup(build) {
let matchPath = ctx.config.tsconfigPath
? createMatchPath(ctx.config.tsconfigPath)
: undefined;
function resolvePath(id: string) {
if (!matchPath) return id;
return (
matchPath(id, undefined, undefined, [
".ts",
".tsx",
".js",
".jsx",
]) || id
);
}
build.onResolve({ filter: /.*/ }, (args) => {
if (!isBareModuleId(resolvePath(args.path))) {
return undefined;
}
return { path: args.path, external: true };
});
},
},
],
});
return compiler;
// let result = await compiler.rebuild();
// console.log(result.metafile.outputs);
};

0 comments on commit e9edd8c

Please sign in to comment.