Skip to content

Commit

Permalink
feat(templates/express): server-side "hmr" via import cache busting
Browse files Browse the repository at this point in the history
  • Loading branch information
pcattori committed May 4, 2023
1 parent b84c9bd commit 3f0ba37
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
3 changes: 2 additions & 1 deletion templates/express/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "module",
"scripts": {
"build": "remix build",
"dev": "remix dev -c \"node server.js\"",
"dev": "remix dev --no-restart -c \"node server.js\"",
"start": "cross-env NODE_ENV=production node ./server.js",
"typecheck": "tsc"
},
Expand All @@ -29,6 +29,7 @@
"@types/morgan": "^1.9.4",
"@types/react": "^18.0.35",
"@types/react-dom": "^18.0.11",
"chokidar": "^3.5.3",
"eslint": "^8.38.0",
"typescript": "^5.0.4"
},
Expand Down
46 changes: 41 additions & 5 deletions templates/express/server.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as fs from "node:fs";
import chokidar from "chokidar";
import express from "express";
import compression from "compression";
import morgan from "morgan";
Expand All @@ -6,6 +8,8 @@ import { broadcastDevReady, installGlobals } from "@remix-run/node";

import * as build from "./build/index.js";

const BUILD_PATH = "./build/index.js";

installGlobals();

const app = express();
Expand All @@ -29,17 +33,49 @@ app.use(morgan("tiny"));

app.all(
"*",
createRequestHandler({
build,
mode: process.env.NODE_ENV,
})
process.env.NODE_ENV === "development"
? createDevRequestHandler()
: createRequestHandler({
build,
mode: process.env.NODE_ENV,
})
);

const port = process.env.PORT || 3000;
app.listen(port, () => {
app.listen(port, async () => {
console.log(`Express server listening on port ${port}`);

if (process.env.NODE_ENV === "development") {
broadcastDevReady(build);
}
});

function createDevRequestHandler() {
// initial build
/**
* @type { import('@remix-run/node').ServerBuild | Promise<import('@remix-run/node').ServerBuild> }
*/
let devBuild = build;

const watcher = chokidar.watch(BUILD_PATH, { ignoreInitial: true });

watcher.on("all", async () => {
// 1. purge require cache && load updated server build
const stat = fs.statSync(BUILD_PATH);
devBuild = import(BUILD_PATH + "?t=" + stat.mtimeMs);
// 2. tell dev server that this app server is now ready
broadcastDevReady(await devBuild);
});

return async (req, res, next) => {
try {
//
return createRequestHandler({
build: await devBuild,
mode: "development",
})(req, res, next);
} catch (error) {
next(error);
}
};
}

0 comments on commit 3f0ba37

Please sign in to comment.