[6a3a178] | 1 | /*
|
---|
| 2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
---|
| 3 | Author Tobias Koppers @sokra
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | "use strict";
|
---|
| 7 |
|
---|
| 8 | const http = require("http");
|
---|
| 9 |
|
---|
| 10 | /** @typedef {import("../Compiler")} Compiler */
|
---|
| 11 |
|
---|
| 12 | /**
|
---|
| 13 | * @param {Compiler} compiler compiler
|
---|
| 14 | * @param {string} client client reference
|
---|
| 15 | * @param {function(Error?, any?): void} callback callback
|
---|
| 16 | * @returns {void}
|
---|
| 17 | */
|
---|
| 18 | module.exports = (compiler, client, callback) => {
|
---|
| 19 | const logger = compiler.getInfrastructureLogger("LazyCompilationBackend");
|
---|
| 20 | const activeModules = new Map();
|
---|
| 21 | const prefix = "/lazy-compilation-using-";
|
---|
| 22 |
|
---|
| 23 | const requestListener = (req, res) => {
|
---|
| 24 | const keys = req.url.slice(prefix.length).split("@");
|
---|
| 25 | req.socket.on("close", () => {
|
---|
| 26 | setTimeout(() => {
|
---|
| 27 | for (const key of keys) {
|
---|
| 28 | const oldValue = activeModules.get(key) || 0;
|
---|
| 29 | activeModules.set(key, oldValue - 1);
|
---|
| 30 | if (oldValue === 1) {
|
---|
| 31 | logger.log(
|
---|
| 32 | `${key} is no longer in use. Next compilation will skip this module.`
|
---|
| 33 | );
|
---|
| 34 | }
|
---|
| 35 | }
|
---|
| 36 | }, 120000);
|
---|
| 37 | });
|
---|
| 38 | req.socket.setNoDelay(true);
|
---|
| 39 | res.writeHead(200, {
|
---|
| 40 | "content-type": "text/event-stream",
|
---|
| 41 | "Access-Control-Allow-Origin": "*"
|
---|
| 42 | });
|
---|
| 43 | res.write("\n");
|
---|
| 44 | let moduleActivated = false;
|
---|
| 45 | for (const key of keys) {
|
---|
| 46 | const oldValue = activeModules.get(key) || 0;
|
---|
| 47 | activeModules.set(key, oldValue + 1);
|
---|
| 48 | if (oldValue === 0) {
|
---|
| 49 | logger.log(`${key} is now in use and will be compiled.`);
|
---|
| 50 | moduleActivated = true;
|
---|
| 51 | }
|
---|
| 52 | }
|
---|
| 53 | if (moduleActivated && compiler.watching) compiler.watching.invalidate();
|
---|
| 54 | };
|
---|
| 55 | const server = http.createServer(requestListener);
|
---|
| 56 | let isClosing = false;
|
---|
| 57 | /** @type {Set<import("net").Socket>} */
|
---|
| 58 | const sockets = new Set();
|
---|
| 59 | server.on("connection", socket => {
|
---|
| 60 | sockets.add(socket);
|
---|
| 61 | socket.on("close", () => {
|
---|
| 62 | sockets.delete(socket);
|
---|
| 63 | });
|
---|
| 64 | if (isClosing) socket.destroy();
|
---|
| 65 | });
|
---|
| 66 | server.listen(err => {
|
---|
| 67 | if (err) return callback(err);
|
---|
| 68 | const addr = server.address();
|
---|
| 69 | if (typeof addr === "string") throw new Error("addr must not be a string");
|
---|
| 70 | const urlBase =
|
---|
| 71 | addr.address === "::" || addr.address === "0.0.0.0"
|
---|
| 72 | ? `http://localhost:${addr.port}`
|
---|
| 73 | : addr.family === "IPv6"
|
---|
| 74 | ? `http://[${addr.address}]:${addr.port}`
|
---|
| 75 | : `http://${addr.address}:${addr.port}`;
|
---|
| 76 | logger.log(
|
---|
| 77 | `Server-Sent-Events server for lazy compilation open at ${urlBase}.`
|
---|
| 78 | );
|
---|
| 79 | callback(null, {
|
---|
| 80 | dispose(callback) {
|
---|
| 81 | isClosing = true;
|
---|
| 82 | // Removing the listener is a workaround for a memory leak in node.js
|
---|
| 83 | server.off("request", requestListener);
|
---|
| 84 | server.close(err => {
|
---|
| 85 | callback(err);
|
---|
| 86 | });
|
---|
| 87 | for (const socket of sockets) {
|
---|
| 88 | socket.destroy(new Error("Server is disposing"));
|
---|
| 89 | }
|
---|
| 90 | },
|
---|
| 91 | module(originalModule) {
|
---|
| 92 | const key = `${encodeURIComponent(
|
---|
| 93 | originalModule.identifier().replace(/\\/g, "/").replace(/@/g, "_")
|
---|
| 94 | ).replace(/%(2F|3A|24|26|2B|2C|3B|3D|3A)/g, decodeURIComponent)}`;
|
---|
| 95 | const active = activeModules.get(key) > 0;
|
---|
| 96 | return {
|
---|
| 97 | client: `${client}?${encodeURIComponent(urlBase + prefix)}`,
|
---|
| 98 | data: key,
|
---|
| 99 | active
|
---|
| 100 | };
|
---|
| 101 | }
|
---|
| 102 | });
|
---|
| 103 | });
|
---|
| 104 | };
|
---|