Skip to content

Commit 241fc39

Browse files
committed
feat: lazy compilation middleware supports multiCompiler
1 parent 5e95aaa commit 241fc39

File tree

10 files changed

+220
-53
lines changed

10 files changed

+220
-53
lines changed

packages/rspack-cli/src/commands/serve.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,15 @@ export class ServeCommand implements RspackCommand {
105105

106106
const result = (compilerForDevServer.options.devServer ??= {});
107107

108-
if (compilerForDevServer.options.experiments.lazyCompilation) {
109-
const options =
110-
compilerForDevServer.options.experiments.lazyCompilation;
111-
108+
// if one of compilers enable lazy compilation
109+
if (
110+
compilers.some(
111+
compiler => compiler.options.experiments.lazyCompilation
112+
)
113+
) {
112114
const setupMiddlewares = result.setupMiddlewares;
113115
const lazyCompileMiddleware =
114-
rspack.experiments.lazyCompilationMiddleware(
115-
compilerForDevServer,
116-
options
117-
);
116+
rspack.experiments.lazyCompilationMiddleware(compiler);
118117
result.setupMiddlewares = (middlewares, server) => {
119118
let finalMiddlewares = middlewares;
120119
if (setupMiddlewares) {

packages/rspack-test-tools/etc/test-tools.api.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type EventEmitter from 'node:events';
1111
import { IBasicGlobalContext as IBasicGlobalContext_2 } from '../../type';
1212
import { IBasicModuleScope as IBasicModuleScope_2 } from '../../type';
1313
import { ITestCompilerManager as ITestCompilerManager_2 } from '../type';
14+
import type { MultiCompiler } from '@rspack/core';
1415
import type { MultiStats } from '@rspack/core';
1516
import type { MultiStats as MultiStats_2 } from 'webpack';
1617
import type { RspackOptions } from '@rspack/core';
@@ -1212,7 +1213,7 @@ export class JSDOMWebRunner<T extends ECompilerType = ECompilerType.Rspack> exte
12121213
// @public (undocumented)
12131214
export class LazyCompilationTestPlugin {
12141215
// (undocumented)
1215-
apply(compiler: Compiler): void;
1216+
apply(compiler: Compiler | MultiCompiler): void;
12161217
}
12171218

12181219
// @public (undocumented)

packages/rspack-test-tools/src/plugin/lazy-compilation-test-plugin.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
import { createServer } from "node:http";
22
import type { Socket } from "node:net";
33
import type { AddressInfo } from "node:net";
4-
import type { Compiler } from "@rspack/core";
4+
import type { Compiler, MultiCompiler } from "@rspack/core";
55
import { experiments } from "@rspack/core";
66

77
export class LazyCompilationTestPlugin {
8-
apply(compiler: Compiler) {
9-
const options = compiler.options.experiments.lazyCompilation!;
10-
if (!options) {
11-
return;
12-
}
13-
8+
apply(compiler: Compiler | MultiCompiler) {
149
let middleware: any;
1510
const server = createServer();
1611
const sockets = new Set<Socket>();
@@ -31,8 +26,7 @@ export class LazyCompilationTestPlugin {
3126
middleware = experiments.lazyCompilationMiddleware(compiler, {
3227
// @ts-expect-error cacheable is hidden config only for tests
3328
cacheable: false,
34-
serverUrl: urlBase,
35-
...options
29+
serverUrl: urlBase
3630
});
3731

3832
resolve(null);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 4;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default import('./d-dynamic');

packages/rspack-test-tools/tests/legacy-test/MultiCompiler.test.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require("../../dist/helper/legacy/warmup-webpack");
44
const path = require("path");
55
const webpack = require("@rspack/core");
6+
const { LazyCompilationTestPlugin } = require("@rspack/test-tools");
67

78
describe("MultiCompiler", function () {
89
jest.setTimeout(20000);
@@ -39,6 +40,82 @@ describe("MultiCompiler", function () {
3940
}, 20000);
4041
});
4142

43+
describe("with lazy compilation", function () {
44+
it("compiler has unique lazy compilation config", done => {
45+
const context = path.join(__dirname, "../fixtures");
46+
const configs = [
47+
{
48+
entry: "./esm/a.js",
49+
context
50+
},
51+
{
52+
entry: "./esm/b.js",
53+
experiments: {
54+
lazyCompilation: {
55+
entries: true
56+
}
57+
},
58+
context
59+
},
60+
{
61+
entry: "./esm/d.js",
62+
experiments: {
63+
lazyCompilation: {
64+
entries: false,
65+
imports: true
66+
}
67+
},
68+
context
69+
}
70+
];
71+
const compiler = webpack(configs);
72+
73+
new LazyCompilationTestPlugin().apply(compiler);
74+
75+
compiler.watch({}, (err, multiStats) => {
76+
if (err) {
77+
compiler.close(() => {
78+
done(err);
79+
});
80+
return;
81+
}
82+
83+
const [statsA, statsB, statsC] = multiStats.stats;
84+
85+
expect(
86+
statsA.toJson().modules.every(module => {
87+
return !module.identifier.includes("lazy-compilation-proxy");
88+
})
89+
).toBeTruthy();
90+
91+
// second compiler lazy compile entry
92+
expect(
93+
statsB.toJson().modules.find(module => {
94+
return (
95+
module.identifier.includes("lazy-compilation-proxy") &&
96+
module.identifier.includes("/esm/b.js")
97+
);
98+
})
99+
).toBeDefined();
100+
101+
// third compiler lazy compile dyn imports
102+
expect(
103+
statsC.toJson().modules.find(module => {
104+
return (
105+
module.identifier.includes("lazy-compilation-proxy") &&
106+
module.identifier.includes("/esm/d-dynamic.js")
107+
);
108+
})
109+
).toBeDefined();
110+
111+
compiler.close(err => {
112+
if (err) return done(err);
113+
done();
114+
});
115+
});
116+
});
117+
});
118+
42119
describe.skip("Pressure test", function () {
43120
it("should work well in multiCompilers", done => {
44121
const configs = Array(100).fill({

packages/rspack/etc/core.api.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3141,7 +3141,7 @@ type KnownStatsProfile = {
31413141
export type Layer = string | null;
31423142

31433143
// @public (undocumented)
3144-
const lazyCompilationMiddleware: (compiler: Compiler, userOptions?: LazyCompilationOptions | boolean) => Middleware;
3144+
const lazyCompilationMiddleware: (compiler: Compiler | MultiCompiler, userOptions?: LazyCompilationOptions | boolean) => Middleware;
31453145

31463146
// @public
31473147
export type LazyCompilationOptions = {
@@ -3750,6 +3750,8 @@ export class MultiCompiler {
37503750
hooks: {
37513751
done: liteTapable.SyncHook<MultiStats>;
37523752
invalid: liteTapable.MultiHook<liteTapable.SyncHook<[string | null, number]>>;
3753+
beforeCompile: liteTapable.MultiHook<liteTapable.AsyncSeriesHook<[CompilationParams]>>;
3754+
shutdown: liteTapable.MultiHook<liteTapable.AsyncSeriesHook<[]>>;
37533755
run: liteTapable.MultiHook<liteTapable.AsyncSeriesHook<[Compiler]>>;
37543756
watchClose: liteTapable.SyncHook<[]>;
37553757
watchRun: liteTapable.MultiHook<liteTapable.AsyncSeriesHook<[Compiler]>>;
@@ -3788,6 +3790,8 @@ export class MultiCompiler {
37883790
// (undocumented)
37893791
get watchFileSystem(): WatchFileSystem;
37903792
set watchFileSystem(value: WatchFileSystem);
3793+
// (undocumented)
3794+
watching?: MultiWatching;
37913795
}
37923796

37933797
// @public (undocumented)
@@ -3825,6 +3829,8 @@ class MultiWatching {
38253829
// (undocumented)
38263830
invalidate(callback: Callback<Error, void>): void;
38273831
// (undocumented)
3832+
invalidateWithChangesAndRemovals(changedFiles?: Set<string>, removedFiles?: Set<string>, callback?: Callback<Error, void>): void;
3833+
// (undocumented)
38283834
resume(): void;
38293835
// (undocumented)
38303836
suspend(): void;

packages/rspack/src/MultiCompiler.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010

1111
import * as liteTapable from "@rspack/lite-tapable";
12-
import type { Compiler, RspackOptions, Stats } from ".";
12+
import type { CompilationParams, Compiler, RspackOptions, Stats } from ".";
1313
import MultiStats from "./MultiStats";
1414
import MultiWatching from "./MultiWatching";
1515
import type { WatchOptions } from "./config";
@@ -56,6 +56,10 @@ export class MultiCompiler {
5656
invalid: liteTapable.MultiHook<
5757
liteTapable.SyncHook<[string | null, number]>
5858
>;
59+
beforeCompile: liteTapable.MultiHook<
60+
liteTapable.AsyncSeriesHook<[CompilationParams]>
61+
>;
62+
shutdown: liteTapable.MultiHook<liteTapable.AsyncSeriesHook<[]>>;
5963
run: liteTapable.MultiHook<liteTapable.AsyncSeriesHook<[Compiler]>>;
6064
watchClose: liteTapable.SyncHook<[]>;
6165
watchRun: liteTapable.MultiHook<liteTapable.AsyncSeriesHook<[Compiler]>>;
@@ -65,6 +69,7 @@ export class MultiCompiler {
6569
};
6670
_options: MultiCompilerOptions;
6771
running: boolean;
72+
watching?: MultiWatching;
6873

6974
constructor(
7075
compilers: Compiler[] | Record<string, Compiler>,
@@ -92,6 +97,12 @@ export class MultiCompiler {
9297
watchRun: new liteTapable.MultiHook(
9398
normalizedCompilers.map(c => c.hooks.watchRun)
9499
),
100+
beforeCompile: new liteTapable.MultiHook(
101+
normalizedCompilers.map(c => c.hooks.beforeCompile)
102+
),
103+
shutdown: new liteTapable.MultiHook(
104+
normalizedCompilers.map(c => c.hooks.shutdown)
105+
),
95106
infrastructureLog: new liteTapable.MultiHook(
96107
normalizedCompilers.map(c => c.hooks.infrastructureLog)
97108
)
@@ -509,10 +520,14 @@ export class MultiCompiler {
509520
},
510521
handler
511522
);
512-
return new MultiWatching(watchings, this);
523+
const watching = new MultiWatching(watchings, this);
524+
this.watching = watching;
525+
return watching;
513526
}
514527

515-
return new MultiWatching([], this);
528+
const watching = new MultiWatching([], this);
529+
this.watching = watching;
530+
return watching;
516531
}
517532

518533
/**

packages/rspack/src/MultiWatching.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,31 @@ class MultiWatching {
4242
}
4343
}
4444

45+
invalidateWithChangesAndRemovals(
46+
changedFiles?: Set<string>,
47+
removedFiles?: Set<string>,
48+
callback?: Callback<Error, void>
49+
) {
50+
if (callback) {
51+
asyncLib.each(
52+
this.watchings,
53+
(watching, callback) =>
54+
watching.invalidateWithChangesAndRemovals(
55+
changedFiles,
56+
removedFiles,
57+
callback
58+
),
59+
// cannot be resolved without assertion
60+
// Type 'Error | null | undefined' is not assignable to type 'Error | null'
61+
callback as (err: Error | null | undefined) => void
62+
);
63+
} else {
64+
for (const watching of this.watchings) {
65+
watching.invalidateWithChangesAndRemovals(changedFiles, removedFiles);
66+
}
67+
}
68+
}
69+
4570
close(callback: Callback<Error, void>) {
4671
asyncLib.each(
4772
this.watchings,

0 commit comments

Comments
 (0)