From e22841062a09cc0f299f7e17b5009a8242b9dba1 Mon Sep 17 00:00:00 2001 From: m5r Date: Sat, 2 Jul 2022 20:25:19 +0200 Subject: [PATCH] restart dev server when something changes and add server sourcemap --- package-lock.json | 66 +++++++++++++++++++++++++++++++++-- package.json | 2 ++ scripts/build-server.js | 28 ++++++++++++++- server/index.ts | 28 ++++++++++----- server/purge-require-cache.ts | 8 +++++ 5 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 server/purge-require-cache.ts diff --git a/package-lock.json b/package-lock.json index d272bb0..166f216 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10 +1,10 @@ { - "name": "shellphoneappremixed", + "name": "shellphone.app", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "shellphoneappremixed", + "name": "shellphone.app", "dependencies": { "@bull-board/express": "3.11.0", "@headlessui/react": "1.6.4", @@ -68,6 +68,7 @@ "@types/morgan": "1.9.3", "@types/nodemailer": "6.4.4", "@types/preview-email": "2.0.1", + "@types/ps-node": "0.1.1", "@types/react": "18.0.10", "@types/react-dom": "18.0.5", "@types/secure-password": "3.1.1", @@ -88,6 +89,7 @@ "prettier": "2.6.2", "prettier-plugin-prisma": "3.14.0", "prisma": "3.14.0", + "ps-node": "0.1.6", "start-server-and-test": "1.14.0", "tailwindcss": "3.0.24", "ts-eager": "npm:@m5r/ts-eager@2.1.0", @@ -4625,6 +4627,12 @@ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", "dev": true }, + "node_modules/@types/ps-node": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@types/ps-node/-/ps-node-0.1.1.tgz", + "integrity": "sha512-t/8CsMBQ1ekBIb+Soqxce6w8M7yt0jRoXgsWHkS66VQ9OcMDQeoRLzz+gGpVeBc8pVskOTwRbCqHxDOGFwkgsg==", + "dev": true + }, "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", @@ -7187,6 +7195,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/connected-domain": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz", + "integrity": "sha512-lHlohUiJxlpunvDag2Y0pO20bnvarMjnrdciZeuJUqRwrf/5JHNhdpiPIr5GQ8IkqrFj5TDMQwcCjblGo1oeuA==", + "dev": true + }, "node_modules/constantinople": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", @@ -17870,6 +17884,15 @@ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", "dev": true }, + "node_modules/ps-node": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz", + "integrity": "sha512-w7QJhUTbu70hpDso0YXDRNKCPNuchV8UTUZsAv0m7Qj5g85oHOJfr9drA1EjvK4nQK/bG8P97W4L6PJ3IQLoOA==", + "dev": true, + "dependencies": { + "table-parser": "^0.1.3" + } + }, "node_modules/ps-tree": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", @@ -20767,6 +20790,15 @@ "node": ">=4" } }, + "node_modules/table-parser": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz", + "integrity": "sha512-LCYeuvqqoPII3lzzYaXKbC3Forb+d2u4bNwhk/9FlivuGRxPE28YEWAYcujeSlLLDlMfvy29+WPybFJZFiKMYg==", + "dev": true, + "dependencies": { + "connected-domain": "^1.0.0" + } + }, "node_modules/tailwindcss": { "version": "3.0.24", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", @@ -26110,6 +26142,12 @@ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", "dev": true }, + "@types/ps-node": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@types/ps-node/-/ps-node-0.1.1.tgz", + "integrity": "sha512-t/8CsMBQ1ekBIb+Soqxce6w8M7yt0jRoXgsWHkS66VQ9OcMDQeoRLzz+gGpVeBc8pVskOTwRbCqHxDOGFwkgsg==", + "dev": true + }, "@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", @@ -28067,6 +28105,12 @@ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" }, + "connected-domain": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz", + "integrity": "sha512-lHlohUiJxlpunvDag2Y0pO20bnvarMjnrdciZeuJUqRwrf/5JHNhdpiPIr5GQ8IkqrFj5TDMQwcCjblGo1oeuA==", + "dev": true + }, "constantinople": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", @@ -35807,6 +35851,15 @@ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", "dev": true }, + "ps-node": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz", + "integrity": "sha512-w7QJhUTbu70hpDso0YXDRNKCPNuchV8UTUZsAv0m7Qj5g85oHOJfr9drA1EjvK4nQK/bG8P97W4L6PJ3IQLoOA==", + "dev": true, + "requires": { + "table-parser": "^0.1.3" + } + }, "ps-tree": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", @@ -38141,6 +38194,15 @@ } } }, + "table-parser": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz", + "integrity": "sha512-LCYeuvqqoPII3lzzYaXKbC3Forb+d2u4bNwhk/9FlivuGRxPE28YEWAYcujeSlLLDlMfvy29+WPybFJZFiKMYg==", + "dev": true, + "requires": { + "connected-domain": "^1.0.0" + } + }, "tailwindcss": { "version": "3.0.24", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", diff --git a/package.json b/package.json index 9cc255a..5cff03a 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "@types/morgan": "1.9.3", "@types/nodemailer": "6.4.4", "@types/preview-email": "2.0.1", + "@types/ps-node": "0.1.1", "@types/react": "18.0.10", "@types/react-dom": "18.0.5", "@types/secure-password": "3.1.1", @@ -109,6 +110,7 @@ "prettier": "2.6.2", "prettier-plugin-prisma": "3.14.0", "prisma": "3.14.0", + "ps-node": "0.1.6", "start-server-and-test": "1.14.0", "tailwindcss": "3.0.24", "ts-eager": "npm:@m5r/ts-eager@2.1.0", diff --git a/scripts/build-server.js b/scripts/build-server.js index a2568e4..8247eda 100644 --- a/scripts/build-server.js +++ b/scripts/build-server.js @@ -1,6 +1,7 @@ const path = require("path"); const esbuild = require("esbuild"); const { nodeExternalsPlugin } = require("esbuild-node-externals"); +const ps = require("ps-node"); const basePath = process.cwd(); const args = process.argv.slice(2); @@ -14,6 +15,7 @@ esbuild platform: "node", format: "cjs", bundle: true, + sourcemap: "inline", plugins: [ nodeExternalsPlugin({ packagePath: path.join(basePath, "package.json") }), { @@ -37,7 +39,31 @@ esbuild process.exit(1); } - console.log("Server rebuilt successfully"); // TODO: find a way to restart the dev server process + ps.lookup( + { + command: "node", + arguments: "./server/index.js", + }, + (error, processes) => { + if (error) { + throw new Error(error); + } + + if (processes.length === 0) { + return; + } + + const devServerProcess = processes.reduce((prev, current) => { + if (prev.pid > current.pid) { + return prev; + } + + return current; + }, processes[0]); + process.kill(devServerProcess.pid, "SIGUSR2"); + }, + ); + console.log("Server rebuilt successfully"); }, } : false, diff --git a/server/index.ts b/server/index.ts index 94d3bac..8f511e6 100644 --- a/server/index.ts +++ b/server/index.ts @@ -8,13 +8,16 @@ import config from "~/config/config.server"; import logger from "~/utils/logger.server"; import { adminMiddleware, setupBullBoard } from "./queues"; import { registerSentry, sentryLoadContext } from "./sentry-remix"; +import { purgeRequireCache } from "./purge-require-cache"; + +const environment = process.env.NODE_ENV; if (config.sentry.dsn) { Sentry.init({ dsn: config.sentry.dsn, integrations: [new Sentry.Integrations.Http({ tracing: true })], tracesSampleRate: 1.0, - environment: process.env.NODE_ENV, + environment, }); } @@ -82,13 +85,13 @@ app.use("/admin/queues", setupBullBoard().getRouter()); app.use(morgan("tiny")); app.all("*", (req, res, next) => { - if (process.env.NODE_ENV !== "production") { + if (environment !== "production") { purgeRequireCache(); } return createRequestHandler({ build: registerSentry(require("../build")), - mode: process.env.NODE_ENV, + mode: environment, getLoadContext: sentryLoadContext, })(req, res, next); }); @@ -98,11 +101,18 @@ app.listen(port, () => { logger.info(`Server listening on port ${port}`); }); -function purgeRequireCache() { - const resolved = require.resolve("../build"); - for (const key in require.cache) { - if (key.startsWith(resolved)) { - delete require.cache[key]; +if (environment !== "production") { + process.on("SIGUSR2", () => process.exit(229)); + + process.on("exit", (exitCode) => { + if (exitCode !== 229) { + return; } - } + + require("child_process").spawn(process.argv.shift(), process.argv, { + cwd: process.cwd(), + detached: true, + stdio: "inherit", + }); + }); } diff --git a/server/purge-require-cache.ts b/server/purge-require-cache.ts new file mode 100644 index 0000000..75cd59c --- /dev/null +++ b/server/purge-require-cache.ts @@ -0,0 +1,8 @@ +export function purgeRequireCache() { + const resolved = require.resolve("../build"); + for (const key in require.cache) { + if (key.startsWith(resolved)) { + delete require.cache[key]; + } + } +}