Skip to content

Commit 4019b51

Browse files
committed
refactor(@ngtools/webpack): cache parsed source files
1 parent 73a3e27 commit 4019b51

File tree

1 file changed

+71
-26
lines changed

1 file changed

+71
-26
lines changed

packages/ngtools/webpack/src/compiler_host.ts

+71-26
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,25 @@ const dev = Math.floor(Math.random() * 10000);
2828

2929
export class WebpackCompilerHost implements ts.CompilerHost {
3030
private _syncHost: virtualFs.SyncDelegateHost;
31+
private _memoryHost: virtualFs.SyncDelegateHost;
3132
private _changedFiles = new Set<string>();
3233
private _basePath: Path;
3334
private _resourceLoader?: WebpackResourceLoader;
35+
private _sourceFileCache = new Map<string, ts.SourceFile>();
3436

3537
constructor(
3638
private _options: ts.CompilerOptions,
3739
basePath: string,
3840
host: virtualFs.Host,
3941
) {
40-
this._syncHost = new virtualFs.SyncDelegateHost(new virtualFs.CordHost(host));
42+
this._syncHost = new virtualFs.SyncDelegateHost(host);
43+
this._memoryHost = new virtualFs.SyncDelegateHost(new virtualFs.SimpleMemoryHost());
4144
this._basePath = normalize(basePath);
4245
}
4346

4447
private get virtualFiles(): Path[] {
45-
return (this._syncHost.delegate as virtualFs.CordHost)
46-
.records()
47-
.filter(record => record.kind === 'create')
48-
.map((record: virtualFs.CordHostCreate) => record.path);
48+
return [...(this._memoryHost.delegate as unknown as { _cache: Map<Path, {}> })
49+
._cache.keys()];
4950
}
5051

5152
denormalizePath(path: string) {
@@ -79,35 +80,50 @@ export class WebpackCompilerHost implements ts.CompilerHost {
7980
invalidate(fileName: string): void {
8081
const fullPath = this.resolve(fileName);
8182

82-
if (this.fileExists(fileName)) {
83-
this._changedFiles.add(fullPath);
83+
if (this._memoryHost.exists(fullPath)) {
84+
this._memoryHost.delete(fullPath);
8485
}
86+
87+
this._sourceFileCache.delete(fullPath);
88+
89+
try {
90+
const exists = this._syncHost.isFile(fullPath);
91+
if (exists) {
92+
this._changedFiles.add(fullPath);
93+
}
94+
} catch { }
8595
}
8696

8797
fileExists(fileName: string, delegate = true): boolean {
8898
const p = this.resolve(fileName);
8999

100+
if (this._memoryHost.isFile(p)) {
101+
return true;
102+
}
103+
104+
if (!delegate) {
105+
return false;
106+
}
107+
108+
let exists = false;
90109
try {
91-
const exists = this._syncHost.isFile(p);
92-
if (delegate) {
93-
return exists;
94-
} else if (exists) {
95-
const backend = new virtualFs.SyncDelegateHost(
96-
(this._syncHost.delegate as virtualFs.CordHost).backend as virtualFs.Host,
97-
);
98-
99-
return !backend.isFile(p);
100-
}
110+
exists = this._syncHost.isFile(p);
101111
} catch { }
102112

103-
return false;
113+
return exists;
104114
}
105115

106116
readFile(fileName: string): string | undefined {
107117
const filePath = this.resolve(fileName);
108118

109119
try {
110-
return virtualFs.fileBufferToString(this._syncHost.read(filePath));
120+
if (this._memoryHost.isFile(filePath)) {
121+
return virtualFs.fileBufferToString(this._memoryHost.read(filePath));
122+
} else {
123+
const content = this._syncHost.read(filePath);
124+
125+
return virtualFs.fileBufferToString(content);
126+
}
111127
} catch {
112128
return undefined;
113129
}
@@ -116,7 +132,13 @@ export class WebpackCompilerHost implements ts.CompilerHost {
116132
readFileBuffer(fileName: string): Buffer {
117133
const filePath = this.resolve(fileName);
118134

119-
return Buffer.from(this._syncHost.read(filePath));
135+
if (this._memoryHost.isFile(filePath)) {
136+
return Buffer.from(this._memoryHost.read(filePath));
137+
} else {
138+
const content = this._syncHost.read(filePath);
139+
140+
return Buffer.from(content);
141+
}
120142
}
121143

122144
private _makeStats(stats: virtualFs.Stats<Partial<Stats>>): Stats {
@@ -154,7 +176,7 @@ export class WebpackCompilerHost implements ts.CompilerHost {
154176

155177
let stats: virtualFs.Stats<Partial<Stats>> | Stats | null = null;
156178
try {
157-
stats = this._syncHost.stat(p);
179+
stats = this._memoryHost.stat(p) || this._syncHost.stat(p);
158180
} catch { }
159181

160182
if (!stats) {
@@ -172,7 +194,7 @@ export class WebpackCompilerHost implements ts.CompilerHost {
172194
const p = this.resolve(directoryName);
173195

174196
try {
175-
return this._syncHost.isDirectory(p);
197+
return this._memoryHost.isDirectory(p) || this._syncHost.isDirectory(p);
176198
} catch {
177199
return false;
178200
}
@@ -194,14 +216,37 @@ export class WebpackCompilerHost implements ts.CompilerHost {
194216
delegated = [];
195217
}
196218

197-
return delegated;
219+
let memory: string[];
220+
try {
221+
memory = this._memoryHost.list(p).filter(x => {
222+
try {
223+
return this._memoryHost.isDirectory(join(p, x));
224+
} catch {
225+
return false;
226+
}
227+
});
228+
} catch {
229+
memory = [];
230+
}
231+
232+
return [...new Set([...delegated, ...memory])];
198233
}
199234

200235
getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: OnErrorFn) {
236+
const p = this.resolve(fileName);
237+
201238
try {
239+
const cached = this._sourceFileCache.get(p);
240+
if (cached) {
241+
return cached;
242+
}
243+
202244
const content = this.readFile(fileName);
203-
if (content != undefined) {
204-
return ts.createSourceFile(workaroundResolve(fileName), content, languageVersion, true);
245+
if (content !== undefined) {
246+
const sf = ts.createSourceFile(workaroundResolve(fileName), content, languageVersion, true);
247+
this._sourceFileCache.set(p, sf);
248+
249+
return sf;
205250
}
206251
} catch (e) {
207252
if (onError) {
@@ -229,7 +274,7 @@ export class WebpackCompilerHost implements ts.CompilerHost {
229274
const p = this.resolve(fileName);
230275

231276
try {
232-
this._syncHost.write(p, virtualFs.stringToFileBuffer(data));
277+
this._memoryHost.write(p, virtualFs.stringToFileBuffer(data));
233278
} catch (e) {
234279
if (onError) {
235280
onError(e.message);

0 commit comments

Comments
 (0)