import { createRequire } from 'node:module'; import { rspack, type Configuration as RspackConfiguration, type DevServer as RspackDevServerConfiguration, } from '@rspack/core'; import { RspackDevServer } from '@rspack/dev-server'; import { dirname } from 'node:path'; import webpack, { type Configuration as WebpackConfiguration } from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; import { logInfo } from './logger'; function getWebpackEnv() { return { ...process.env, analyze: process.env.BUNDLE_ANALYZE === 'true', production: process.env.NODE_ENV === 'production', development: process.env.NODE_ENV === 'development', }; } function loadConfig(configPath: string): WebpackConfiguration | RspackConfiguration { const require = createRequire(import.meta.url); const content: | WebpackConfiguration | RspackConfiguration | ((env: Record) => WebpackConfiguration | RspackConfiguration) = require(configPath); if (typeof content === 'function') { return content(getWebpackEnv()); } return content; } function startDevServer(configPath: string, port: number, useRspack: boolean = false) { const config = loadConfig(configPath); const devServerOptions = { ...config.devServer, port, static: dirname(configPath), }; let compilationDone = false; let serverListening = false; function signalReadyIfBothDone() { if (compilationDone && serverListening) { process.send?.({ type: 'compilation-complete' }); } } let server: WebpackDevServer | RspackDevServer; if (!useRspack) { const compiler = webpack(config as WebpackConfiguration); compiler.hooks.done.tap('OpenMRSDevServer', () => { if (!compilationDone) { compilationDone = true; signalReadyIfBothDone(); } }); server = new WebpackDevServer(devServerOptions as WebpackDevServer.Configuration, compiler); } else { const compiler = rspack(config as RspackConfiguration); compiler.hooks.done.tap('OpenMRSDevServer', () => { if (!compilationDone) { compilationDone = true; signalReadyIfBothDone(); } }); server = new RspackDevServer(devServerOptions as RspackDevServerConfiguration, compiler); } server.startCallback(() => { logInfo(`Listening at http://localhost:${port}`); serverListening = true; signalReadyIfBothDone(); }); } process.on('message', ({ source, port, useRspack }: { source: string; port: number; useRspack: boolean }) => startDevServer(source, port, useRspack), );