Created
May 22, 2021 08:21
-
-
Save theKashey/5e5f8051aa51fcd3df6e559b1c00c5c1 to your computer and use it in GitHub Desktop.
Node Workers based Webpack StartServerPlugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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