Skip to content

Instantly share code, notes, and snippets.

@theKashey
Created May 22, 2021 08:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theKashey/5e5f8051aa51fcd3df6e559b1c00c5c1 to your computer and use it in GitHub Desktop.
Save theKashey/5e5f8051aa51fcd3df6e559b1c00c5c1 to your computer and use it in GitHub Desktop.
Node Workers based Webpack StartServerPlugin
import { Worker } from "worker_threads";
import type { Compiler, compilation, Plugin } from "webpack";
interface Options {
name: string;
require?: string[];
keyboard?: boolean;
}
type Callback = () => void;
type Compilation = compilation.Compilation;
export class StartServerPlugin implements Plugin {
private options: Options;
private worker: Worker | null;
private restartWorker: Callback | undefined;
constructor(options: Options) {
this.options = {
// Only listen on keyboard in development, so the server doesn't hang forever
keyboard: process.env.NODE_ENV === "development",
...options,
};
this.worker = null;
this.enableRestarting();
}
apply(compiler: Compiler) {
const plugin = { name: "StartServerPlugin" };
compiler.hooks.afterEmit.tapAsync(plugin, this.afterEmit);
}
private afterEmit = ({ assets }: Compilation, callback: Callback) => {
if (this.worker) {
this.worker.terminate();
}
this.startServer(assets, callback);
};
private enableRestarting() {
if (this.options.keyboard) {
process.stdin.setEncoding("utf8");
process.stdin.on("data", (data: string) => {
if (data.trim() === "rs" && this.restartWorker) {
console.log("Restarting app...");
this.restartWorker();
}
});
}
}
private startServer(assets: Record<string, { existsAt: string }>, callback: Callback) {
const { name } = this.options;
const targetFile = assets[name].existsAt;
if (!targetFile) {
console.error(`Entry ${name} not found. Try one of: ${Object.keys(assets).join(" ")}`);
}
this.restartWorker = () => {
if (this.worker) {
this.worker.terminate();
}
this.spawnWorker(targetFile, callback);
};
this.restartWorker();
}
private spawnWorker(entrypoint: string, callback: Callback) {
this.worker = new Worker(
`
require('v8-compile-cache');
${this.options.require ? this.options.require.join(";\n") : ""}
require('${entrypoint}');
`,
{
eval: true,
}
);
this.worker.on("online", callback);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment