@simplysm/sd-cli 12.5.18 → 12.5.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-tools/SdNgBundler.d.ts +1 -0
- package/dist/build-tools/SdNgBundler.js +70 -57
- package/dist/build-tools/SdNgBundler.js.map +1 -1
- package/dist/build-tools/SdServerBundler.d.ts +1 -0
- package/dist/build-tools/SdServerBundler.js +8 -7
- package/dist/build-tools/SdServerBundler.js.map +1 -1
- package/dist/build-tools/SdTsCompiler.d.ts +1 -0
- package/dist/build-tools/SdTsCompiler.js +355 -328
- package/dist/build-tools/SdTsCompiler.js.map +1 -1
- package/dist/build-tools/SdTsLibBundler.d.ts +1 -1
- package/dist/build-tools/SdTsLibBundler.js +2 -1
- package/dist/build-tools/SdTsLibBundler.js.map +1 -1
- package/dist/builders/SdCliClientBuilder.js +19 -42
- package/dist/builders/SdCliClientBuilder.js.map +1 -1
- package/dist/builders/SdCliServerBuilder.js +2 -1
- package/dist/builders/SdCliServerBuilder.js.map +1 -1
- package/dist/builders/SdCliTsLibBuilder.js +4 -2
- package/dist/builders/SdCliTsLibBuilder.js.map +1 -1
- package/dist/bundle-plugins/sdNgPlugin.d.ts +1 -0
- package/dist/bundle-plugins/sdNgPlugin.js +38 -23
- package/dist/bundle-plugins/sdNgPlugin.js.map +1 -1
- package/dist/bundle-plugins/sdServerPlugin.d.ts +1 -0
- package/dist/bundle-plugins/sdServerPlugin.js +1 -0
- package/dist/bundle-plugins/sdServerPlugin.js.map +1 -1
- package/dist/entry/SdCliProject.js +7 -4
- package/dist/entry/SdCliProject.js.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/dist/utils/SdCliPerformanceTime.d.ts +9 -0
- package/dist/utils/SdCliPerformanceTime.js +40 -0
- package/dist/utils/SdCliPerformanceTime.js.map +1 -0
- package/package.json +10 -14
- package/src/build-tools/SdNgBundler.ts +82 -68
- package/src/build-tools/SdServerBundler.ts +22 -20
- package/src/build-tools/SdTsCompiler.ts +341 -358
- package/src/build-tools/SdTsLibBundler.ts +2 -1
- package/src/builders/SdCliClientBuilder.ts +27 -54
- package/src/builders/SdCliServerBuilder.ts +5 -4
- package/src/builders/SdCliTsLibBuilder.ts +7 -4
- package/src/bundle-plugins/sdNgPlugin.ts +44 -23
- package/src/bundle-plugins/sdServerPlugin.ts +2 -0
- package/src/entry/SdCliProject.ts +6 -4
- package/src/index.ts +1 -4
- package/src/utils/SdCliPerformanceTime.ts +42 -0
- package/tsconfig.json +1 -1
- package/dist/build-tools/SdReactBundler.d.ts +0 -24
- package/dist/build-tools/SdReactBundler.js +0 -294
- package/dist/build-tools/SdReactBundler.js.map +0 -1
- package/dist/build-tools/SdReactBundlerContext.d.ts +0 -14
- package/dist/build-tools/SdReactBundlerContext.js +0 -59
- package/dist/build-tools/SdReactBundlerContext.js.map +0 -1
- package/dist/bundle-plugins/KeysTransformer.d.ts +0 -2
- package/dist/bundle-plugins/KeysTransformer.js +0 -61
- package/dist/bundle-plugins/KeysTransformer.js.map +0 -1
- package/dist/bundle-plugins/sdReactPlugin.d.ts +0 -15
- package/dist/bundle-plugins/sdReactPlugin.js +0 -116
- package/dist/bundle-plugins/sdReactPlugin.js.map +0 -1
- package/src/build-tools/SdReactBundler.ts +0 -370
- package/src/build-tools/SdReactBundlerContext.ts +0 -71
- package/src/bundle-plugins/KeysTransformer.ts +0 -70
- package/src/bundle-plugins/sdReactPlugin.ts +0 -160
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
1
|
+
import ts, { DiagnosticCategory } from "typescript";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { FsUtil, Logger, PathUtil } from "@simplysm/sd-core-node";
|
|
4
4
|
import { StringUtil } from "@simplysm/sd-core-common";
|
|
5
5
|
import { NgtscProgram, OptimizeFor } from "@angular/compiler-cli";
|
|
6
|
-
import { createHash } from "crypto";
|
|
7
6
|
import { ComponentStylesheetBundler } from "@angular/build/src/tools/esbuild/angular/component-stylesheets";
|
|
8
7
|
import { transformSupportedBrowsersToTargets } from "@angular/build/src/tools/esbuild/utils";
|
|
9
8
|
import browserslist from "browserslist";
|
|
10
|
-
import transformKeys from "@simplysm/ts-transformer-keys/transformer";
|
|
11
9
|
import { replaceBootstrap } from "@angular/build/src/tools/angular/transformers/jit-bootstrap-transformer";
|
|
10
|
+
import { SdCliPerformanceTimer } from "../utils/SdCliPerformanceTime";
|
|
12
11
|
export class SdTsCompiler {
|
|
13
12
|
#logger = Logger.get(["simplysm", "sd-cli", "SdTsCompiler"]);
|
|
14
13
|
#parsedTsconfig;
|
|
15
14
|
#isForAngular;
|
|
16
|
-
|
|
15
|
+
#revDependencyCacheMap = new Map();
|
|
17
16
|
#resourceDependencyCacheMap = new Map();
|
|
18
17
|
#sourceFileCacheMap = new Map();
|
|
19
18
|
#emittedFilesCacheMap = new Map();
|
|
@@ -21,18 +20,19 @@ export class SdTsCompiler {
|
|
|
21
20
|
#compilerHost;
|
|
22
21
|
#ngProgram;
|
|
23
22
|
#program;
|
|
24
|
-
#builder;
|
|
25
23
|
#modifiedFileSet = new Set();
|
|
26
24
|
#watchFileSet = new Set();
|
|
27
25
|
#stylesheetBundlingResultMap = new Map();
|
|
28
26
|
#pkgPath;
|
|
29
27
|
#distPath;
|
|
30
28
|
#globalStyleFilePath;
|
|
29
|
+
#watchScopePaths;
|
|
31
30
|
#isForBundle;
|
|
32
31
|
constructor(opt) {
|
|
33
32
|
this.#pkgPath = opt.pkgPath;
|
|
34
33
|
this.#globalStyleFilePath = opt.globalStyleFilePath != null ? path.normalize(opt.globalStyleFilePath) : undefined;
|
|
35
34
|
this.#isForBundle = opt.isForBundle;
|
|
35
|
+
this.#watchScopePaths = opt.watchScopePaths;
|
|
36
36
|
this.#debug("초기화...");
|
|
37
37
|
//-- isForAngular / parsedTsConfig
|
|
38
38
|
const tsconfigPath = path.resolve(opt.pkgPath, "tsconfig.json");
|
|
@@ -126,56 +126,58 @@ export class SdTsCompiler {
|
|
|
126
126
|
return stylesheetResult.contents;
|
|
127
127
|
}
|
|
128
128
|
invalidate(modifiedFileSet) {
|
|
129
|
-
|
|
130
|
-
this.#modifiedFileSet.add(modifiedFile);
|
|
131
|
-
this.#modifiedFileSet.adds(...(this.#resourceDependencyCacheMap.get(modifiedFile) ?? []));
|
|
132
|
-
}
|
|
129
|
+
this.#modifiedFileSet.adds(...Array.from(modifiedFileSet).map((item) => path.normalize(item)));
|
|
133
130
|
}
|
|
134
131
|
async buildAsync() {
|
|
135
|
-
|
|
132
|
+
let perf = new SdCliPerformanceTimer("esbuild");
|
|
133
|
+
const affectedFileSet = new Set();
|
|
136
134
|
const emitFileSet = new Set();
|
|
137
135
|
this.#debug(`get affected (old deps & old res deps)...`);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
136
|
+
perf.run("get affected", () => {
|
|
137
|
+
for (const modifiedFile of this.#modifiedFileSet) {
|
|
138
|
+
affectedFileSet.add(modifiedFile);
|
|
139
|
+
affectedFileSet.adds(...(this.#revDependencyCacheMap.get(modifiedFile) ?? []));
|
|
140
|
+
affectedFileSet.adds(...(this.#resourceDependencyCacheMap.get(modifiedFile) ?? []));
|
|
141
|
+
this.#emittedFilesCacheMap.delete(path.normalize(modifiedFile));
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
this.#debug(`invalidate & clear cache...`);
|
|
145
|
+
perf.run("invalidate & clear cache", () => {
|
|
146
|
+
this.#stylesheetBundler?.invalidate(this.#modifiedFileSet);
|
|
147
|
+
for (const affectedFile of affectedFileSet) {
|
|
148
|
+
this.#sourceFileCacheMap.delete(path.normalize(affectedFile));
|
|
149
|
+
this.#stylesheetBundlingResultMap.delete(path.normalize(affectedFile));
|
|
150
|
+
this.#watchFileSet.delete(path.normalize(affectedFile));
|
|
151
|
+
}
|
|
152
|
+
this.#revDependencyCacheMap.clear();
|
|
153
|
+
this.#resourceDependencyCacheMap.clear();
|
|
154
|
+
});
|
|
157
155
|
this.#debug(`create program...`);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
156
|
+
perf.run("create program", () => {
|
|
157
|
+
if (this.#isForAngular) {
|
|
158
|
+
this.#ngProgram = new NgtscProgram(this.#parsedTsconfig.fileNames, this.#parsedTsconfig.options, this.#compilerHost, this.#ngProgram);
|
|
159
|
+
this.#program = this.#ngProgram.getTsProgram();
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
this.#program = ts.createProgram(this.#parsedTsconfig.fileNames, this.#parsedTsconfig.options, this.#compilerHost, this.#program);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
/*const baseGetSourceFiles = this.#program.getSourceFiles;
|
|
167
166
|
this.#program.getSourceFiles = function (...parameters) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
167
|
+
const files: readonly (ts.SourceFile & { version?: string })[] = baseGetSourceFiles(...parameters);
|
|
168
|
+
|
|
169
|
+
for (const file of files) {
|
|
170
|
+
if (file.version === undefined) {
|
|
171
|
+
file.version = createHash("sha256").update(file.text).digest("hex");
|
|
173
172
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return files;
|
|
176
|
+
};*/
|
|
177
177
|
if (this.#ngProgram) {
|
|
178
|
-
await
|
|
178
|
+
await perf.run("ng analyze", async () => {
|
|
179
|
+
await this.#ngProgram.compiler.analyzeAsync();
|
|
180
|
+
});
|
|
179
181
|
}
|
|
180
182
|
const getOrgSourceFile = (sf) => {
|
|
181
183
|
if (sf.fileName.endsWith(".ngtypecheck.ts")) {
|
|
@@ -185,310 +187,219 @@ export class SdTsCompiler {
|
|
|
185
187
|
return sf;
|
|
186
188
|
};
|
|
187
189
|
this.#debug(`get affected (new deps)...`);
|
|
188
|
-
// const sourceFileSet = new Set(
|
|
189
|
-
// this.#program
|
|
190
|
-
// .getSourceFiles()
|
|
191
|
-
// .map((sf) => getOrgSourceFile(sf))
|
|
192
|
-
// .filterExists(),
|
|
193
|
-
// );
|
|
194
|
-
// const depMap = new Map<
|
|
195
|
-
// string,
|
|
196
|
-
// {
|
|
197
|
-
// fileName: string;
|
|
198
|
-
// importName: string;
|
|
199
|
-
// exportName?: string;
|
|
200
|
-
// }[]
|
|
201
|
-
// >();
|
|
202
|
-
// for (const sf of sourceFileSet) {
|
|
203
|
-
// const refs = this.#findDeps(sf);
|
|
204
|
-
// depMap.set(path.normalize(sf.fileName), refs);
|
|
205
|
-
// }
|
|
206
|
-
//
|
|
207
|
-
// const allDepMap = new Map<string, Set<string>>();
|
|
208
|
-
// const getAllDeps = (fileName: string, prevSet?: Set<string>) => {
|
|
209
|
-
// if (allDepMap.has(fileName)) {
|
|
210
|
-
// return allDepMap.get(fileName)!;
|
|
211
|
-
// }
|
|
212
|
-
//
|
|
213
|
-
// const result = new Set<string>();
|
|
214
|
-
//
|
|
215
|
-
// const deps = depMap.get(fileName) ?? [];
|
|
216
|
-
// result.adds(...deps.map((item) => item.fileName));
|
|
217
|
-
//
|
|
218
|
-
// for (const dep of deps) {
|
|
219
|
-
// const targetDeps = depMap.get(dep.fileName) ?? [];
|
|
220
|
-
//
|
|
221
|
-
// if (dep.importName === "*") {
|
|
222
|
-
// for (const targetRefItem of targetDeps.filter((item) => item.exportName != null)) {
|
|
223
|
-
// if (prevSet?.has(targetRefItem.fileName)) continue;
|
|
224
|
-
//
|
|
225
|
-
// result.add(targetRefItem.fileName);
|
|
226
|
-
// result.adds(...getAllDeps(targetRefItem.fileName, new Set<string>(prevSet).adds(...result)));
|
|
227
|
-
// }
|
|
228
|
-
// } else {
|
|
229
|
-
// for (const targetRefItem of targetDeps.filter((item) => item.exportName === dep.importName)) {
|
|
230
|
-
// if (prevSet?.has(targetRefItem.fileName)) continue;
|
|
231
|
-
//
|
|
232
|
-
// result.add(targetRefItem.fileName);
|
|
233
|
-
// result.adds(...getAllDeps(targetRefItem.fileName, new Set<string>(prevSet).adds(...result)));
|
|
234
|
-
// }
|
|
235
|
-
// }
|
|
236
|
-
// }
|
|
237
|
-
//
|
|
238
|
-
// return result;
|
|
239
|
-
// };
|
|
240
|
-
// for (const sf of sourceFileSet) {
|
|
241
|
-
// const deps = getAllDeps(path.normalize(sf.fileName));
|
|
242
|
-
// allDepMap.set(path.normalize(sf.fileName), deps);
|
|
243
|
-
//
|
|
244
|
-
// for (const dep of getAllDeps(path.normalize(sf.fileName))) {
|
|
245
|
-
// const depCache = this.#revDependencyCacheMap.getOrCreate(path.normalize(dep), new Set<string>());
|
|
246
|
-
// depCache.add(path.normalize(sf.fileName));
|
|
247
|
-
// if (this.#modifiedFileSet.has(path.normalize(dep))) {
|
|
248
|
-
// affectedFileSet.add(path.normalize(sf.fileName));
|
|
249
|
-
// }
|
|
250
|
-
// }
|
|
251
|
-
//
|
|
252
|
-
// if (this.#ngProgram) {
|
|
253
|
-
// if (this.#ngProgram.compiler.ignoreForEmit.has(sf)) {
|
|
254
|
-
// continue;
|
|
255
|
-
// }
|
|
256
|
-
//
|
|
257
|
-
// for (const dep of this.#ngProgram.compiler.getResourceDependencies(sf)) {
|
|
258
|
-
// const ref = this.#resourceDependencyCacheMap.getOrCreate(path.normalize(dep), new Set<string>());
|
|
259
|
-
// ref.add(path.normalize(sf.fileName));
|
|
260
|
-
// if (this.#modifiedFileSet.has(path.normalize(dep))) {
|
|
261
|
-
// affectedFileSet.add(path.normalize(sf.fileName));
|
|
262
|
-
// }
|
|
263
|
-
// }
|
|
264
|
-
// }
|
|
265
|
-
// }
|
|
266
|
-
// if (affectedFileSet.size === 0) {
|
|
267
|
-
// this.#debug(`get affected (init)...`);
|
|
268
|
-
//
|
|
269
|
-
// for (const sf of this.#program.getSourceFiles()) {
|
|
270
|
-
// const orgSf = getOrgSourceFile(sf);
|
|
271
|
-
// if (!orgSf) continue;
|
|
272
|
-
//
|
|
273
|
-
// affectedFileSet.add(path.normalize(orgSf.fileName));
|
|
274
|
-
// }
|
|
275
|
-
// }
|
|
276
|
-
this.#debug(`get diagnostics...`);
|
|
277
190
|
const diagnostics = [];
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
diagnostics.push(...this.#ngProgram.compiler.getOptionDiagnostics());
|
|
286
|
-
}
|
|
287
|
-
this.#debug(`get diagnostics of files...`);
|
|
288
|
-
while (true) {
|
|
289
|
-
const affectedFileResult = this.#builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sf) => {
|
|
290
|
-
if (this.#ngProgram &&
|
|
291
|
-
this.#ngProgram.compiler.ignoreForDiagnostics.has(sf) &&
|
|
292
|
-
sf.fileName.endsWith(".ngtypecheck.ts")) {
|
|
293
|
-
const orgSourceFile = getOrgSourceFile(sf);
|
|
294
|
-
if (orgSourceFile) {
|
|
295
|
-
affectedSourceFileSet.add(orgSourceFile);
|
|
296
|
-
}
|
|
297
|
-
return true;
|
|
298
|
-
}
|
|
299
|
-
return false;
|
|
300
|
-
});
|
|
301
|
-
if (!affectedFileResult)
|
|
302
|
-
break;
|
|
303
|
-
const affectedSourceFile = affectedFileResult.affected;
|
|
304
|
-
affectedSourceFileSet.add(affectedSourceFile);
|
|
305
|
-
}
|
|
306
|
-
for (const affectedSourceFile of affectedSourceFileSet) {
|
|
307
|
-
this.#debug(`get diagnostics of file [${affectedSourceFile.fileName}]`);
|
|
308
|
-
diagnostics.push(...this.#program.getSyntacticDiagnostics(affectedSourceFile), ...this.#program.getSemanticDiagnostics(affectedSourceFile));
|
|
309
|
-
if (this.#ngProgram) {
|
|
310
|
-
if (affectedSourceFile.isDeclarationFile) {
|
|
191
|
+
perf.run("get affected (deps)", () => {
|
|
192
|
+
const sourceFileSet = new Set(this.#program.getSourceFiles()
|
|
193
|
+
.map((sf) => getOrgSourceFile(sf))
|
|
194
|
+
.filterExists());
|
|
195
|
+
const depMap = new Map();
|
|
196
|
+
for (const sf of sourceFileSet) {
|
|
197
|
+
if (!PathUtil.isChildPath(sf.fileName, this.#pkgPath)) {
|
|
311
198
|
continue;
|
|
312
199
|
}
|
|
313
|
-
|
|
200
|
+
const refs = this.#findDeps(sf);
|
|
201
|
+
diagnostics.push(...refs.filter((item) => "category" in item));
|
|
202
|
+
depMap.set(path.normalize(sf.fileName), refs
|
|
203
|
+
.filter((item) => "fileName" in item)
|
|
204
|
+
.filter((item) => this.#watchScopePaths.some((scopePath) => PathUtil.isChildPath(item.fileName, scopePath))));
|
|
314
205
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
...this.#ngProgram.compiler.getDiagnosticsForFile(affectedSourceFile, OptimizeFor.WholeProgram),
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
}*/
|
|
347
|
-
this.#debug(`prepare emit...`);
|
|
348
|
-
let transformers = {};
|
|
349
|
-
if (this.#ngProgram) {
|
|
350
|
-
transformers = {
|
|
351
|
-
...transformers,
|
|
352
|
-
...this.#ngProgram.compiler.prepareEmit().transformers,
|
|
206
|
+
const allDepMap = new Map();
|
|
207
|
+
const getAllDeps = (fileName, prevSet) => {
|
|
208
|
+
if (allDepMap.has(fileName)) {
|
|
209
|
+
return allDepMap.get(fileName);
|
|
210
|
+
}
|
|
211
|
+
const result = new Set();
|
|
212
|
+
const deps = depMap.get(fileName) ?? [];
|
|
213
|
+
result.adds(...deps.map((item) => item.fileName));
|
|
214
|
+
for (const dep of deps) {
|
|
215
|
+
const targetDeps = depMap.get(dep.fileName) ?? [];
|
|
216
|
+
if (dep.importName === "*") {
|
|
217
|
+
for (const targetRefItem of targetDeps.filter((item) => item.exportName != null)) {
|
|
218
|
+
if (prevSet?.has(targetRefItem.fileName))
|
|
219
|
+
continue;
|
|
220
|
+
result.add(targetRefItem.fileName);
|
|
221
|
+
result.adds(...getAllDeps(targetRefItem.fileName, new Set(prevSet).adds(...result)));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
for (const targetRefItem of targetDeps.filter((item) => item.exportName === dep.importName)) {
|
|
226
|
+
if (prevSet?.has(targetRefItem.fileName))
|
|
227
|
+
continue;
|
|
228
|
+
result.add(targetRefItem.fileName);
|
|
229
|
+
result.adds(...getAllDeps(targetRefItem.fileName, new Set(prevSet).adds(...result)));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
353
234
|
};
|
|
354
|
-
(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
235
|
+
for (const sf of sourceFileSet) {
|
|
236
|
+
const deps = getAllDeps(path.normalize(sf.fileName));
|
|
237
|
+
allDepMap.set(path.normalize(sf.fileName), deps);
|
|
238
|
+
for (const dep of getAllDeps(path.normalize(sf.fileName))) {
|
|
239
|
+
const depCache = this.#revDependencyCacheMap.getOrCreate(path.normalize(dep), new Set());
|
|
240
|
+
depCache.add(path.normalize(sf.fileName));
|
|
241
|
+
if (this.#modifiedFileSet.has(path.normalize(dep))) {
|
|
242
|
+
affectedFileSet.add(path.normalize(sf.fileName));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (this.#ngProgram) {
|
|
246
|
+
if (this.#ngProgram.compiler.ignoreForEmit.has(sf)) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
for (const dep of this.#ngProgram.compiler.getResourceDependencies(sf)) {
|
|
250
|
+
const ref = this.#resourceDependencyCacheMap.getOrCreate(path.normalize(dep), new Set());
|
|
251
|
+
ref.add(path.normalize(sf.fileName));
|
|
252
|
+
if (this.#modifiedFileSet.has(path.normalize(dep))) {
|
|
253
|
+
affectedFileSet.add(path.normalize(sf.fileName));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
367
256
|
}
|
|
368
|
-
this.#ngProgram.compiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
369
257
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const sourceMapContents = JSON.parse(realText);
|
|
378
|
-
// remove "../../"
|
|
379
|
-
sourceMapContents.sources[0] = sourceMapContents.sources[0].slice(6);
|
|
380
|
-
realText = JSON.stringify(sourceMapContents);
|
|
258
|
+
});
|
|
259
|
+
if (affectedFileSet.size === 0) {
|
|
260
|
+
this.#debug(`get affected (init)...`);
|
|
261
|
+
perf.run("get affected (init)", () => {
|
|
262
|
+
for (const sf of this.#program.getSourceFiles()) {
|
|
263
|
+
if (!this.#watchScopePaths.some((scopePath) => PathUtil.isChildPath(sf.fileName, scopePath))) {
|
|
264
|
+
continue;
|
|
381
265
|
}
|
|
266
|
+
const orgSf = getOrgSourceFile(sf);
|
|
267
|
+
if (!orgSf)
|
|
268
|
+
continue;
|
|
269
|
+
affectedFileSet.add(path.normalize(orgSf.fileName));
|
|
382
270
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
this.#debug(`get diagnostics...`);
|
|
274
|
+
perf.run("get program diagnostics", () => {
|
|
275
|
+
diagnostics.push(...this.#program.getConfigFileParsingDiagnostics(), ...this.#program.getOptionsDiagnostics(), ...this.#program.getGlobalDiagnostics());
|
|
276
|
+
if (this.#ngProgram) {
|
|
277
|
+
diagnostics.push(...this.#ngProgram.compiler.getOptionDiagnostics());
|
|
387
278
|
}
|
|
388
|
-
|
|
389
|
-
|
|
279
|
+
});
|
|
280
|
+
this.#debug(`get diagnostics of files...`);
|
|
281
|
+
perf.run("get file diagnostics", () => {
|
|
282
|
+
for (const affectedFile of affectedFileSet) {
|
|
283
|
+
if (!PathUtil.isChildPath(affectedFile, this.#pkgPath)) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const affectedSourceFile = this.#program.getSourceFile(affectedFile);
|
|
287
|
+
if (!affectedSourceFile ||
|
|
288
|
+
(this.#ngProgram && this.#ngProgram.compiler.ignoreForDiagnostics.has(affectedSourceFile))) {
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
// this.#debug(`get diagnostics of file ${affectedFile}...`);
|
|
292
|
+
diagnostics.push(...this.#program.getSyntacticDiagnostics(affectedSourceFile), ...this.#program.getSemanticDiagnostics(affectedSourceFile));
|
|
293
|
+
if (this.#ngProgram) {
|
|
294
|
+
perf.run("get file diagnostics: ng", () => {
|
|
295
|
+
if (affectedSourceFile.isDeclarationFile) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
diagnostics.push(...this.#ngProgram.compiler.getDiagnosticsForFile(affectedSourceFile, OptimizeFor.WholeProgram));
|
|
299
|
+
});
|
|
300
|
+
}
|
|
390
301
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
if (!sf) {
|
|
402
|
-
continue;
|
|
403
|
-
}*/
|
|
404
|
-
/*for (const sf of sourceFileSet) {
|
|
405
|
-
if (this.#emittedFilesCacheMap.has(path.normalize(sf.fileName))) {
|
|
406
|
-
continue;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
if (sf.isDeclarationFile) {
|
|
410
|
-
continue;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
if (this.#ngProgram?.compiler.ignoreForEmit.has(sf)) {
|
|
414
|
-
continue;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// esbuild를 통해 bundle로 묶어야 하는놈들은 모든 output이 있어야 함.
|
|
418
|
-
if (!this.#isForBundle) {
|
|
419
|
-
if (!PathUtil.isChildPath(sf.fileName, this.#pkgPath)) {
|
|
420
|
-
continue;
|
|
302
|
+
});
|
|
303
|
+
perf.run("emit", () => {
|
|
304
|
+
this.#debug(`prepare emit...`);
|
|
305
|
+
let transformers = {};
|
|
306
|
+
if (this.#ngProgram) {
|
|
307
|
+
transformers = {
|
|
308
|
+
...transformers,
|
|
309
|
+
...this.#ngProgram.compiler.prepareEmit().transformers,
|
|
310
|
+
};
|
|
311
|
+
(transformers.before ??= []).push(replaceBootstrap(() => this.#program.getTypeChecker()));
|
|
421
312
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
(
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
const sourceFile = ts.getOriginalNode(sourceFiles[0], ts.isSourceFile);
|
|
434
|
-
if (this.#ngProgram) {
|
|
435
|
-
if (this.#ngProgram.compiler.ignoreForEmit.has(sourceFile)) {
|
|
436
|
-
return;
|
|
313
|
+
// (transformers.before ??= []).push(transformKeys(this.#program));
|
|
314
|
+
this.#debug(`emit for files...`);
|
|
315
|
+
// affected에 새로 추가된 파일은 포함되지 않는 현상이 있어 getSourceFiles로 바꿈
|
|
316
|
+
// 비교해보니, 딱히 getSourceFiles라서 더 느려지는것 같지는 않음
|
|
317
|
+
// 그래도 affected로 다시 테스트
|
|
318
|
+
for (const affectedFile of affectedFileSet) {
|
|
319
|
+
if (this.#emittedFilesCacheMap.has(affectedFile)) {
|
|
320
|
+
continue;
|
|
437
321
|
}
|
|
438
|
-
this.#
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
const emitFileInfoCaches = this.#emittedFilesCacheMap.getOrCreate(path.normalize(sourceFile.fileName), []);
|
|
442
|
-
if (PathUtil.isChildPath(sourceFile.fileName, this.#pkgPath)) {
|
|
443
|
-
let realFilePath = fileName;
|
|
444
|
-
let realText = text;
|
|
445
|
-
if (PathUtil.isChildPath(realFilePath, path.resolve(this.#distPath, path.basename(this.#pkgPath), "src"))) {
|
|
446
|
-
realFilePath = path.resolve(
|
|
447
|
-
this.#distPath,
|
|
448
|
-
path.relative(path.resolve(this.#distPath, path.basename(this.#pkgPath), "src"), realFilePath),
|
|
449
|
-
);
|
|
450
|
-
|
|
451
|
-
if (fileName.endsWith(".js.map")) {
|
|
452
|
-
const sourceMapContents = JSON.parse(realText);
|
|
453
|
-
// remove "../../"
|
|
454
|
-
sourceMapContents.sources[0] = sourceMapContents.sources[0].slice(6);
|
|
455
|
-
realText = JSON.stringify(sourceMapContents);
|
|
456
|
-
}
|
|
322
|
+
const sf = this.#program.getSourceFile(affectedFile);
|
|
323
|
+
if (!sf) {
|
|
324
|
+
continue;
|
|
457
325
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
326
|
+
// for (const sf of sourceFileSet) {
|
|
327
|
+
/*if (this.#emittedFilesCacheMap.has(path.normalize(sf.fileName))) {
|
|
328
|
+
continue;
|
|
329
|
+
}*/
|
|
330
|
+
if (sf.isDeclarationFile) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (this.#ngProgram?.compiler.ignoreForEmit.has(sf)) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
if (this.#ngProgram?.compiler.incrementalCompilation.safeToSkipEmit(sf) &&
|
|
337
|
+
!affectedFileSet.has(path.normalize(sf.fileName))) {
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
// esbuild를 통해 bundle로 묶어야 하는놈들은 모든 output이 있어야 함.
|
|
341
|
+
if (!this.#isForBundle) {
|
|
342
|
+
if (!PathUtil.isChildPath(sf.fileName, this.#pkgPath)) {
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
// this.#debug(`emit for`, sf.fileName);
|
|
347
|
+
this.#program.emit(sf, (fileName, text, writeByteOrderMark, onError, sourceFiles, data) => {
|
|
348
|
+
if (!sourceFiles || sourceFiles.length === 0) {
|
|
349
|
+
this.#compilerHost.writeFile(fileName, text, writeByteOrderMark, onError, sourceFiles, data);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
const sourceFile = ts.getOriginalNode(sourceFiles[0], ts.isSourceFile);
|
|
353
|
+
if (this.#ngProgram) {
|
|
354
|
+
if (this.#ngProgram.compiler.ignoreForEmit.has(sourceFile)) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
this.#ngProgram.compiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
358
|
+
}
|
|
359
|
+
const emitFileInfoCaches = this.#emittedFilesCacheMap.getOrCreate(path.normalize(sourceFile.fileName), []);
|
|
360
|
+
if (PathUtil.isChildPath(sourceFile.fileName, this.#pkgPath)) {
|
|
361
|
+
let realFilePath = fileName;
|
|
362
|
+
let realText = text;
|
|
363
|
+
if (PathUtil.isChildPath(realFilePath, path.resolve(this.#distPath, path.basename(this.#pkgPath), "src"))) {
|
|
364
|
+
realFilePath = path.resolve(this.#distPath, path.relative(path.resolve(this.#distPath, path.basename(this.#pkgPath), "src"), realFilePath));
|
|
365
|
+
if (fileName.endsWith(".js.map")) {
|
|
366
|
+
const sourceMapContents = JSON.parse(realText);
|
|
367
|
+
// remove "../../"
|
|
368
|
+
sourceMapContents.sources[0] = sourceMapContents.sources[0].slice(6);
|
|
369
|
+
realText = JSON.stringify(sourceMapContents);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
emitFileInfoCaches.push({
|
|
373
|
+
outAbsPath: realFilePath,
|
|
374
|
+
text: realText,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
emitFileInfoCaches.push({ text });
|
|
379
|
+
}
|
|
380
|
+
emitFileSet.add(path.normalize(sourceFile.fileName));
|
|
381
|
+
}, undefined, undefined, transformers);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
474
384
|
//-- global style
|
|
475
385
|
if (this.#globalStyleFilePath != null &&
|
|
476
386
|
FsUtil.exists(this.#globalStyleFilePath) &&
|
|
477
387
|
!this.#emittedFilesCacheMap.has(this.#globalStyleFilePath)) {
|
|
478
388
|
this.#debug(`bundle global style...`);
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
389
|
+
await perf.run("bundle global style", async () => {
|
|
390
|
+
const data = await FsUtil.readFileAsync(this.#globalStyleFilePath);
|
|
391
|
+
const contents = await this.#bundleStylesheetAsync(data, this.#globalStyleFilePath, this.#globalStyleFilePath);
|
|
392
|
+
const emitFileInfos = this.#emittedFilesCacheMap.getOrCreate(this.#globalStyleFilePath, []);
|
|
393
|
+
emitFileInfos.push({
|
|
394
|
+
outAbsPath: path.resolve(this.#pkgPath, path.relative(path.resolve(this.#pkgPath, "src"), this.#globalStyleFilePath).replace(/\.scss$/, ".css")),
|
|
395
|
+
text: contents,
|
|
396
|
+
});
|
|
397
|
+
emitFileSet.add(this.#globalStyleFilePath);
|
|
485
398
|
});
|
|
486
|
-
emitFileSet.add(this.#globalStyleFilePath);
|
|
487
399
|
}
|
|
488
400
|
//-- init
|
|
489
401
|
this.#modifiedFileSet.clear();
|
|
490
|
-
|
|
491
|
-
this.#debug(`build completed`, affectedFileSet, diagnostics.length);
|
|
402
|
+
this.#debug(`build completed`, perf.toString());
|
|
492
403
|
//-- result
|
|
493
404
|
return {
|
|
494
405
|
program: this.#program,
|
|
@@ -503,5 +414,121 @@ export class SdTsCompiler {
|
|
|
503
414
|
#debug(...msg) {
|
|
504
415
|
this.#logger.debug(`[${path.basename(this.#pkgPath)}]`, ...msg);
|
|
505
416
|
}
|
|
417
|
+
#findDeps(sf) {
|
|
418
|
+
const deps = [];
|
|
419
|
+
const tc = this.#program.getTypeChecker();
|
|
420
|
+
sf.forEachChild((node) => {
|
|
421
|
+
if (ts.isExportDeclaration(node)) {
|
|
422
|
+
if (node.moduleSpecifier) {
|
|
423
|
+
const moduleSymbol = tc.getSymbolAtLocation(node.moduleSpecifier);
|
|
424
|
+
if (!moduleSymbol) {
|
|
425
|
+
deps.push({
|
|
426
|
+
category: DiagnosticCategory.Error,
|
|
427
|
+
code: -1,
|
|
428
|
+
file: sf,
|
|
429
|
+
start: node.getStart(),
|
|
430
|
+
length: node.getEnd() - node.getStart(),
|
|
431
|
+
messageText: `export moduleSymbol not found`,
|
|
432
|
+
});
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const decls = moduleSymbol.getDeclarations();
|
|
436
|
+
if (!decls) {
|
|
437
|
+
deps.push({
|
|
438
|
+
category: DiagnosticCategory.Error,
|
|
439
|
+
code: -1,
|
|
440
|
+
file: sf,
|
|
441
|
+
start: node.getStart(),
|
|
442
|
+
length: node.getEnd() - node.getStart(),
|
|
443
|
+
messageText: `export decls not found`,
|
|
444
|
+
});
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const namedBindings = node.exportClause;
|
|
448
|
+
if (namedBindings && ts.isNamedExports(namedBindings)) {
|
|
449
|
+
for (const el of namedBindings.elements) {
|
|
450
|
+
for (const decl of decls) {
|
|
451
|
+
deps.push({
|
|
452
|
+
fileName: path.normalize(decl.getSourceFile().fileName),
|
|
453
|
+
importName: el.name.text,
|
|
454
|
+
exportName: el.propertyName?.text ?? el.name.text,
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
if (!moduleSymbol.exports) {
|
|
461
|
+
deps.push({
|
|
462
|
+
category: DiagnosticCategory.Error,
|
|
463
|
+
code: -1,
|
|
464
|
+
file: sf,
|
|
465
|
+
start: node.getStart(),
|
|
466
|
+
length: node.getEnd() - node.getStart(),
|
|
467
|
+
messageText: `moduleSymbol exports not found`,
|
|
468
|
+
});
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
for (const decl of decls) {
|
|
472
|
+
for (const key of moduleSymbol.exports.keys()) {
|
|
473
|
+
deps.push({
|
|
474
|
+
fileName: path.normalize(decl.getSourceFile().fileName),
|
|
475
|
+
importName: key.toString(),
|
|
476
|
+
exportName: key.toString(),
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
else if (ts.isImportDeclaration(node)) {
|
|
484
|
+
const moduleSymbol = tc.getSymbolAtLocation(node.moduleSpecifier);
|
|
485
|
+
if (!moduleSymbol) {
|
|
486
|
+
if (ts.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text.startsWith("./")) {
|
|
487
|
+
deps.push({
|
|
488
|
+
fileName: path.normalize(path.resolve(path.dirname(sf.fileName), node.moduleSpecifier.text)),
|
|
489
|
+
importName: "*",
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
/*else {
|
|
493
|
+
throw new NeverEntryError(`import moduleSymbol: ${sf.fileName} ${node.moduleSpecifier["text"]}`);
|
|
494
|
+
}*/
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
const decls = moduleSymbol.getDeclarations();
|
|
498
|
+
if (!decls) {
|
|
499
|
+
deps.push({
|
|
500
|
+
category: DiagnosticCategory.Error,
|
|
501
|
+
code: -1,
|
|
502
|
+
file: sf,
|
|
503
|
+
start: node.getStart(),
|
|
504
|
+
length: node.getEnd() - node.getStart(),
|
|
505
|
+
messageText: `import decls not found`,
|
|
506
|
+
});
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const namedBindings = node.importClause?.namedBindings;
|
|
510
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
511
|
+
for (const el of namedBindings.elements) {
|
|
512
|
+
for (const decl of decls) {
|
|
513
|
+
deps.push({
|
|
514
|
+
fileName: path.normalize(decl.getSourceFile().fileName),
|
|
515
|
+
importName: el.name.text,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
for (const decl of decls) {
|
|
522
|
+
deps.push({
|
|
523
|
+
fileName: path.normalize(decl.getSourceFile().fileName),
|
|
524
|
+
importName: "*",
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
return deps;
|
|
532
|
+
}
|
|
506
533
|
}
|
|
507
534
|
//# sourceMappingURL=SdTsCompiler.js.map
|