@simplysm/sd-cli 12.15.39 → 12.15.41
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/entry/SdCliCordova.d.ts +33 -1
- package/dist/entry/SdCliCordova.js +84 -88
- package/dist/entry/SdCliElectron.d.ts +5 -1
- package/dist/entry/SdCliElectron.js +21 -21
- package/dist/entry/SdCliLocalUpdate.d.ts +1 -1
- package/dist/entry/SdCliLocalUpdate.js +3 -3
- package/dist/entry/SdCliProject.d.ts +4 -1
- package/dist/entry/SdCliProject.js +11 -11
- package/dist/pkg-builders/SdProjectBuildRunner.d.ts +6 -1
- package/dist/pkg-builders/SdProjectBuildRunner.js +27 -27
- package/dist/pkg-builders/client/SdClientBuildRunner.d.ts +2 -1
- package/dist/pkg-builders/client/SdClientBuildRunner.js +8 -10
- package/dist/pkg-builders/client/SdNgBundler.d.ts +22 -1
- package/dist/pkg-builders/client/SdNgBundler.js +70 -80
- package/dist/pkg-builders/client/SdNgBundlerContext.d.ts +3 -1
- package/dist/pkg-builders/client/SdNgBundlerContext.js +9 -10
- package/dist/pkg-builders/lib/SdCliIndexFileGenerator.d.ts +2 -1
- package/dist/pkg-builders/lib/SdCliIndexFileGenerator.js +5 -5
- package/dist/pkg-builders/lib/SdJsLibBuildRunner.d.ts +1 -1
- package/dist/pkg-builders/lib/SdJsLibBuildRunner.js +2 -2
- package/dist/pkg-builders/lib/SdTsLibBuildRunner.d.ts +1 -1
- package/dist/pkg-builders/lib/SdTsLibBuildRunner.js +2 -3
- package/dist/pkg-builders/lib/SdTsLibBuilder.d.ts +2 -1
- package/dist/pkg-builders/lib/SdTsLibBuilder.js +7 -8
- package/dist/pkg-builders/server/SdServerBuildRunner.d.ts +3 -1
- package/dist/pkg-builders/server/SdServerBuildRunner.js +6 -7
- package/dist/pkg-builders/server/SdServerBundler.d.ts +6 -1
- package/dist/pkg-builders/server/SdServerBundler.js +21 -23
- package/dist/ts-compiler/ScopePathSet.d.ts +1 -1
- package/dist/ts-compiler/ScopePathSet.js +3 -4
- package/dist/ts-compiler/SdDepCache.d.ts +45 -1
- package/dist/ts-compiler/SdDepCache.js +71 -69
- package/dist/ts-compiler/SdStyleBundler.d.ts +5 -1
- package/dist/ts-compiler/SdStyleBundler.js +25 -26
- package/dist/ts-compiler/SdTsCompiler.d.ts +20 -1
- package/dist/ts-compiler/SdTsCompiler.js +122 -129
- package/dist/utils/SdCliPerformanceTimer.d.ts +2 -1
- package/dist/utils/SdCliPerformanceTimer.js +9 -9
- package/package.json +8 -8
- package/src/entry/SdCliCordova.ts +89 -89
- package/src/entry/SdCliElectron.ts +21 -21
- package/src/entry/SdCliLocalUpdate.ts +3 -3
- package/src/entry/SdCliProject.ts +11 -11
- package/src/pkg-builders/SdProjectBuildRunner.ts +27 -27
- package/src/pkg-builders/client/SdClientBuildRunner.ts +10 -10
- package/src/pkg-builders/client/SdNgBundler.ts +78 -78
- package/src/pkg-builders/client/SdNgBundlerContext.ts +10 -10
- package/src/pkg-builders/lib/SdCliIndexFileGenerator.ts +5 -5
- package/src/pkg-builders/lib/SdJsLibBuildRunner.ts +2 -2
- package/src/pkg-builders/lib/SdTsLibBuildRunner.ts +3 -3
- package/src/pkg-builders/lib/SdTsLibBuilder.ts +8 -8
- package/src/pkg-builders/server/SdServerBuildRunner.ts +7 -7
- package/src/pkg-builders/server/SdServerBundler.ts +23 -23
- package/src/ts-compiler/ScopePathSet.ts +4 -4
- package/src/ts-compiler/SdDepCache.ts +47 -47
- package/src/ts-compiler/SdStyleBundler.ts +26 -26
- package/src/ts-compiler/SdTsCompiler.ts +130 -130
- package/src/utils/SdCliPerformanceTimer.ts +9 -9
|
@@ -17,28 +17,28 @@ import { ISdTsCompilerResult } from "../types/build/ISdTsCompilerResult";
|
|
|
17
17
|
import { ScopePathSet } from "./ScopePathSet";
|
|
18
18
|
|
|
19
19
|
export class SdTsCompiler {
|
|
20
|
-
|
|
20
|
+
private readonly _logger = SdLogger.get(["simplysm", "sd-cli", "SdTsCompiler"]);
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
private readonly _isForAngular: boolean;
|
|
23
|
+
private readonly _scopePathSet: ScopePathSet;
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
private readonly _styleBundler: SdStyleBundler | undefined;
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
private _moduleResolutionCache: ts.ModuleResolutionCache | undefined;
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
private _ngProgram: NgtscProgram | undefined;
|
|
30
|
+
private _program: ts.Program | undefined;
|
|
31
31
|
|
|
32
32
|
// 빌드정보 캐싱
|
|
33
|
-
|
|
33
|
+
private readonly _cache = {
|
|
34
34
|
dep: new SdDepCache(),
|
|
35
35
|
type: new WeakMap<ts.Node, ts.Type | undefined>(),
|
|
36
36
|
prop: new WeakMap<ts.Type, Map<string, ts.Symbol | undefined>>(),
|
|
37
37
|
declFiles: new WeakMap<ts.Symbol, TNormPath[]>(),
|
|
38
38
|
ngOrg: new Map<TNormPath, ts.SourceFile>(),
|
|
39
39
|
};
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
private readonly _sourceFileCacheMap = new Map<TNormPath, ts.SourceFile>();
|
|
41
|
+
private readonly _emittedFilesCacheMap = new Map<
|
|
42
42
|
TNormPath,
|
|
43
43
|
{
|
|
44
44
|
outAbsPath?: TNormPath;
|
|
@@ -46,29 +46,29 @@ export class SdTsCompiler {
|
|
|
46
46
|
}[]
|
|
47
47
|
>();
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
private _perf!: SdCliPerformanceTimer;
|
|
50
50
|
|
|
51
51
|
constructor(
|
|
52
52
|
private readonly _opt: ISdTsCompilerOptions,
|
|
53
53
|
private readonly _forBundle: boolean,
|
|
54
54
|
) {
|
|
55
|
-
this
|
|
55
|
+
this._debug("초기화 중...");
|
|
56
56
|
const tsconfigPath = path.resolve(this._opt.pkgPath, "tsconfig.json");
|
|
57
57
|
const tsconfig = FsUtils.readJson(tsconfigPath);
|
|
58
|
-
this
|
|
58
|
+
this._isForAngular = Boolean(tsconfig.angularCompilerOptions);
|
|
59
59
|
|
|
60
|
-
this
|
|
60
|
+
this._scopePathSet = new ScopePathSet(this._opt.scopePathSet);
|
|
61
61
|
|
|
62
62
|
if (!this._opt.watch?.noEmit) {
|
|
63
|
-
this
|
|
63
|
+
this._styleBundler = new SdStyleBundler({
|
|
64
64
|
pkgPath: this._opt.pkgPath,
|
|
65
|
-
scopePathSet: this
|
|
65
|
+
scopePathSet: this._scopePathSet,
|
|
66
66
|
dev: !!this._opt.watch?.dev,
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
private _parseTsConfig(): ITsConfigInfo {
|
|
72
72
|
const tsconfigPath = path.resolve(this._opt.pkgPath, "tsconfig.json");
|
|
73
73
|
const tsconfig = FsUtils.readJson(tsconfigPath);
|
|
74
74
|
const parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._opt.pkgPath, {
|
|
@@ -103,7 +103,7 @@ export class SdTsCompiler {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
private _createCompilerHost(compilerOptions: ts.CompilerOptions, modifiedFileSet: Set<TNormPath>) {
|
|
107
107
|
// 지식: SourceFile은 하나의 파일에만 국한된 정적 정보객체임, 변경된 파일의 SourceFile만 다시 생성하면됨
|
|
108
108
|
|
|
109
109
|
const compilerHost = ts.createCompilerHost(compilerOptions);
|
|
@@ -122,8 +122,8 @@ export class SdTsCompiler {
|
|
|
122
122
|
return this.#sourceFileCacheMap.get(fileNPath);
|
|
123
123
|
}*/
|
|
124
124
|
|
|
125
|
-
if (this
|
|
126
|
-
return this
|
|
125
|
+
if (this._sourceFileCacheMap.has(fileNPath)) {
|
|
126
|
+
return this._sourceFileCacheMap.get(fileNPath);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
const sf: ts.SourceFile | undefined = baseGetSourceFile.call(
|
|
@@ -136,16 +136,16 @@ export class SdTsCompiler {
|
|
|
136
136
|
);
|
|
137
137
|
|
|
138
138
|
if (!sf) {
|
|
139
|
-
this
|
|
139
|
+
this._sourceFileCacheMap.delete(fileNPath);
|
|
140
140
|
return undefined;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
this
|
|
143
|
+
this._sourceFileCacheMap.set(fileNPath, sf);
|
|
144
144
|
|
|
145
145
|
return sf;
|
|
146
146
|
};
|
|
147
147
|
|
|
148
|
-
if (this
|
|
148
|
+
if (this._isForAngular) {
|
|
149
149
|
(compilerHost as AngularCompilerHost).readResource = (fileName: string) => {
|
|
150
150
|
return compilerHost.readFile(fileName) ?? "";
|
|
151
151
|
};
|
|
@@ -163,7 +163,7 @@ export class SdTsCompiler {
|
|
|
163
163
|
return null;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
const styleBundleResult = await this
|
|
166
|
+
const styleBundleResult = await this._styleBundler!.bundleAsync(
|
|
167
167
|
data,
|
|
168
168
|
PathUtils.norm(context.containingFile),
|
|
169
169
|
context.resourceFile != null ? PathUtils.norm(context.resourceFile) : undefined,
|
|
@@ -180,26 +180,26 @@ export class SdTsCompiler {
|
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
this
|
|
183
|
+
this._moduleResolutionCache = ts.createModuleResolutionCache(
|
|
184
184
|
compilerHost.getCurrentDirectory(),
|
|
185
185
|
compilerHost.getCanonicalFileName.bind(compilerHost),
|
|
186
186
|
compilerOptions,
|
|
187
|
-
this
|
|
187
|
+
this._moduleResolutionCache?.getPackageJsonInfoCache(),
|
|
188
188
|
);
|
|
189
|
-
compilerHost.getModuleResolutionCache = () => this
|
|
189
|
+
compilerHost.getModuleResolutionCache = () => this._moduleResolutionCache;
|
|
190
190
|
|
|
191
191
|
return compilerHost;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
async compileAsync(modifiedFileSet: Set<TNormPath>): Promise<ISdTsCompilerResult> {
|
|
195
|
-
this
|
|
195
|
+
this._perf = new SdCliPerformanceTimer("esbuild compile");
|
|
196
196
|
|
|
197
|
-
const prepareResult = await this
|
|
197
|
+
const prepareResult = await this._prepareAsync(modifiedFileSet);
|
|
198
198
|
|
|
199
199
|
const [globalStyleSheet, lintResults, buildResult] = await Promise.all([
|
|
200
|
-
this._opt.watch?.noEmit ? Promise.resolve(undefined) : this
|
|
201
|
-
this._opt.watch?.emitOnly ? Promise.resolve([]) : this
|
|
202
|
-
Promise.resolve(this
|
|
200
|
+
this._opt.watch?.noEmit ? Promise.resolve(undefined) : this._buildGlobalStyleAsync(),
|
|
201
|
+
this._opt.watch?.emitOnly ? Promise.resolve([]) : this._lintAsync(prepareResult),
|
|
202
|
+
Promise.resolve(this._build(prepareResult)),
|
|
203
203
|
]);
|
|
204
204
|
|
|
205
205
|
const messages = [
|
|
@@ -208,136 +208,136 @@ export class SdTsCompiler {
|
|
|
208
208
|
];
|
|
209
209
|
const affectedFileSet = new Set([
|
|
210
210
|
...prepareResult.affectedFileSet,
|
|
211
|
-
...(this
|
|
211
|
+
...(this._styleBundler?.getAffectedFileSet(modifiedFileSet) ?? []),
|
|
212
212
|
]);
|
|
213
213
|
const watchFileSet = new Set([
|
|
214
214
|
...prepareResult.watchFileSet,
|
|
215
|
-
...(this
|
|
215
|
+
...(this._styleBundler?.getAllStyleFileSet() ?? []),
|
|
216
216
|
]);
|
|
217
217
|
|
|
218
|
-
this
|
|
219
|
-
this
|
|
218
|
+
this._debug(`빌드 완료됨`, this._perf.toString());
|
|
219
|
+
this._debug(
|
|
220
220
|
`영향 받은 파일: ${affectedFileSet.size}개`,
|
|
221
221
|
...(modifiedFileSet.size > 0 ? [affectedFileSet] : []),
|
|
222
222
|
);
|
|
223
|
-
this
|
|
223
|
+
this._debug(`감시 중인 파일: ${watchFileSet.size}개`);
|
|
224
224
|
|
|
225
225
|
return {
|
|
226
226
|
messages: messages,
|
|
227
227
|
affectedFileSet: affectedFileSet,
|
|
228
228
|
watchFileSet: watchFileSet,
|
|
229
|
-
stylesheetBundlingResultMap: this
|
|
230
|
-
emittedFilesCacheMap: this
|
|
229
|
+
stylesheetBundlingResultMap: this._styleBundler?.getResultCache() ?? new Map(),
|
|
230
|
+
emittedFilesCacheMap: this._emittedFilesCacheMap,
|
|
231
231
|
emitFileSet: new Set([...buildResult.emitFileSet, globalStyleSheet].filterExists()),
|
|
232
232
|
};
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
async
|
|
236
|
-
const tsconfig = this
|
|
235
|
+
private async _prepareAsync(modifiedFileSet: Set<TNormPath>): Promise<IPrepareResult> {
|
|
236
|
+
const tsconfig = this._parseTsConfig();
|
|
237
237
|
|
|
238
238
|
if (modifiedFileSet.size !== 0 && this._opt.watch) {
|
|
239
|
-
this
|
|
239
|
+
this._debug(`캐시 무효화 및 초기화 중...`);
|
|
240
240
|
|
|
241
241
|
// this._perf.run("캐시 무효화 및 초기화", () => {
|
|
242
|
-
this
|
|
242
|
+
this._perf.run("캐시 무효화 및 초기화", () => {
|
|
243
243
|
// 소스파일은 변경된 파일들로 무효화
|
|
244
244
|
for (const modifiedFile of modifiedFileSet) {
|
|
245
|
-
this
|
|
245
|
+
this._sourceFileCacheMap.delete(modifiedFile);
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
// 스타일 번들러 무효화 (transformResource 재실행 땜에 필요할듯)
|
|
249
|
-
if (this
|
|
250
|
-
const styleAffectedFileSet = this
|
|
249
|
+
if (this._styleBundler) {
|
|
250
|
+
const styleAffectedFileSet = this._styleBundler.invalidate(modifiedFileSet);
|
|
251
251
|
// 스타일 변경된 파일들로 무효화
|
|
252
252
|
for (const styleAffectedFile of styleAffectedFileSet) {
|
|
253
|
-
this
|
|
254
|
-
this
|
|
253
|
+
this._sourceFileCacheMap.delete(styleAffectedFile);
|
|
254
|
+
this._emittedFilesCacheMap.delete(styleAffectedFile);
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
// angular origin 파일 매핑은 변경된 파일들로 무효화
|
|
259
259
|
for (const modifiedFile of modifiedFileSet) {
|
|
260
|
-
this
|
|
260
|
+
this._cache.ngOrg.delete(modifiedFile);
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
// 기존 의존성에 의해 영향받는 파일들 계산
|
|
264
|
-
this
|
|
264
|
+
this._cache.dep.invalidates(modifiedFileSet);
|
|
265
265
|
|
|
266
266
|
// 결과물이 바뀌어야 하는 캐시 모두 무효화 (modified만 다시쓰면될듯..)
|
|
267
267
|
for (const modifiedFile of modifiedFileSet) {
|
|
268
|
-
this
|
|
268
|
+
this._emittedFilesCacheMap.delete(modifiedFile);
|
|
269
269
|
}
|
|
270
270
|
});
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
this
|
|
273
|
+
this._debug(`ts.Program 생성 중...`);
|
|
274
274
|
|
|
275
|
-
const compilerHost = this
|
|
276
|
-
return this
|
|
275
|
+
const compilerHost = this._perf.run("ts.CompilerHost 생성", () => {
|
|
276
|
+
return this._createCompilerHost(tsconfig.options, modifiedFileSet);
|
|
277
277
|
});
|
|
278
278
|
|
|
279
|
-
this
|
|
280
|
-
if (this
|
|
281
|
-
this
|
|
279
|
+
this._perf.run("ts.Program 생성", () => {
|
|
280
|
+
if (this._isForAngular) {
|
|
281
|
+
this._ngProgram = new NgtscProgram(
|
|
282
282
|
tsconfig.fileNames,
|
|
283
283
|
tsconfig.options,
|
|
284
284
|
compilerHost,
|
|
285
|
-
this
|
|
285
|
+
this._ngProgram,
|
|
286
286
|
);
|
|
287
|
-
this
|
|
287
|
+
this._program = this._ngProgram.getTsProgram();
|
|
288
288
|
} else {
|
|
289
|
-
this
|
|
289
|
+
this._program = ts.createProgram(
|
|
290
290
|
tsconfig.fileNames,
|
|
291
291
|
tsconfig.options,
|
|
292
292
|
compilerHost,
|
|
293
|
-
this
|
|
293
|
+
this._program,
|
|
294
294
|
);
|
|
295
295
|
}
|
|
296
296
|
});
|
|
297
297
|
|
|
298
|
-
if (this
|
|
299
|
-
this
|
|
298
|
+
if (this._ngProgram) {
|
|
299
|
+
this._debug(`Angular 템플릿 분석...`);
|
|
300
300
|
|
|
301
|
-
await this
|
|
302
|
-
await this
|
|
301
|
+
await this._perf.run("Angular 템플릿 분석", async () => {
|
|
302
|
+
await this._ngProgram!.compiler.analyzeAsync();
|
|
303
303
|
});
|
|
304
304
|
}
|
|
305
305
|
|
|
306
306
|
if (this._opt.watch && !this._opt.watch.emitOnly) {
|
|
307
|
-
this
|
|
307
|
+
this._debug(`새 의존성 분석 중...`);
|
|
308
308
|
|
|
309
|
-
this
|
|
309
|
+
this._perf.run("새 의존성 분석", () => {
|
|
310
310
|
// SdTsDependencyAnalyzer를 통해 의존성 분석 및 SdDepCache 업데이트
|
|
311
|
-
SdDepAnalyzer.analyze(this
|
|
311
|
+
SdDepAnalyzer.analyze(this._program!, compilerHost, this._scopePathSet, this._cache);
|
|
312
312
|
});
|
|
313
313
|
|
|
314
314
|
// Angular 리소스 의존성 추가
|
|
315
|
-
if (this
|
|
316
|
-
this
|
|
315
|
+
if (this._ngProgram) {
|
|
316
|
+
this._debug(`새 의존성 분석(Angular) 중...`);
|
|
317
317
|
|
|
318
|
-
this
|
|
318
|
+
this._perf.run("새 의존성 분석(Angular)", () => {
|
|
319
319
|
SdDepAnalyzer.analyzeAngularResources(
|
|
320
|
-
this
|
|
321
|
-
this
|
|
322
|
-
this
|
|
320
|
+
this._ngProgram!,
|
|
321
|
+
this._scopePathSet,
|
|
322
|
+
this._cache.dep,
|
|
323
323
|
);
|
|
324
324
|
});
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
-
const allTsFiles = this
|
|
328
|
+
const allTsFiles = this._program!.getSourceFiles().mapMany((item) => [
|
|
329
329
|
PathUtils.norm(item.fileName),
|
|
330
330
|
...(item.fileName.endsWith(".d.ts")
|
|
331
331
|
? [PathUtils.norm(item.fileName.replace(/\.d\.ts$/, "") + ".js")]
|
|
332
332
|
: []),
|
|
333
333
|
]);
|
|
334
|
-
const watchFileSet = new Set(allTsFiles.filter((item) => this
|
|
334
|
+
const watchFileSet = new Set(allTsFiles.filter((item) => this._scopePathSet.inScope(item)));
|
|
335
335
|
|
|
336
336
|
let affectedFileSet: Set<TNormPath>;
|
|
337
337
|
if (modifiedFileSet.size === 0) {
|
|
338
|
-
affectedFileSet = new Set(allTsFiles.filter((item) => this
|
|
338
|
+
affectedFileSet = new Set(allTsFiles.filter((item) => this._scopePathSet.inScope(item)));
|
|
339
339
|
} else {
|
|
340
|
-
const affectedFileMap = this
|
|
340
|
+
const affectedFileMap = this._cache.dep.getAffectedFileMap(modifiedFileSet);
|
|
341
341
|
affectedFileSet = new Set(
|
|
342
342
|
Array.from(affectedFileMap.values()).mapMany((item) => Array.from(item)),
|
|
343
343
|
);
|
|
@@ -348,13 +348,13 @@ export class SdTsCompiler {
|
|
|
348
348
|
compilerHost,
|
|
349
349
|
watchFileSet,
|
|
350
350
|
affectedFileSet,
|
|
351
|
-
styleAffectedFileSet: this
|
|
351
|
+
styleAffectedFileSet: this._styleBundler?.getAffectedFileSet(modifiedFileSet) ?? new Set(),
|
|
352
352
|
};
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
async
|
|
356
|
-
return await this
|
|
357
|
-
this
|
|
355
|
+
private async _lintAsync(prepareResult: IPrepareResult) {
|
|
356
|
+
return await this._perf.run("Linting", async () => {
|
|
357
|
+
this._debug(`Linting...`);
|
|
358
358
|
|
|
359
359
|
const lintFilePaths = Array.from(prepareResult.affectedFileSet)
|
|
360
360
|
.filter((item) => PathUtils.isChildPath(item, this._opt.pkgPath))
|
|
@@ -374,7 +374,7 @@ export class SdTsCompiler {
|
|
|
374
374
|
// project: true,
|
|
375
375
|
// tsconfigRootDir: this._opt.pkgPath,
|
|
376
376
|
project: null,
|
|
377
|
-
programs: [this
|
|
377
|
+
programs: [this._program],
|
|
378
378
|
},
|
|
379
379
|
},
|
|
380
380
|
},
|
|
@@ -386,30 +386,30 @@ export class SdTsCompiler {
|
|
|
386
386
|
// return await linter.lintText(sf.text, { filePath: lintFilePath });
|
|
387
387
|
// });
|
|
388
388
|
const result = await linter.lintFiles(lintFilePaths);
|
|
389
|
-
this
|
|
389
|
+
this._debug(`Linting 완료`);
|
|
390
390
|
// return result.mapMany();
|
|
391
391
|
return result;
|
|
392
392
|
});
|
|
393
393
|
}
|
|
394
394
|
|
|
395
|
-
async
|
|
396
|
-
if (!this
|
|
395
|
+
private async _buildGlobalStyleAsync() {
|
|
396
|
+
if (!this._isForAngular) return;
|
|
397
397
|
|
|
398
398
|
//-- global style
|
|
399
399
|
const globalStyleFilePath = PathUtils.norm(this._opt.pkgPath, "scss/styles.scss");
|
|
400
|
-
if (this
|
|
400
|
+
if (this._emittedFilesCacheMap.has(globalStyleFilePath)) return;
|
|
401
401
|
if (!FsUtils.exists(globalStyleFilePath)) return;
|
|
402
402
|
|
|
403
|
-
this
|
|
403
|
+
this._debug(`전역 스타일 번들링 중...`);
|
|
404
404
|
|
|
405
|
-
await this
|
|
405
|
+
await this._perf.run("전역 스타일 번들링", async () => {
|
|
406
406
|
const data = await FsUtils.readFileAsync(globalStyleFilePath);
|
|
407
|
-
const stylesheetBundlingResult = await this
|
|
407
|
+
const stylesheetBundlingResult = await this._styleBundler!.bundleAsync(
|
|
408
408
|
data,
|
|
409
409
|
globalStyleFilePath,
|
|
410
410
|
globalStyleFilePath,
|
|
411
411
|
);
|
|
412
|
-
const emitFileInfos = this
|
|
412
|
+
const emitFileInfos = this._emittedFilesCacheMap.getOrCreate(globalStyleFilePath, []);
|
|
413
413
|
emitFileInfos.push({
|
|
414
414
|
outAbsPath: PathUtils.norm(
|
|
415
415
|
this._opt.pkgPath,
|
|
@@ -424,51 +424,51 @@ export class SdTsCompiler {
|
|
|
424
424
|
return globalStyleFilePath;
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
-
|
|
427
|
+
private _build(prepareResult: IPrepareResult) {
|
|
428
428
|
const emitFileSet = new Set<TNormPath>();
|
|
429
429
|
const diagnostics: ts.Diagnostic[] = [];
|
|
430
430
|
|
|
431
431
|
if (!this._opt.watch?.emitOnly) {
|
|
432
|
-
this
|
|
432
|
+
this._debug(`프로그램 진단 수집 중...`);
|
|
433
433
|
|
|
434
|
-
this
|
|
434
|
+
this._perf.run("프로그램 진단 수집", () => {
|
|
435
435
|
diagnostics.push(
|
|
436
|
-
...this
|
|
437
|
-
...this
|
|
438
|
-
...this
|
|
436
|
+
...this._program!.getConfigFileParsingDiagnostics(),
|
|
437
|
+
...this._program!.getOptionsDiagnostics(),
|
|
438
|
+
...this._program!.getGlobalDiagnostics(),
|
|
439
439
|
);
|
|
440
440
|
|
|
441
|
-
if (this
|
|
442
|
-
diagnostics.push(...this
|
|
441
|
+
if (this._ngProgram) {
|
|
442
|
+
diagnostics.push(...this._ngProgram.compiler.getOptionDiagnostics());
|
|
443
443
|
}
|
|
444
444
|
});
|
|
445
445
|
|
|
446
|
-
this
|
|
446
|
+
this._debug(`개별 파일 진단 수집 중...`);
|
|
447
447
|
|
|
448
448
|
for (const affectedFile of prepareResult.affectedFileSet) {
|
|
449
449
|
if (!PathUtils.isChildPath(affectedFile, this._opt.pkgPath)) continue;
|
|
450
450
|
|
|
451
|
-
const affectedSourceFile = this
|
|
451
|
+
const affectedSourceFile = this._program!.getSourceFile(affectedFile);
|
|
452
452
|
if (
|
|
453
453
|
!affectedSourceFile ||
|
|
454
|
-
(this
|
|
454
|
+
(this._ngProgram && this._ngProgram.compiler.ignoreForDiagnostics.has(affectedSourceFile))
|
|
455
455
|
) {
|
|
456
456
|
continue;
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
-
this
|
|
459
|
+
this._perf.run("개별 파일 진단 수집", () => {
|
|
460
460
|
diagnostics.push(
|
|
461
|
-
...this
|
|
462
|
-
...this
|
|
461
|
+
...this._program!.getSyntacticDiagnostics(affectedSourceFile),
|
|
462
|
+
...this._program!.getSemanticDiagnostics(affectedSourceFile),
|
|
463
463
|
);
|
|
464
464
|
});
|
|
465
465
|
|
|
466
|
-
if (this
|
|
467
|
-
this
|
|
466
|
+
if (this._ngProgram) {
|
|
467
|
+
this._perf.run("개별 파일 진단 수집(Angular)", () => {
|
|
468
468
|
if (affectedSourceFile.isDeclarationFile) return;
|
|
469
469
|
|
|
470
470
|
diagnostics.push(
|
|
471
|
-
...this
|
|
471
|
+
...this._ngProgram!.compiler.getDiagnosticsForFile(
|
|
472
472
|
affectedSourceFile,
|
|
473
473
|
OptimizeFor.WholeProgram,
|
|
474
474
|
),
|
|
@@ -479,13 +479,13 @@ export class SdTsCompiler {
|
|
|
479
479
|
}
|
|
480
480
|
|
|
481
481
|
if (!this._opt.watch?.noEmit) {
|
|
482
|
-
this
|
|
483
|
-
this
|
|
482
|
+
this._perf.run("파일 출력 (emit)", () => {
|
|
483
|
+
this._debug(`파일 출력 준비 중...`);
|
|
484
484
|
|
|
485
485
|
let transformers: ts.CustomTransformers = {};
|
|
486
486
|
|
|
487
|
-
if (this
|
|
488
|
-
const angularTransfomers = this
|
|
487
|
+
if (this._ngProgram) {
|
|
488
|
+
const angularTransfomers = this._ngProgram.compiler.prepareEmit().transformers;
|
|
489
489
|
(transformers.before ??= []).push(...(angularTransfomers.before ?? []));
|
|
490
490
|
(transformers.after ??= []).push(...(angularTransfomers.after ?? []));
|
|
491
491
|
(transformers.afterDeclarations ??= []).push(
|
|
@@ -493,7 +493,7 @@ export class SdTsCompiler {
|
|
|
493
493
|
);
|
|
494
494
|
|
|
495
495
|
(transformers.before ??= []).push(
|
|
496
|
-
replaceBootstrap(() => this
|
|
496
|
+
replaceBootstrap(() => this._program!.getTypeChecker()),
|
|
497
497
|
);
|
|
498
498
|
(transformers.before ??= []).push(
|
|
499
499
|
createWorkerTransformer((file, importer) => {
|
|
@@ -504,7 +504,7 @@ export class SdTsCompiler {
|
|
|
504
504
|
);
|
|
505
505
|
}
|
|
506
506
|
|
|
507
|
-
this
|
|
507
|
+
this._debug(`파일 출력 중...`);
|
|
508
508
|
|
|
509
509
|
// affected에 새로 추가된 파일은 포함되지 않는 현상이 있어 sourceFileSet으로 바꿈
|
|
510
510
|
// 비교해보니, 딱히 getSourceFiles라서 더 느려지는것 같지는 않음
|
|
@@ -515,16 +515,16 @@ export class SdTsCompiler {
|
|
|
515
515
|
]) {
|
|
516
516
|
if (affectedFile.endsWith(".scss")) continue;
|
|
517
517
|
if (
|
|
518
|
-
this
|
|
518
|
+
this._emittedFilesCacheMap
|
|
519
519
|
.get(affectedFile)
|
|
520
520
|
?.some((item) => !item.outAbsPath?.endsWith(".css"))
|
|
521
521
|
)
|
|
522
522
|
continue;
|
|
523
523
|
|
|
524
|
-
const sf = this
|
|
524
|
+
const sf = this._program!.getSourceFile(affectedFile);
|
|
525
525
|
if (!sf || sf.isDeclarationFile) continue;
|
|
526
|
-
if (this
|
|
527
|
-
if (this
|
|
526
|
+
if (this._ngProgram?.compiler.ignoreForEmit.has(sf)) continue;
|
|
527
|
+
if (this._ngProgram?.compiler.incrementalCompilation.safeToSkipEmit(sf)) continue;
|
|
528
528
|
|
|
529
529
|
// 번들이 아닌 외부패키지는 보통 emit안해도 됨
|
|
530
530
|
// but esbuild를 통해 bundle로 묶어야 하는놈들은 모든 output이 있어야 함.
|
|
@@ -532,7 +532,7 @@ export class SdTsCompiler {
|
|
|
532
532
|
continue;
|
|
533
533
|
}
|
|
534
534
|
|
|
535
|
-
this
|
|
535
|
+
this._program!.emit(
|
|
536
536
|
sf,
|
|
537
537
|
(fileName, text, writeByteOrderMark, onError, sourceFiles, data) => {
|
|
538
538
|
if (!sourceFiles || sourceFiles.length === 0) {
|
|
@@ -548,18 +548,18 @@ export class SdTsCompiler {
|
|
|
548
548
|
}
|
|
549
549
|
|
|
550
550
|
const sourceFile = ts.getOriginalNode(sourceFiles[0], ts.isSourceFile);
|
|
551
|
-
if (this
|
|
552
|
-
if (this
|
|
553
|
-
this
|
|
551
|
+
if (this._ngProgram) {
|
|
552
|
+
if (this._ngProgram.compiler.ignoreForEmit.has(sourceFile)) return;
|
|
553
|
+
this._ngProgram.compiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
554
554
|
}
|
|
555
555
|
|
|
556
|
-
const emitFileInfoCaches = this
|
|
556
|
+
const emitFileInfoCaches = this._emittedFilesCacheMap.getOrCreate(
|
|
557
557
|
PathUtils.norm(sourceFile.fileName),
|
|
558
558
|
[],
|
|
559
559
|
);
|
|
560
560
|
|
|
561
561
|
if (PathUtils.isChildPath(sourceFile.fileName, this._opt.pkgPath)) {
|
|
562
|
-
const real = this
|
|
562
|
+
const real = this._convertOutputToReal(
|
|
563
563
|
fileName,
|
|
564
564
|
prepareResult.tsconfig.distPath,
|
|
565
565
|
text,
|
|
@@ -567,7 +567,7 @@ export class SdTsCompiler {
|
|
|
567
567
|
|
|
568
568
|
emitFileInfoCaches.push({
|
|
569
569
|
outAbsPath: real.filePath,
|
|
570
|
-
text: this
|
|
570
|
+
text: this._removeOutputDevModeLine(real.text),
|
|
571
571
|
});
|
|
572
572
|
} else {
|
|
573
573
|
emitFileInfoCaches.push({ text });
|
|
@@ -581,7 +581,7 @@ export class SdTsCompiler {
|
|
|
581
581
|
);
|
|
582
582
|
}
|
|
583
583
|
|
|
584
|
-
this
|
|
584
|
+
this._debug(`파일 출력 완료`);
|
|
585
585
|
});
|
|
586
586
|
}
|
|
587
587
|
|
|
@@ -591,7 +591,7 @@ export class SdTsCompiler {
|
|
|
591
591
|
};
|
|
592
592
|
}
|
|
593
593
|
|
|
594
|
-
|
|
594
|
+
private _convertOutputToReal(filePath: string, distPath: string, text: string) {
|
|
595
595
|
let realFilePath = PathUtils.norm(filePath);
|
|
596
596
|
let realText = text;
|
|
597
597
|
|
|
@@ -611,15 +611,15 @@ export class SdTsCompiler {
|
|
|
611
611
|
return { filePath: realFilePath, text: realText };
|
|
612
612
|
}
|
|
613
613
|
|
|
614
|
-
|
|
614
|
+
private _removeOutputDevModeLine(str: string) {
|
|
615
615
|
return str.replace(
|
|
616
616
|
/\(\(\) => \{ \(typeof ngDevMode === "undefined" \|\| ngDevMode\) && i0.ɵsetClassDebugInfo\(.*, \{ className: ".*", filePath: ".*", lineNumber: [0-9]* }\); }\)\(\);/,
|
|
617
617
|
"",
|
|
618
618
|
);
|
|
619
619
|
}
|
|
620
620
|
|
|
621
|
-
|
|
622
|
-
this
|
|
621
|
+
private _debug(...msg: any[]): void {
|
|
622
|
+
this._logger.debug(`[${path.basename(this._opt.pkgPath)}]`, ...msg);
|
|
623
623
|
}
|
|
624
624
|
}
|
|
625
625
|
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
export class SdCliPerformanceTimer {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
private readonly _startingMap = new Map<string, { time: number; cpu: NodeJS.CpuUsage }>();
|
|
3
|
+
private readonly _resultMap = new Map<string, { time: number; cpu: number }>();
|
|
4
4
|
|
|
5
5
|
constructor(private readonly _name: string) {
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
start(name: string) {
|
|
9
|
-
this
|
|
9
|
+
this._startingMap.set(name, {
|
|
10
10
|
time: new Date().getTime(),
|
|
11
11
|
cpu: process.cpuUsage(),
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
end(name: string) {
|
|
16
|
-
const start = this
|
|
16
|
+
const start = this._startingMap.get(name);
|
|
17
17
|
if (start == null) throw new Error(`No start record for '${name}'`);
|
|
18
18
|
|
|
19
19
|
const time = new Date().getTime() - start.time;
|
|
20
20
|
const cpuUsage = process.cpuUsage(start.cpu);
|
|
21
21
|
const cpu = (cpuUsage.user + cpuUsage.system) / 1000; // μs -> ms
|
|
22
22
|
|
|
23
|
-
this
|
|
24
|
-
this
|
|
23
|
+
this._resultMap.set(name, { time, cpu });
|
|
24
|
+
this._startingMap.delete(name);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
run<R>(name: string, fn: () => R): R {
|
|
@@ -32,8 +32,8 @@ export class SdCliPerformanceTimer {
|
|
|
32
32
|
const duration = new Date().getTime() - start;
|
|
33
33
|
const cpu = (process.cpuUsage(startCpu).user + process.cpuUsage(startCpu).system) / 1000;
|
|
34
34
|
|
|
35
|
-
const prev = this
|
|
36
|
-
this
|
|
35
|
+
const prev = this._resultMap.get(name);
|
|
36
|
+
this._resultMap.set(name, {
|
|
37
37
|
time: (prev?.time ?? 0) + duration,
|
|
38
38
|
cpu: (prev?.cpu ?? 0) + cpu,
|
|
39
39
|
});
|
|
@@ -52,7 +52,7 @@ export class SdCliPerformanceTimer {
|
|
|
52
52
|
toString() {
|
|
53
53
|
return `${this._name} 성능 보고서
|
|
54
54
|
------------------------------------
|
|
55
|
-
${Array.from(this
|
|
55
|
+
${Array.from(this._resultMap.entries())
|
|
56
56
|
.map(([key, val]) =>
|
|
57
57
|
`${key}: ${val.time.toLocaleString()}ms (${val.cpu.toLocaleString()}ms CPU)`,
|
|
58
58
|
)
|