Skip to content

Commit ba154bc

Browse files
committed
refactor and add test case
1 parent 537da95 commit ba154bc

File tree

14 files changed

+431
-187
lines changed

14 files changed

+431
-187
lines changed

declarations/WebpackOptions.d.ts

Lines changed: 60 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,43 +1117,7 @@ export interface Experiments {
11171117
/**
11181118
* Compile entrypoints and import()s only when they are accessed.
11191119
*/
1120-
lazyCompilation?:
1121-
| boolean
1122-
| {
1123-
/**
1124-
* A custom backend.
1125-
*/
1126-
backend?:
1127-
| ((
1128-
compiler: import("../lib/Compiler"),
1129-
client: string,
1130-
callback: (err?: Error, api?: any) => void
1131-
) => void)
1132-
| ((
1133-
compiler: import("../lib/Compiler"),
1134-
client: string
1135-
) => Promise<any>);
1136-
/**
1137-
* Additional configuration to pass to the backend server.
1138-
*/
1139-
backendConfiguration?: import("../lib/hmr/lazyCompilationBackend").BackendConfiguration;
1140-
/**
1141-
* A custom client.
1142-
*/
1143-
client?: string;
1144-
/**
1145-
* Enable/disable lazy compilation for entries.
1146-
*/
1147-
entries?: boolean;
1148-
/**
1149-
* Enable/disable lazy compilation for import() modules.
1150-
*/
1151-
imports?: boolean;
1152-
/**
1153-
* Specify which entrypoints or import()ed modules should be lazily compiled. This is matched with the imported module and not the entrypoint name.
1154-
*/
1155-
test?: RegExp | string | ((module: import("../lib/Module")) => boolean);
1156-
};
1120+
lazyCompilation?: boolean | LazyCompilationOptions;
11571121
/**
11581122
* Allow output javascript files as module source type.
11591123
*/
@@ -1188,6 +1152,65 @@ export interface HttpUriOptions {
11881152
*/
11891153
upgrade?: boolean;
11901154
}
1155+
/**
1156+
* This interface was referenced by `WebpackOptions`'s JSON-Schema
1157+
* via the `definition` "LazyCompilationOptions".
1158+
*/
1159+
export interface LazyCompilationOptions {
1160+
backend?:
1161+
| (
1162+
| ((
1163+
compiler: import("../lib/Compiler"),
1164+
callback: (
1165+
err?: Error,
1166+
api?: import("../lib/hmr/LazyCompilationPlugin").BackendApi
1167+
) => void
1168+
) => void)
1169+
| ((
1170+
compiler: import("../lib/Compiler")
1171+
) => Promise<import("../lib/hmr/LazyCompilationPlugin").BackendApi>)
1172+
)
1173+
| LazyCompilationDefaultBackendOptions;
1174+
/**
1175+
* Enable/disable lazy compilation for entries.
1176+
*/
1177+
entries?: boolean;
1178+
/**
1179+
* Enable/disable lazy compilation for import() modules.
1180+
*/
1181+
imports?: boolean;
1182+
/**
1183+
* Specify which entrypoints or import()ed modules should be lazily compiled. This is matched with the imported module and not the entrypoint name.
1184+
*/
1185+
test?: RegExp | string | ((module: import("../lib/Module")) => boolean);
1186+
}
1187+
/**
1188+
* Options for the default backend.
1189+
*/
1190+
export interface LazyCompilationDefaultBackendOptions {
1191+
/**
1192+
* A custom client.
1193+
*/
1194+
client?: string;
1195+
/**
1196+
* Specifies where to listen to from the server.
1197+
*/
1198+
listen?:
1199+
| number
1200+
| import("net").ListenOptions
1201+
| ((server: import("net").Server) => void);
1202+
/**
1203+
* Specifies the protocol the client should use to connect to the server.
1204+
*/
1205+
protocol?: "http" | "https";
1206+
/**
1207+
* Specifies how to create the server handling the EventSource requests.
1208+
*/
1209+
server?:
1210+
| (import("https").ServerOptions | import("http").ServerOptions)
1211+
| (() => import("net").Server);
1212+
[k: string]: any;
1213+
}
11911214
/**
11921215
* Enable presets of externals for specific targets.
11931216
*/

hot/lazy-compilation-node.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ exports.keepAlive = function (options) {
99
var active = options.active;
1010
var module = options.module;
1111
var response;
12-
var request = require("http").request(
12+
var request = (
13+
urlBase.startsWith("https") ? require("https") : require("http")
14+
).request(
1315
urlBase + data,
1416
{
1517
agent: false,

lib/WebpackOptionsApply.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -261,20 +261,21 @@ class WebpackOptionsApply extends OptionsApply {
261261
: null;
262262
new LazyCompilationPlugin({
263263
backend:
264-
(lazyOptions && lazyOptions.backend) ||
265-
require("./hmr/lazyCompilationBackend"),
266-
client:
267-
(lazyOptions && lazyOptions.client) ||
268-
require.resolve(
269-
`../hot/lazy-compilation-${
270-
options.externalsPresets.node ? "node" : "web"
271-
}.js`
272-
),
264+
typeof lazyOptions.backend === "function"
265+
? lazyOptions.backend
266+
: require("./hmr/lazyCompilationBackend")({
267+
...lazyOptions.backend,
268+
client:
269+
lazyOptions.backend.client ||
270+
require.resolve(
271+
`../hot/lazy-compilation-${
272+
options.externalsPresets.node ? "node" : "web"
273+
}.js`
274+
)
275+
}),
273276
entries: !lazyOptions || lazyOptions.entries !== false,
274277
imports: !lazyOptions || lazyOptions.imports !== false,
275-
test: (lazyOptions && lazyOptions.test) || undefined,
276-
backendConfiguration:
277-
(lazyOptions && lazyOptions.backendConfiguration) || undefined
278+
test: (lazyOptions && lazyOptions.test) || undefined
278279
}).apply(compiler);
279280
}
280281

lib/hmr/LazyCompilationPlugin.js

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ const { registerNotSerializable } = require("../util/serialization");
3232
/** @typedef {import("../util/Hash")} Hash */
3333
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
3434

35+
/**
36+
* @typedef {Object} BackendApi
37+
* @property {function(Error=): void} dispose
38+
* @property {function(Module): { client: string, data: string, active: boolean }} module
39+
*/
40+
3541
const IGNORED_DEPENDENCY_TYPES = new Set([
3642
"import.meta.webpackHot.accept",
3743
"import.meta.webpackHot.decline",
@@ -303,27 +309,16 @@ class LazyCompilationDependencyFactory extends ModuleFactory {
303309
class LazyCompilationPlugin {
304310
/**
305311
* @param {Object} options options
306-
* @param {(function(Compiler, string, function(Error?, any?): void, Object): void) | function(Compiler, string): Promise<any>} options.backend the backend
307-
* @param {Object} options.backendConfiguration additional configuration passed to backend
308-
* @param {string} options.client the client reference
312+
* @param {(function(Compiler, function(Error?, BackendApi?): void): void) | function(Compiler): Promise<BackendApi>} options.backend the backend
309313
* @param {boolean} options.entries true, when entries are lazy compiled
310314
* @param {boolean} options.imports true, when import() modules are lazy compiled
311315
* @param {RegExp | string | (function(Module): boolean)} options.test additional filter for lazy compiled entrypoint modules
312316
*/
313-
constructor({
314-
backend,
315-
client,
316-
entries,
317-
imports,
318-
test,
319-
backendConfiguration
320-
}) {
317+
constructor({ backend, entries, imports, test }) {
321318
this.backend = backend;
322-
this.client = client;
323319
this.entries = entries;
324320
this.imports = imports;
325321
this.test = test;
326-
this.backendConfiguration = backendConfiguration;
327322
}
328323
/**
329324
* Apply the plugin
@@ -336,16 +331,11 @@ class LazyCompilationPlugin {
336331
"LazyCompilationPlugin",
337332
(params, callback) => {
338333
if (backend !== undefined) return callback();
339-
const promise = this.backend(
340-
compiler,
341-
this.client,
342-
(err, result) => {
343-
if (err) return callback(err);
344-
backend = result;
345-
callback();
346-
},
347-
this.backendConfiguration
348-
);
334+
const promise = this.backend(compiler, (err, result) => {
335+
if (err) return callback(err);
336+
backend = result;
337+
callback();
338+
});
349339
if (promise && promise.then) {
350340
promise.then(b => {
351341
backend = b;

lib/hmr/lazyCompilationBackend.js

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,43 @@
77

88
/** @typedef {import("http").ServerOptions} HttpServerOptions */
99
/** @typedef {import("https").ServerOptions} HttpsServerOptions */
10+
/** @typedef {import("../../declarations/WebpackOptions").LazyCompilationDefaultBackendOptions} LazyCompilationDefaultBackendOptions */
1011
/** @typedef {import("../Compiler")} Compiler */
1112

1213
/**
13-
* @typedef {Object} BackendConfiguration
14-
* @property {HttpServerOptions} httpServerOptions Options to be passed to the Node.js HTTP module.
15-
* @property {HttpsServerOptions} httpsServerOptions Options to be passed to the Node.js HTTPS module.
16-
* @property {number?} port Custom port for lazy compilation backend. If not defined, a random port will be used.
17-
*/
18-
19-
/**
14+
* @callback BackendHandler
2015
* @param {Compiler} compiler compiler
21-
* @param {string} client client reference
2216
* @param {function(Error?, any?): void} callback callback
23-
* @param {?BackendConfiguration} backendConfiguration additional options for the backend
2417
* @returns {void}
2518
*/
26-
module.exports = (compiler, client, callback, backendConfiguration) => {
19+
20+
/**
21+
* @param {Omit<LazyCompilationDefaultBackendOptions, "client"> & { client: NonNullable<LazyCompilationDefaultBackendOptions["client"]>}} options additional options for the backend
22+
* @returns {BackendHandler} backend
23+
*/
24+
module.exports = options => (compiler, callback) => {
2725
const logger = compiler.getInfrastructureLogger("LazyCompilationBackend");
2826
const activeModules = new Map();
2927
const prefix = "/lazy-compilation-using-";
3028

31-
const isHTTPS =
32-
!!backendConfiguration && !!backendConfiguration.httpsServerOptions;
29+
const isHttps =
30+
options.protocol === "https" ||
31+
(typeof options.server === "object" &&
32+
("key" in options.server || "pfx" in options.server));
33+
34+
const createServer =
35+
typeof options.server === "function"
36+
? options.server
37+
: (() => {
38+
const http = isHttps ? require("https") : require("http");
39+
return http.createServer.bind(http, options.server);
40+
})();
41+
const listen =
42+
typeof options.listen === "function"
43+
? options.listen
44+
: server => server.listen(options.listen);
3345

34-
const protocol = isHTTPS ? "https" : "http";
35-
const httpModule = isHTTPS ? require("https") : require("http");
46+
const protocol = options.protocol || (isHttps ? "https" : "http");
3647

3748
const requestListener = (req, res) => {
3849
const keys = req.url.slice(prefix.length).split("@");
@@ -67,12 +78,8 @@ module.exports = (compiler, client, callback, backendConfiguration) => {
6778
if (moduleActivated && compiler.watching) compiler.watching.invalidate();
6879
};
6980

70-
const server = httpModule.createServer(
71-
backendConfiguration &&
72-
(backendConfiguration.httpServerOptions ||
73-
backendConfiguration.httpsServerOptions),
74-
requestListener
75-
);
81+
const server = /** @type {import("net").Server} */ (createServer());
82+
server.on("request", requestListener);
7683

7784
let isClosing = false;
7885
/** @type {Set<import("net").Socket>} */
@@ -84,7 +91,8 @@ module.exports = (compiler, client, callback, backendConfiguration) => {
8491
});
8592
if (isClosing) socket.destroy();
8693
});
87-
server.listen(backendConfiguration && backendConfiguration.port, err => {
94+
server.on("clientError", e => logger.warn(e));
95+
server.on("listening", err => {
8896
if (err) return callback(err);
8997
const addr = server.address();
9098
if (typeof addr === "string") throw new Error("addr must not be a string");
@@ -115,11 +123,12 @@ module.exports = (compiler, client, callback, backendConfiguration) => {
115123
).replace(/%(2F|3A|24|26|2B|2C|3B|3D|3A)/g, decodeURIComponent)}`;
116124
const active = activeModules.get(key) > 0;
117125
return {
118-
client: `${client}?${encodeURIComponent(urlBase + prefix)}`,
126+
client: `${options.client}?${encodeURIComponent(urlBase + prefix)}`,
119127
data: key,
120128
active
121129
};
122130
}
123131
});
124132
});
133+
listen(server);
125134
};

schemas/WebpackOptions.check.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)