source: imaps-frontend/node_modules/webpack/lib/hmr/lazyCompilationBackend.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8/** @typedef {import("http").IncomingMessage} IncomingMessage */
9/** @typedef {import("http").RequestListener} RequestListener */
10/** @typedef {import("http").ServerOptions} HttpServerOptions */
11/** @typedef {import("http").ServerResponse} ServerResponse */
12/** @typedef {import("https").ServerOptions} HttpsServerOptions */
13/** @typedef {import("net").AddressInfo} AddressInfo */
14/** @typedef {import("net").Server} Server */
15/** @typedef {import("../../declarations/WebpackOptions").LazyCompilationDefaultBackendOptions} LazyCompilationDefaultBackendOptions */
16/** @typedef {import("../Compiler")} Compiler */
17/** @typedef {import("../Module")} Module */
18/** @typedef {import("./LazyCompilationPlugin").BackendApi} BackendApi */
19/** @typedef {import("./LazyCompilationPlugin").BackendHandler} BackendHandler */
20
21/**
22 * @param {Omit<LazyCompilationDefaultBackendOptions, "client"> & { client: NonNullable<LazyCompilationDefaultBackendOptions["client"]>}} options additional options for the backend
23 * @returns {BackendHandler} backend
24 */
25module.exports = options => (compiler, callback) => {
26 const logger = compiler.getInfrastructureLogger("LazyCompilationBackend");
27 const activeModules = new Map();
28 const prefix = "/lazy-compilation-using-";
29
30 const isHttps =
31 options.protocol === "https" ||
32 (typeof options.server === "object" &&
33 ("key" in options.server || "pfx" in options.server));
34
35 const createServer =
36 typeof options.server === "function"
37 ? options.server
38 : (() => {
39 const http = isHttps ? require("https") : require("http");
40 return http.createServer.bind(
41 http,
42 /** @type {HttpServerOptions | HttpsServerOptions} */
43 (options.server)
44 );
45 })();
46 /** @type {function(Server): void} */
47 const listen =
48 typeof options.listen === "function"
49 ? options.listen
50 : server => {
51 let listen = options.listen;
52 if (typeof listen === "object" && !("port" in listen))
53 listen = { ...listen, port: undefined };
54 server.listen(listen);
55 };
56
57 const protocol = options.protocol || (isHttps ? "https" : "http");
58
59 /** @type {RequestListener} */
60 const requestListener = (req, res) => {
61 if (req.url === undefined) return;
62 const keys = req.url.slice(prefix.length).split("@");
63 req.socket.on("close", () => {
64 setTimeout(() => {
65 for (const key of keys) {
66 const oldValue = activeModules.get(key) || 0;
67 activeModules.set(key, oldValue - 1);
68 if (oldValue === 1) {
69 logger.log(
70 `${key} is no longer in use. Next compilation will skip this module.`
71 );
72 }
73 }
74 }, 120000);
75 });
76 req.socket.setNoDelay(true);
77 res.writeHead(200, {
78 "content-type": "text/event-stream",
79 "Access-Control-Allow-Origin": "*",
80 "Access-Control-Allow-Methods": "*",
81 "Access-Control-Allow-Headers": "*"
82 });
83 res.write("\n");
84 let moduleActivated = false;
85 for (const key of keys) {
86 const oldValue = activeModules.get(key) || 0;
87 activeModules.set(key, oldValue + 1);
88 if (oldValue === 0) {
89 logger.log(`${key} is now in use and will be compiled.`);
90 moduleActivated = true;
91 }
92 }
93 if (moduleActivated && compiler.watching) compiler.watching.invalidate();
94 };
95
96 const server = /** @type {Server} */ (createServer());
97 server.on("request", requestListener);
98
99 let isClosing = false;
100 /** @type {Set<import("net").Socket>} */
101 const sockets = new Set();
102 server.on("connection", socket => {
103 sockets.add(socket);
104 socket.on("close", () => {
105 sockets.delete(socket);
106 });
107 if (isClosing) socket.destroy();
108 });
109 server.on("clientError", e => {
110 if (e.message !== "Server is disposing") logger.warn(e);
111 });
112
113 server.on(
114 "listening",
115 /**
116 * @param {Error} err error
117 * @returns {void}
118 */
119 err => {
120 if (err) return callback(err);
121 const _addr = server.address();
122 if (typeof _addr === "string")
123 throw new Error("addr must not be a string");
124 const addr = /** @type {AddressInfo} */ (_addr);
125 const urlBase =
126 addr.address === "::" || addr.address === "0.0.0.0"
127 ? `${protocol}://localhost:${addr.port}`
128 : addr.family === "IPv6"
129 ? `${protocol}://[${addr.address}]:${addr.port}`
130 : `${protocol}://${addr.address}:${addr.port}`;
131 logger.log(
132 `Server-Sent-Events server for lazy compilation open at ${urlBase}.`
133 );
134 callback(null, {
135 dispose(callback) {
136 isClosing = true;
137 // Removing the listener is a workaround for a memory leak in node.js
138 server.off("request", requestListener);
139 server.close(err => {
140 callback(err);
141 });
142 for (const socket of sockets) {
143 socket.destroy(new Error("Server is disposing"));
144 }
145 },
146 module(originalModule) {
147 const key = `${encodeURIComponent(
148 originalModule.identifier().replace(/\\/g, "/").replace(/@/g, "_")
149 ).replace(/%(2F|3A|24|26|2B|2C|3B|3D)/g, decodeURIComponent)}`;
150 const active = activeModules.get(key) > 0;
151 return {
152 client: `${options.client}?${encodeURIComponent(urlBase + prefix)}`,
153 data: key,
154 active
155 };
156 }
157 });
158 }
159 );
160 listen(server);
161};
Note: See TracBrowser for help on using the repository browser.