diff --git a/.changeset/dev-server-node18-close.md b/.changeset/dev-server-node18-close.md new file mode 100644 index 000000000..1b5b4f2f0 --- /dev/null +++ b/.changeset/dev-server-node18-close.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack-dev-server": patch +--- + +Fix dev server shutdown hanging on Node 18 with fastify 5.12+ by force-closing open connections on stop diff --git a/apps/tester-app/rspack.config.mjs b/apps/tester-app/rspack.config.mjs index 80bd93db2..641ffbb37 100644 --- a/apps/tester-app/rspack.config.mjs +++ b/apps/tester-app/rspack.config.mjs @@ -2,7 +2,12 @@ import path from 'node:path'; import * as Repack from '@callstack/repack'; import { NativeWindPlugin } from '@callstack/repack-plugin-nativewind'; import { ReanimatedPlugin } from '@callstack/repack-plugin-reanimated'; -import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin'; + +// Rsdoctor (through rslog) throws on import under Node < 20, so only load it +// when it's actually enabled to keep the Node 18 test matrix working. +const { RsdoctorRspackPlugin } = process.env.RSDOCTOR + ? await import('@rsdoctor/rspack-plugin') + : {}; const dirname = Repack.getDirname(import.meta.url); diff --git a/packages/dev-server/src/createServer.ts b/packages/dev-server/src/createServer.ts index 404d956d3..5c1805c91 100644 --- a/packages/dev-server/src/createServer.ts +++ b/packages/dev-server/src/createServer.ts @@ -28,6 +28,10 @@ export async function createServer(config: Server.Config) { /** Fastify instance powering the development server. */ const instance = Fastify({ + // Since fastify 5.12 the default ('idle') leaves idle keep-alive sockets + // to `server.close()`, which only closes them on Node 19+. Force-closing + // keeps `stop()` from hanging on Node 18. + forceCloseConnections: true, disableRequestLogging: options.disableRequestLogging, logger: { level: 'trace',