@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
|
@@ -2,7 +2,10 @@ import { TNormPath } from "@simplysm/sd-core-node";
|
|
|
2
2
|
import { ISdProjectConfig } from "../types/config/ISdProjectConfig";
|
|
3
3
|
import { ISdBuildMessage } from "../types/build/ISdBuildMessage";
|
|
4
4
|
export declare class SdProjectBuildRunner {
|
|
5
|
-
|
|
5
|
+
private static readonly _logger;
|
|
6
|
+
private static readonly _buildInfoMap;
|
|
7
|
+
private static readonly _serverInfoMap;
|
|
8
|
+
private static readonly _resultCache;
|
|
6
9
|
static watchAsync(opt: {
|
|
7
10
|
allPkgPaths: TNormPath[];
|
|
8
11
|
pkgPaths: TNormPath[];
|
|
@@ -17,4 +20,6 @@ export declare class SdProjectBuildRunner {
|
|
|
17
20
|
pkgPaths: TNormPath[];
|
|
18
21
|
projConf: ISdProjectConfig;
|
|
19
22
|
}): Promise<ISdBuildMessage[]>;
|
|
23
|
+
private static _getScopePathSetAsync;
|
|
24
|
+
private static _restartServerAsync;
|
|
20
25
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { FsUtils, PathUtils, SdFsWatcher, SdLogger, SdWorker, } from "@simplysm/sd-core-node";
|
|
2
2
|
import path from "path";
|
|
3
3
|
export class SdProjectBuildRunner {
|
|
4
|
-
static
|
|
5
|
-
static
|
|
6
|
-
static
|
|
7
|
-
static
|
|
4
|
+
static { this._logger = SdLogger.get(["simplysm", "sd-cli", "SdProjectBuildRunner"]); }
|
|
5
|
+
static { this._buildInfoMap = new Map(); }
|
|
6
|
+
static { this._serverInfoMap = new Map(); }
|
|
7
|
+
static { this._resultCache = new Map(); }
|
|
8
8
|
static async watchAsync(opt) {
|
|
9
|
-
const scopePathSet = await this
|
|
9
|
+
const scopePathSet = await this._getScopePathSetAsync(opt.allPkgPaths, Object.keys(opt.projConf.localUpdates ?? {}));
|
|
10
10
|
const watcher = await SdFsWatcher.watchAsync(Array.from(scopePathSet), {
|
|
11
11
|
ignoreInitial: false,
|
|
12
12
|
});
|
|
@@ -15,7 +15,7 @@ export class SdProjectBuildRunner {
|
|
|
15
15
|
const changeFiles = changeInfos.map((item) => PathUtils.norm(item.path));
|
|
16
16
|
const changedPkgInfos = opt.pkgPaths
|
|
17
17
|
.map((pkgPath) => {
|
|
18
|
-
let buildInfo = this
|
|
18
|
+
let buildInfo = this._buildInfoMap.get(pkgPath);
|
|
19
19
|
if (!buildInfo)
|
|
20
20
|
return { pkgPath };
|
|
21
21
|
const modifiedFileSet = new Set(changeFiles.filter((item) => buildInfo.watchFileSet.has(item) ||
|
|
@@ -55,7 +55,7 @@ export class SdProjectBuildRunner {
|
|
|
55
55
|
},
|
|
56
56
|
]);
|
|
57
57
|
const result = await buildWorker.run("rebuild", []);
|
|
58
|
-
this
|
|
58
|
+
this._buildInfoMap.set(changedPkgInfo.pkgPath, {
|
|
59
59
|
buildWorker,
|
|
60
60
|
watchFileSet: result.watchFileSet,
|
|
61
61
|
});
|
|
@@ -90,9 +90,9 @@ export class SdProjectBuildRunner {
|
|
|
90
90
|
const pkgConf = opt.projConf.packages[path.basename(buildResult.pkgPath)];
|
|
91
91
|
if (pkgConf.type === "server") {
|
|
92
92
|
const serverName = path.basename(buildResult.pkgPath);
|
|
93
|
-
this
|
|
94
|
-
const serverInfo = this
|
|
95
|
-
const restartServerResult = await this
|
|
93
|
+
this._logger.debug(`서버 '${serverName}' 재시작...`);
|
|
94
|
+
const serverInfo = this._serverInfoMap.getOrCreate(serverName, {});
|
|
95
|
+
const restartServerResult = await this._restartServerAsync(serverInfo.worker, buildResult.pkgPath, pkgConf);
|
|
96
96
|
serverInfo.worker = restartServerResult.worker;
|
|
97
97
|
serverInfo.port = restartServerResult.port;
|
|
98
98
|
/*await serverInfo.worker.run("addPathProxy", [
|
|
@@ -107,9 +107,9 @@ export class SdProjectBuildRunner {
|
|
|
107
107
|
}
|
|
108
108
|
else if (pkgConf.type === "client" && typeof pkgConf.server === "object") {
|
|
109
109
|
const serverName = pkgConf.server.port.toString();
|
|
110
|
-
this
|
|
111
|
-
const serverInfo = this
|
|
112
|
-
const restartServerResult = await this
|
|
110
|
+
this._logger.debug(`서버 '${serverName}' 재시작...`);
|
|
111
|
+
const serverInfo = this._serverInfoMap.getOrCreate(serverName, {});
|
|
112
|
+
const restartServerResult = await this._restartServerAsync(serverInfo.worker, buildResult.pkgPath, pkgConf.server.port);
|
|
113
113
|
serverInfo.worker = restartServerResult.worker;
|
|
114
114
|
serverInfo.port = restartServerResult.port;
|
|
115
115
|
/*await worker.run("addPathProxy", [
|
|
@@ -132,7 +132,7 @@ export class SdProjectBuildRunner {
|
|
|
132
132
|
: undefined;
|
|
133
133
|
if (serverKey == null)
|
|
134
134
|
continue;
|
|
135
|
-
const serverInfo = this
|
|
135
|
+
const serverInfo = this._serverInfoMap.get(serverKey);
|
|
136
136
|
if (!serverInfo || !serverInfo.worker)
|
|
137
137
|
continue;
|
|
138
138
|
const distPath = path.resolve(buildResult.pkgPath, "dist");
|
|
@@ -143,7 +143,7 @@ export class SdProjectBuildRunner {
|
|
|
143
143
|
});
|
|
144
144
|
if (buildResult.isFirst)
|
|
145
145
|
continue;
|
|
146
|
-
this
|
|
146
|
+
this._logger.debug(`클라이언트 '${clientName}' 새로고침...`);
|
|
147
147
|
await serverInfo.worker.run("broadcastReload", [
|
|
148
148
|
clientName,
|
|
149
149
|
new Set(Array.from(buildResult.emitFileSet)
|
|
@@ -153,7 +153,7 @@ export class SdProjectBuildRunner {
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
// 서버 Proxy 설정
|
|
156
|
-
for (const serverInfo of this
|
|
156
|
+
for (const serverInfo of this._serverInfoMap.values()) {
|
|
157
157
|
if (!serverInfo.worker)
|
|
158
158
|
continue;
|
|
159
159
|
await serverInfo.worker.run("setPathProxy", [
|
|
@@ -164,8 +164,8 @@ export class SdProjectBuildRunner {
|
|
|
164
164
|
]);
|
|
165
165
|
}
|
|
166
166
|
// 접속주소 logging
|
|
167
|
-
for (const serverName of this
|
|
168
|
-
const serverInfo = this
|
|
167
|
+
for (const serverName of this._serverInfoMap.keys()) {
|
|
168
|
+
const serverInfo = this._serverInfoMap.get(serverName);
|
|
169
169
|
const clientPaths = [];
|
|
170
170
|
for (const [clientName, clientInfo] of serverInfo?.clientMap?.entries() ?? []) {
|
|
171
171
|
for (const buildType of clientInfo.buildTypes) {
|
|
@@ -177,27 +177,27 @@ export class SdProjectBuildRunner {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
|
-
this
|
|
180
|
+
this._logger.info("클라이언트 개발 서버 접속 주소\n" + clientPaths.join("\n"));
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
// 빌드 완료 이벤트
|
|
184
184
|
for (const buildResult of buildResults) {
|
|
185
|
-
this
|
|
185
|
+
this._resultCache.delete(buildResult.pkgPath);
|
|
186
186
|
for (const affectedFilePath of buildResult.affectedFileSet) {
|
|
187
|
-
this
|
|
187
|
+
this._resultCache.delete(affectedFilePath);
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
for (const buildResult of buildResults) {
|
|
191
191
|
for (const buildMessage of buildResult.buildMessages) {
|
|
192
|
-
const cacheItem = this
|
|
192
|
+
const cacheItem = this._resultCache.getOrCreate(buildMessage.filePath ?? buildResult.pkgPath, []);
|
|
193
193
|
cacheItem.push(buildMessage);
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
-
opt.onComplete(Array.from(this
|
|
196
|
+
opt.onComplete(Array.from(this._resultCache.values()).mapMany());
|
|
197
197
|
});
|
|
198
198
|
}
|
|
199
199
|
static async buildAsync(opt) {
|
|
200
|
-
const scopePathSet = await this
|
|
200
|
+
const scopePathSet = await this._getScopePathSetAsync(opt.allPkgPaths, Object.keys(opt.projConf.localUpdates ?? {}));
|
|
201
201
|
const buildResults = await opt.pkgPaths.parallelAsync(async (pkgPath) => {
|
|
202
202
|
const pkgConf = opt.projConf.packages[path.basename(pkgPath)];
|
|
203
203
|
const worker = new SdWorker(import.meta.resolve("../workers/build-runner.worker"), {
|
|
@@ -221,7 +221,7 @@ export class SdProjectBuildRunner {
|
|
|
221
221
|
});
|
|
222
222
|
return buildResults.mapMany((item) => item.buildMessages);
|
|
223
223
|
}
|
|
224
|
-
static async
|
|
224
|
+
static async _getScopePathSetAsync(pkgPaths, localUpdateGlobs) {
|
|
225
225
|
const workspacePaths = pkgPaths.mapMany((item) => [
|
|
226
226
|
path.resolve(item, "src"),
|
|
227
227
|
path.resolve(item, "public"),
|
|
@@ -231,7 +231,7 @@ export class SdProjectBuildRunner {
|
|
|
231
231
|
const localUpdatePaths = (await localUpdateGlobs.mapManyAsync(async (glob) => await FsUtils.globAsync(path.resolve(process.cwd(), "node_modules", glob)))).mapMany((dir) => [path.resolve(dir, "dist"), path.resolve(dir, "scss")]);
|
|
232
232
|
return new Set([...workspacePaths, ...localUpdatePaths].map((item) => PathUtils.norm(item)));
|
|
233
233
|
}
|
|
234
|
-
static async
|
|
234
|
+
static async _restartServerAsync(prevWorker, pkgPath, pkgConfOrPort) {
|
|
235
235
|
if (prevWorker) {
|
|
236
236
|
await prevWorker.killAsync();
|
|
237
237
|
}
|
|
@@ -252,7 +252,7 @@ export class SdProjectBuildRunner {
|
|
|
252
252
|
const port = await worker.run("listen", [
|
|
253
253
|
typeof pkgConfOrPort === "number" ? pkgConfOrPort : pkgPath,
|
|
254
254
|
]);
|
|
255
|
-
this
|
|
255
|
+
this._logger.debug("서버가 시작되었습니다.");
|
|
256
256
|
return { worker, port };
|
|
257
257
|
}
|
|
258
258
|
}
|
|
@@ -2,7 +2,8 @@ import { SdLogger, TNormPath } from "@simplysm/sd-core-node";
|
|
|
2
2
|
import { SdBuildRunnerBase } from "../SdBuildRunnerBase";
|
|
3
3
|
import { ISdBuildResult } from "../../types/build/ISdBuildResult";
|
|
4
4
|
export declare class SdClientBuildRunner extends SdBuildRunnerBase<"client"> {
|
|
5
|
-
#private;
|
|
6
5
|
protected _logger: SdLogger;
|
|
6
|
+
private _ngBundlers?;
|
|
7
|
+
private _cordova?;
|
|
7
8
|
protected _runAsync(modifiedFileSet?: Set<TNormPath>): Promise<ISdBuildResult>;
|
|
8
9
|
}
|
|
@@ -10,8 +10,6 @@ export class SdClientBuildRunner extends SdBuildRunnerBase {
|
|
|
10
10
|
super(...arguments);
|
|
11
11
|
this._logger = SdLogger.get(["simplysm", "sd-cli", "SdClientBuildRunner"]);
|
|
12
12
|
}
|
|
13
|
-
#ngBundlers;
|
|
14
|
-
#cordova;
|
|
15
13
|
async _runAsync(modifiedFileSet) {
|
|
16
14
|
// 최초 한번
|
|
17
15
|
if (!modifiedFileSet) {
|
|
@@ -23,11 +21,11 @@ export class SdClientBuildRunner extends SdBuildRunnerBase {
|
|
|
23
21
|
// cordova
|
|
24
22
|
if (this._pkgConf.builder?.cordova) {
|
|
25
23
|
this._debug("Preparing Cordova...");
|
|
26
|
-
this
|
|
24
|
+
this._cordova = new SdCliCordova({
|
|
27
25
|
pkgPath: this._opt.pkgPath,
|
|
28
26
|
config: this._pkgConf.builder.cordova,
|
|
29
27
|
});
|
|
30
|
-
await this
|
|
28
|
+
await this._cordova.initializeAsync();
|
|
31
29
|
}
|
|
32
30
|
// routes
|
|
33
31
|
const npmConf = (await FsUtils.readJsonAsync(path.resolve(this._opt.pkgPath, "package.json")));
|
|
@@ -45,20 +43,20 @@ export class SdClientBuildRunner extends SdBuildRunnerBase {
|
|
|
45
43
|
// ng
|
|
46
44
|
this._debug(`Preparing build...`);
|
|
47
45
|
const builderTypes = Object.keys(this._pkgConf.builder ?? { web: {} });
|
|
48
|
-
this
|
|
46
|
+
this._ngBundlers = builderTypes.map((builderType) => new SdNgBundler(this._opt, {
|
|
49
47
|
builderType: builderType,
|
|
50
48
|
builderConfig: this._pkgConf.builder?.[builderType],
|
|
51
49
|
env: this._pkgConf.env,
|
|
52
50
|
}));
|
|
53
51
|
}
|
|
54
52
|
if (modifiedFileSet) {
|
|
55
|
-
for (const ngBundler of this
|
|
53
|
+
for (const ngBundler of this._ngBundlers) {
|
|
56
54
|
ngBundler.markForChanges(Array.from(modifiedFileSet));
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
if (this._opt.watch?.noEmit) {
|
|
60
58
|
this._debug(`Building...`);
|
|
61
|
-
const buildResults = await Promise.all(this
|
|
59
|
+
const buildResults = await Promise.all(this._ngBundlers.map((builder) => builder.bundleAsync()));
|
|
62
60
|
const watchFileSet = new Set(buildResults.mapMany((item) => Array.from(item.watchFileSet)));
|
|
63
61
|
const affectedFileSet = new Set(buildResults.mapMany((item) => Array.from(item.affectedFileSet)));
|
|
64
62
|
const emitFileSet = new Set(buildResults.mapMany((item) => Array.from(item.emitFileSet)));
|
|
@@ -73,14 +71,14 @@ export class SdClientBuildRunner extends SdBuildRunnerBase {
|
|
|
73
71
|
}
|
|
74
72
|
else {
|
|
75
73
|
this._debug(`Building...`);
|
|
76
|
-
const buildResults = await Promise.all(this
|
|
74
|
+
const buildResults = await Promise.all(this._ngBundlers.map((builder) => builder.bundleAsync()));
|
|
77
75
|
const watchFileSet = new Set(buildResults.mapMany((item) => Array.from(item.watchFileSet)));
|
|
78
76
|
const affectedFileSet = new Set(buildResults.mapMany((item) => Array.from(item.affectedFileSet)));
|
|
79
77
|
const emitFileSet = new Set(buildResults.mapMany((item) => Array.from(item.emitFileSet)));
|
|
80
78
|
const buildMessages = buildResults.mapMany((item) => item.buildMessages).distinct();
|
|
81
|
-
if (!this._opt.watch?.dev && this
|
|
79
|
+
if (!this._opt.watch?.dev && this._cordova) {
|
|
82
80
|
this._debug("Building Cordova...");
|
|
83
|
-
await this
|
|
81
|
+
await this._cordova.buildAsync(path.resolve(this._opt.pkgPath, "dist"));
|
|
84
82
|
}
|
|
85
83
|
if (!this._opt.watch?.dev && this._pkgConf.builder?.electron) {
|
|
86
84
|
this._debug("Bulding Electron...");
|
|
@@ -2,12 +2,33 @@ import { ISdClientPackageConfig } from "../../types/config/ISdProjectConfig";
|
|
|
2
2
|
import { ISdBuildResult } from "../../types/build/ISdBuildResult";
|
|
3
3
|
import { ISdTsCompilerOptions } from "../../types/build/ISdTsCompilerOptions";
|
|
4
4
|
export declare class SdNgBundler {
|
|
5
|
-
#private;
|
|
6
5
|
private readonly _opt;
|
|
7
6
|
private readonly _conf;
|
|
7
|
+
private readonly _logger;
|
|
8
|
+
private readonly _modifiedFileSet;
|
|
9
|
+
private readonly _ngResultCache;
|
|
10
|
+
private readonly _styleLoadResultCache;
|
|
11
|
+
private _contexts;
|
|
12
|
+
private readonly _outputHashCache;
|
|
13
|
+
private readonly _pkgNpmConf;
|
|
14
|
+
private readonly _mainFilePath;
|
|
15
|
+
private readonly _tsConfigFilePath;
|
|
16
|
+
private readonly _swConfFilePath;
|
|
17
|
+
private readonly _browserTarget;
|
|
18
|
+
private readonly _indexHtmlFilePath;
|
|
19
|
+
private readonly _pkgName;
|
|
20
|
+
private readonly _baseHref;
|
|
21
|
+
private readonly _outputPath;
|
|
8
22
|
constructor(_opt: ISdTsCompilerOptions, _conf: IConf<any>);
|
|
9
23
|
markForChanges(filePaths: string[]): void;
|
|
10
24
|
bundleAsync(): Promise<ISdBuildResult>;
|
|
25
|
+
private _genIndexHtmlAsync;
|
|
26
|
+
private _copyAssetsAsync;
|
|
27
|
+
private _genServiceWorkerAsync;
|
|
28
|
+
private _getAppContext;
|
|
29
|
+
private _getStyleContext;
|
|
30
|
+
private _getElectronMainContext;
|
|
31
|
+
private _debug;
|
|
11
32
|
}
|
|
12
33
|
interface IConf<T extends keyof NonNullable<ISdClientPackageConfig["builder"]>> {
|
|
13
34
|
builderType: T;
|
|
@@ -23,41 +23,31 @@ import { SdCliPerformanceTimer } from "../../utils/SdCliPerformanceTimer";
|
|
|
23
23
|
import nodeModule from "module";
|
|
24
24
|
import { SdWorkerPathPlugin } from "../commons/SdWorkerPathPlugin";
|
|
25
25
|
export class SdNgBundler {
|
|
26
|
-
#logger = SdLogger.get(["simplysm", "sd-cli", "SdNgBundler"]);
|
|
27
|
-
#modifiedFileSet = new Set();
|
|
28
|
-
#ngResultCache = {
|
|
29
|
-
affectedFileSet: new Set(),
|
|
30
|
-
watchFileSet: new Set(),
|
|
31
|
-
};
|
|
32
|
-
#styleLoadResultCache = new MemoryLoadResultCache();
|
|
33
|
-
#contexts;
|
|
34
|
-
#outputHashCache = new Map();
|
|
35
|
-
#pkgNpmConf;
|
|
36
|
-
#mainFilePath;
|
|
37
|
-
#tsConfigFilePath;
|
|
38
|
-
#swConfFilePath;
|
|
39
|
-
#browserTarget;
|
|
40
|
-
#indexHtmlFilePath;
|
|
41
|
-
#pkgName;
|
|
42
|
-
#baseHref;
|
|
43
|
-
#outputPath;
|
|
44
26
|
constructor(_opt, _conf) {
|
|
45
27
|
this._opt = _opt;
|
|
46
28
|
this._conf = _conf;
|
|
47
|
-
this
|
|
48
|
-
this
|
|
49
|
-
this
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this
|
|
54
|
-
this
|
|
29
|
+
this._logger = SdLogger.get(["simplysm", "sd-cli", "SdNgBundler"]);
|
|
30
|
+
this._modifiedFileSet = new Set();
|
|
31
|
+
this._ngResultCache = {
|
|
32
|
+
affectedFileSet: new Set(),
|
|
33
|
+
watchFileSet: new Set(),
|
|
34
|
+
};
|
|
35
|
+
this._styleLoadResultCache = new MemoryLoadResultCache();
|
|
36
|
+
this._outputHashCache = new Map();
|
|
37
|
+
this._pkgNpmConf = FsUtils.readJson(path.resolve(this._opt.pkgPath, "package.json"));
|
|
38
|
+
this._mainFilePath = path.resolve(this._opt.pkgPath, "src/main.ts");
|
|
39
|
+
this._tsConfigFilePath = path.resolve(this._opt.pkgPath, "tsconfig.json");
|
|
40
|
+
this._swConfFilePath = path.resolve(this._opt.pkgPath, "ngsw-config.json");
|
|
41
|
+
this._browserTarget = transformSupportedBrowsersToTargets(browserslist(["Chrome > 78"]));
|
|
42
|
+
this._indexHtmlFilePath = path.resolve(this._opt.pkgPath, "src/index.html");
|
|
43
|
+
this._pkgName = path.basename(this._opt.pkgPath);
|
|
44
|
+
this._baseHref =
|
|
55
45
|
this._conf.builderType === "web"
|
|
56
|
-
? `/${this
|
|
46
|
+
? `/${this._pkgName}/`
|
|
57
47
|
: this._opt.watch?.dev
|
|
58
|
-
? `/${this
|
|
48
|
+
? `/${this._pkgName}/${this._conf.builderType}/`
|
|
59
49
|
: ``;
|
|
60
|
-
this
|
|
50
|
+
this._outputPath =
|
|
61
51
|
this._conf.builderType === "web"
|
|
62
52
|
? PathUtils.norm(this._opt.pkgPath, "dist")
|
|
63
53
|
: this._conf.builderType === "electron" && !this._opt.watch?.dev
|
|
@@ -68,8 +58,8 @@ export class SdNgBundler {
|
|
|
68
58
|
}
|
|
69
59
|
markForChanges(filePaths) {
|
|
70
60
|
for (const filePath of filePaths) {
|
|
71
|
-
this
|
|
72
|
-
this
|
|
61
|
+
this._modifiedFileSet.add(PathUtils.norm(filePath));
|
|
62
|
+
this._styleLoadResultCache.invalidate(PathUtils.norm(filePath));
|
|
73
63
|
/*if (this.#styleLoadResultCache.invalidate(PathUtils.norm(filePath))) {
|
|
74
64
|
this.#styleLoadResultCache.invalidate(PathUtils.norm(this._opt.pkgPath, "src/styles.scss"));
|
|
75
65
|
}*/
|
|
@@ -78,32 +68,32 @@ export class SdNgBundler {
|
|
|
78
68
|
}
|
|
79
69
|
async bundleAsync() {
|
|
80
70
|
const perf = new SdCliPerformanceTimer("ng bundle");
|
|
81
|
-
this
|
|
82
|
-
if (!this
|
|
83
|
-
this
|
|
84
|
-
this
|
|
71
|
+
this._debug(`Preparing build contexts...`);
|
|
72
|
+
if (!this._contexts) {
|
|
73
|
+
this._contexts = perf.run("Preparing build contexts", () => [
|
|
74
|
+
this._getAppContext(),
|
|
85
75
|
...(FsUtils.exists(path.resolve(this._opt.pkgPath, "src/styles.scss"))
|
|
86
|
-
? [this
|
|
76
|
+
? [this._getStyleContext()]
|
|
87
77
|
: []),
|
|
88
|
-
...(this._conf.builderType === "electron" ? [this
|
|
78
|
+
...(this._conf.builderType === "electron" ? [this._getElectronMainContext()] : []),
|
|
89
79
|
]);
|
|
90
80
|
}
|
|
91
|
-
this
|
|
81
|
+
this._debug("Bundling...");
|
|
92
82
|
const bundlingResults = await perf.run("Bundling", async () => {
|
|
93
|
-
return await this
|
|
83
|
+
return await this._contexts.parallelAsync(async (ctx) => await ctx.bundleAsync());
|
|
94
84
|
});
|
|
95
85
|
//-- results
|
|
96
86
|
const buildMessages = bundlingResults.mapMany((bundlingResult) => bundlingResult.results);
|
|
97
87
|
if (this._opt.watch?.noEmit) {
|
|
98
88
|
return {
|
|
99
|
-
watchFileSet: this
|
|
100
|
-
affectedFileSet: this
|
|
89
|
+
watchFileSet: this._ngResultCache.watchFileSet,
|
|
90
|
+
affectedFileSet: this._ngResultCache.affectedFileSet,
|
|
101
91
|
buildMessages,
|
|
102
92
|
emitFileSet: new Set(),
|
|
103
93
|
};
|
|
104
94
|
}
|
|
105
95
|
else {
|
|
106
|
-
this
|
|
96
|
+
this._debug(`Converting build results...`);
|
|
107
97
|
const outputFiles = bundlingResults.mapMany((item) => item.outputFiles?.map((file) => convertOutputFile(file, BuildOutputFileType.Root)) ?? []);
|
|
108
98
|
const initialFiles = new Map();
|
|
109
99
|
const metafile = {
|
|
@@ -119,9 +109,9 @@ export class SdNgBundler {
|
|
|
119
109
|
/*if (this._opt.builderType === "cordova" && this._opt.cordovaConfig?.plugins) {
|
|
120
110
|
outputFiles.push(createOutputFile("cordova-empty.js", "export default {};", BuildOutputFileType.Root));
|
|
121
111
|
}*/
|
|
122
|
-
this
|
|
112
|
+
this._debug(`Generating index.html...`);
|
|
123
113
|
await perf.run("Generating index.html", async () => {
|
|
124
|
-
const genIndexHtmlResult = await this
|
|
114
|
+
const genIndexHtmlResult = await this._genIndexHtmlAsync(outputFiles, initialFiles);
|
|
125
115
|
for (const warning of genIndexHtmlResult.warnings) {
|
|
126
116
|
buildMessages.push({
|
|
127
117
|
filePath: undefined,
|
|
@@ -146,22 +136,22 @@ export class SdNgBundler {
|
|
|
146
136
|
}
|
|
147
137
|
outputFiles.push(createOutputFile("index.html", genIndexHtmlResult.csrContent, BuildOutputFileType.Root));
|
|
148
138
|
});
|
|
149
|
-
this
|
|
139
|
+
this._debug(`Processing assets...`);
|
|
150
140
|
const assetFiles = [];
|
|
151
141
|
await perf.run("Processing assets", async () => {
|
|
152
142
|
//-- copy assets
|
|
153
|
-
assetFiles.push(...(await this
|
|
143
|
+
assetFiles.push(...(await this._copyAssetsAsync()));
|
|
154
144
|
//-- extract 3rdpartylicenses
|
|
155
145
|
if (!this._opt.watch?.dev) {
|
|
156
146
|
outputFiles.push(createOutputFile("3rdpartylicenses.txt", await extractLicenses(metafile, this._opt.pkgPath), BuildOutputFileType.Root));
|
|
157
147
|
}
|
|
158
148
|
});
|
|
159
149
|
//-- service worker
|
|
160
|
-
if (FsUtils.exists(this
|
|
161
|
-
this
|
|
150
|
+
if (FsUtils.exists(this._swConfFilePath) && !this._opt.watch?.dev) {
|
|
151
|
+
this._debug(`Preparing service worker...`);
|
|
162
152
|
await perf.run("Preparing service worker", async () => {
|
|
163
153
|
try {
|
|
164
|
-
const serviceWorkerResult = await this
|
|
154
|
+
const serviceWorkerResult = await this._genServiceWorkerAsync(outputFiles, assetFiles);
|
|
165
155
|
outputFiles.push(createOutputFile("ngsw.json", serviceWorkerResult.manifest, BuildOutputFileType.Root));
|
|
166
156
|
assetFiles.push(...serviceWorkerResult.assetFiles);
|
|
167
157
|
}
|
|
@@ -179,28 +169,28 @@ export class SdNgBundler {
|
|
|
179
169
|
});
|
|
180
170
|
}
|
|
181
171
|
//-- write
|
|
182
|
-
this
|
|
172
|
+
this._debug(`Writing output files...(${outputFiles.length})`);
|
|
183
173
|
const emitFileSet = new Set();
|
|
184
174
|
await perf.run("Writing output file", async () => {
|
|
185
175
|
const allOutputFiles = outputFiles
|
|
186
176
|
.map((item) => ({
|
|
187
|
-
path: PathUtils.norm(this
|
|
177
|
+
path: PathUtils.norm(this._outputPath, item.path),
|
|
188
178
|
contents: item.contents,
|
|
189
179
|
hash: item.hash,
|
|
190
180
|
}))
|
|
191
181
|
.concat(await assetFiles.parallelAsync(async (item) => {
|
|
192
182
|
const contents = await FsUtils.readFileBufferAsync(item.source);
|
|
193
183
|
return {
|
|
194
|
-
path: PathUtils.norm(this
|
|
184
|
+
path: PathUtils.norm(this._outputPath, item.destination),
|
|
195
185
|
contents,
|
|
196
186
|
hash: HashUtils.get(contents),
|
|
197
187
|
};
|
|
198
188
|
}));
|
|
199
189
|
for (const outputFile of allOutputFiles) {
|
|
200
|
-
const prevHash = this
|
|
190
|
+
const prevHash = this._outputHashCache.get(outputFile.path);
|
|
201
191
|
if (prevHash !== outputFile.hash) {
|
|
202
192
|
await FsUtils.writeFileAsync(outputFile.path, outputFile.contents);
|
|
203
|
-
this
|
|
193
|
+
this._outputHashCache.set(outputFile.path, outputFile.hash);
|
|
204
194
|
emitFileSet.add(outputFile.path);
|
|
205
195
|
}
|
|
206
196
|
}
|
|
@@ -229,21 +219,21 @@ export class SdNgBundler {
|
|
|
229
219
|
}),
|
|
230
220
|
]);*/
|
|
231
221
|
});
|
|
232
|
-
this
|
|
222
|
+
this._debug(`Build performance summary:\n${perf.toString()}`);
|
|
233
223
|
return {
|
|
234
224
|
watchFileSet: new Set([
|
|
235
|
-
...this
|
|
236
|
-
...this
|
|
225
|
+
...this._ngResultCache.watchFileSet,
|
|
226
|
+
...this._styleLoadResultCache.watchFiles.map((item) => PathUtils.norm(item)),
|
|
237
227
|
...assetFiles.map((item) => PathUtils.norm(item.source)),
|
|
238
|
-
PathUtils.norm(this
|
|
228
|
+
PathUtils.norm(this._indexHtmlFilePath),
|
|
239
229
|
]),
|
|
240
|
-
affectedFileSet: this
|
|
230
|
+
affectedFileSet: this._ngResultCache.affectedFileSet,
|
|
241
231
|
buildMessages,
|
|
242
232
|
emitFileSet: emitFileSet,
|
|
243
233
|
};
|
|
244
234
|
}
|
|
245
235
|
}
|
|
246
|
-
async
|
|
236
|
+
async _genIndexHtmlAsync(outputFiles, initialFiles) {
|
|
247
237
|
const readAsset = (filePath) => {
|
|
248
238
|
const relFilePath = path.relative("/", filePath);
|
|
249
239
|
const currFile = outputFiles.find((outputFile) => outputFile.path === relFilePath);
|
|
@@ -253,7 +243,7 @@ export class SdNgBundler {
|
|
|
253
243
|
throw new Error(`Output file does not exist: ${relFilePath}`);
|
|
254
244
|
};
|
|
255
245
|
const indexHtmlGenerator = new IndexHtmlGenerator({
|
|
256
|
-
indexPath: this
|
|
246
|
+
indexPath: this._indexHtmlFilePath,
|
|
257
247
|
entrypoints: [
|
|
258
248
|
["polyfills", true],
|
|
259
249
|
["styles", false],
|
|
@@ -293,7 +283,7 @@ export class SdNgBundler {
|
|
|
293
283
|
hints.push(...modulePreloads.slice(0, 10));
|
|
294
284
|
}
|
|
295
285
|
return await indexHtmlGenerator.process({
|
|
296
|
-
baseHref: this
|
|
286
|
+
baseHref: this._baseHref,
|
|
297
287
|
lang: undefined,
|
|
298
288
|
outputPath: "/",
|
|
299
289
|
files: [...initialFiles].map(([file, record]) => ({
|
|
@@ -304,7 +294,7 @@ export class SdNgBundler {
|
|
|
304
294
|
hints,
|
|
305
295
|
});
|
|
306
296
|
}
|
|
307
|
-
async
|
|
297
|
+
async _copyAssetsAsync() {
|
|
308
298
|
return await resolveAssets([
|
|
309
299
|
{ input: "public", glob: "**/*", output: "." },
|
|
310
300
|
...(this._opt.watch?.dev ? [{ input: "public-dev", glob: "**/*", output: "." }] : []),
|
|
@@ -334,10 +324,10 @@ export class SdNgBundler {
|
|
|
334
324
|
: []),
|
|
335
325
|
], this._opt.pkgPath);
|
|
336
326
|
}
|
|
337
|
-
async
|
|
338
|
-
return await augmentAppWithServiceWorkerEsbuild(this._opt.pkgPath, this
|
|
327
|
+
async _genServiceWorkerAsync(outputFiles, assetFiles) {
|
|
328
|
+
return await augmentAppWithServiceWorkerEsbuild(this._opt.pkgPath, this._swConfFilePath, this._baseHref, "index.html", outputFiles, assetFiles);
|
|
339
329
|
}
|
|
340
|
-
|
|
330
|
+
_getAppContext() {
|
|
341
331
|
/*const workerEntries = (
|
|
342
332
|
await FsUtils.globAsync(path.resolve(this._opt.pkgPath, "src/workers/!*.ts"))
|
|
343
333
|
).toObject((p) => "workers/" + path.basename(p, path.extname(p)));*/
|
|
@@ -359,7 +349,7 @@ export class SdNgBundler {
|
|
|
359
349
|
outExtension: undefined,
|
|
360
350
|
sourcemap: !!this._opt.watch?.dev,
|
|
361
351
|
chunkNames: "[name]-[hash]",
|
|
362
|
-
tsconfig: this
|
|
352
|
+
tsconfig: this._tsConfigFilePath,
|
|
363
353
|
write: false,
|
|
364
354
|
preserveSymlinks: false,
|
|
365
355
|
define: {
|
|
@@ -368,7 +358,7 @@ export class SdNgBundler {
|
|
|
368
358
|
"global": "global",
|
|
369
359
|
"process": "process",
|
|
370
360
|
"Buffer": "Buffer",
|
|
371
|
-
"process.env.SD_VERSION": JSON.stringify(this
|
|
361
|
+
"process.env.SD_VERSION": JSON.stringify(this._pkgNpmConf.version),
|
|
372
362
|
"process.env.NODE_ENV": JSON.stringify(this._opt.watch?.dev ? "development" : "production"),
|
|
373
363
|
...(this._conf.env
|
|
374
364
|
? Object.keys(this._conf.env).toObject((key) => `process.env.${key}`, (key) => JSON.stringify(this._conf.env[key]))
|
|
@@ -377,7 +367,7 @@ export class SdNgBundler {
|
|
|
377
367
|
mainFields: ["es2020", "es2015", "browser", "module", "main"],
|
|
378
368
|
entryNames: "[dir]/[name]",
|
|
379
369
|
entryPoints: {
|
|
380
|
-
main: this
|
|
370
|
+
main: this._mainFilePath,
|
|
381
371
|
...(FsUtils.exists(path.resolve(this._opt.pkgPath, "src/polyfills.ts"))
|
|
382
372
|
? {
|
|
383
373
|
polyfills: path.resolve(this._opt.pkgPath, "src/polyfills.ts"),
|
|
@@ -430,7 +420,7 @@ export class SdNgBundler {
|
|
|
430
420
|
}
|
|
431
421
|
: {
|
|
432
422
|
platform: "browser",
|
|
433
|
-
target: this
|
|
423
|
+
target: this._browserTarget,
|
|
434
424
|
format: "esm",
|
|
435
425
|
splitting: true,
|
|
436
426
|
inject: [
|
|
@@ -439,7 +429,7 @@ export class SdNgBundler {
|
|
|
439
429
|
}),
|
|
440
430
|
plugins: [
|
|
441
431
|
createSourcemapIgnorelistPlugin(),
|
|
442
|
-
createSdNgPlugin(this._opt, this
|
|
432
|
+
createSdNgPlugin(this._opt, this._modifiedFileSet, this._ngResultCache),
|
|
443
433
|
...(this._conf.builderType === "electron"
|
|
444
434
|
? []
|
|
445
435
|
: [nodeStdLibBrowserPlugin(nodeStdLibBrowser)]),
|
|
@@ -458,11 +448,11 @@ export class SdNgBundler {
|
|
|
458
448
|
],
|
|
459
449
|
});
|
|
460
450
|
}
|
|
461
|
-
|
|
451
|
+
_getStyleContext() {
|
|
462
452
|
const pluginFactory = new StylesheetPluginFactory({
|
|
463
453
|
sourcemap: !!this._opt.watch?.dev,
|
|
464
454
|
includePaths: [],
|
|
465
|
-
}, this
|
|
455
|
+
}, this._styleLoadResultCache);
|
|
466
456
|
return new SdNgBundlerContext(this._opt.pkgPath, !!this._opt.watch, {
|
|
467
457
|
absWorkingDir: this._opt.pkgPath,
|
|
468
458
|
bundle: true,
|
|
@@ -475,7 +465,7 @@ export class SdNgBundler {
|
|
|
475
465
|
outdir: this._opt.pkgPath,
|
|
476
466
|
write: false,
|
|
477
467
|
platform: "browser",
|
|
478
|
-
target: this
|
|
468
|
+
target: this._browserTarget,
|
|
479
469
|
preserveSymlinks: false,
|
|
480
470
|
external: [],
|
|
481
471
|
conditions: ["style", "sass"],
|
|
@@ -487,11 +477,11 @@ export class SdNgBundler {
|
|
|
487
477
|
plugins: [
|
|
488
478
|
pluginFactory.create(SassStylesheetLanguage),
|
|
489
479
|
pluginFactory.create(CssStylesheetLanguage),
|
|
490
|
-
createCssResourcePlugin(this
|
|
480
|
+
createCssResourcePlugin(this._styleLoadResultCache),
|
|
491
481
|
],
|
|
492
482
|
});
|
|
493
483
|
}
|
|
494
|
-
|
|
484
|
+
_getElectronMainContext() {
|
|
495
485
|
return new SdNgBundlerContext(this._opt.pkgPath, !!this._opt.watch, {
|
|
496
486
|
absWorkingDir: this._opt.pkgPath,
|
|
497
487
|
bundle: true,
|
|
@@ -505,7 +495,7 @@ export class SdNgBundler {
|
|
|
505
495
|
minify: !this._opt.watch?.dev,
|
|
506
496
|
outdir: this._opt.pkgPath,
|
|
507
497
|
sourcemap: !!this._opt.watch?.dev,
|
|
508
|
-
tsconfig: this
|
|
498
|
+
tsconfig: this._tsConfigFilePath,
|
|
509
499
|
write: false,
|
|
510
500
|
preserveSymlinks: false,
|
|
511
501
|
external: [
|
|
@@ -515,7 +505,7 @@ export class SdNgBundler {
|
|
|
515
505
|
],
|
|
516
506
|
define: {
|
|
517
507
|
...(!this._opt.watch?.dev ? { ngDevMode: "false" } : {}),
|
|
518
|
-
"process.env.SD_VERSION": JSON.stringify(this
|
|
508
|
+
"process.env.SD_VERSION": JSON.stringify(this._pkgNpmConf.version),
|
|
519
509
|
"process.env.NODE_ENV": JSON.stringify(this._opt.watch?.dev ? "development" : "production"),
|
|
520
510
|
...(this._conf.env
|
|
521
511
|
? Object.keys(this._conf.env).toObject((key) => `process.env.${key}`, (key) => JSON.stringify(this._conf.env[key]))
|
|
@@ -527,7 +517,7 @@ export class SdNgBundler {
|
|
|
527
517
|
},
|
|
528
518
|
});
|
|
529
519
|
}
|
|
530
|
-
|
|
531
|
-
this
|
|
520
|
+
_debug(...msg) {
|
|
521
|
+
this._logger.debug(`[${path.basename(this._opt.pkgPath)}]`, ...msg);
|
|
532
522
|
}
|
|
533
523
|
}
|