@simplysm/sd-cli 12.5.22 → 12.5.24

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.
Files changed (77) hide show
  1. package/dist/entry/SdCliCordova.js +2 -2
  2. package/dist/entry/SdCliCordova.js.map +1 -1
  3. package/dist/entry/SdCliElectron.js +2 -2
  4. package/dist/entry/SdCliElectron.js.map +1 -1
  5. package/dist/entry/SdCliLocalUpdate.js +6 -8
  6. package/dist/entry/SdCliLocalUpdate.js.map +1 -1
  7. package/dist/entry/SdCliProject.js +4 -4
  8. package/dist/entry/SdCliProject.js.map +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/pkg-builders/SdMultiBuildRunner.d.ts +3 -10
  13. package/dist/pkg-builders/SdMultiBuildRunner.js +133 -117
  14. package/dist/pkg-builders/SdMultiBuildRunner.js.map +1 -1
  15. package/dist/pkg-builders/client/SdCliNgRoutesFileGenerator.js +1 -1
  16. package/dist/pkg-builders/client/SdCliNgRoutesFileGenerator.js.map +1 -1
  17. package/dist/pkg-builders/client/SdClientBuildRunner.d.ts +6 -5
  18. package/dist/pkg-builders/client/SdClientBuildRunner.js +16 -8
  19. package/dist/pkg-builders/client/SdClientBuildRunner.js.map +1 -1
  20. package/dist/pkg-builders/client/SdNgBundler.js +13 -61
  21. package/dist/pkg-builders/client/SdNgBundler.js.map +1 -1
  22. package/dist/pkg-builders/client/createSdNgPlugin.js +3 -3
  23. package/dist/pkg-builders/client/createSdNgPlugin.js.map +1 -1
  24. package/dist/pkg-builders/lib/SdCliIndexFileGenerator.js +1 -1
  25. package/dist/pkg-builders/lib/SdCliIndexFileGenerator.js.map +1 -1
  26. package/dist/pkg-builders/lib/SdJsLibBuildRunner.js +1 -1
  27. package/dist/pkg-builders/lib/SdTsLibBuildRunner.d.ts +6 -1
  28. package/dist/pkg-builders/lib/SdTsLibBuildRunner.js +27 -28
  29. package/dist/pkg-builders/lib/SdTsLibBuildRunner.js.map +1 -1
  30. package/dist/pkg-builders/lib/SdTsLibBuilder.d.ts +3 -4
  31. package/dist/pkg-builders/lib/SdTsLibBuilder.js +7 -11
  32. package/dist/pkg-builders/lib/SdTsLibBuilder.js.map +1 -1
  33. package/dist/pkg-builders/server/SdServerBuildRunner.d.ts +5 -1
  34. package/dist/pkg-builders/server/SdServerBuildRunner.js +32 -29
  35. package/dist/pkg-builders/server/SdServerBuildRunner.js.map +1 -1
  36. package/dist/pkg-builders/server/createSdServerPlugin.js +3 -3
  37. package/dist/pkg-builders/server/createSdServerPlugin.js.map +1 -1
  38. package/dist/ts-builder/SdTsCompiler.d.ts +1 -1
  39. package/dist/ts-builder/SdTsCompiler.js +222 -201
  40. package/dist/ts-builder/SdTsCompiler.js.map +1 -1
  41. package/dist/types/build-runner.type.d.ts +7 -0
  42. package/dist/types/build-runner.type.js +2 -0
  43. package/dist/types/build-runner.type.js.map +1 -0
  44. package/dist/types/workers.type.d.ts +15 -1
  45. package/dist/workers/build-runner-worker.js +45 -0
  46. package/dist/workers/build-runner-worker.js.map +1 -0
  47. package/package.json +6 -6
  48. package/src/entry/SdCliCordova.ts +2 -2
  49. package/src/entry/SdCliElectron.ts +2 -2
  50. package/src/entry/SdCliLocalUpdate.ts +8 -8
  51. package/src/entry/SdCliProject.ts +4 -4
  52. package/src/index.ts +1 -1
  53. package/src/pkg-builders/SdMultiBuildRunner.ts +123 -121
  54. package/src/pkg-builders/client/SdCliNgRoutesFileGenerator.ts +1 -1
  55. package/src/pkg-builders/client/SdClientBuildRunner.ts +26 -22
  56. package/src/pkg-builders/client/SdNgBundler.ts +16 -74
  57. package/src/pkg-builders/client/createSdNgPlugin.ts +3 -3
  58. package/src/pkg-builders/lib/SdCliIndexFileGenerator.ts +1 -1
  59. package/src/pkg-builders/lib/SdJsLibBuildRunner.ts +1 -1
  60. package/src/pkg-builders/lib/SdTsLibBuildRunner.ts +42 -29
  61. package/src/pkg-builders/lib/SdTsLibBuilder.ts +13 -14
  62. package/src/pkg-builders/server/SdServerBuildRunner.ts +44 -29
  63. package/src/pkg-builders/server/createSdServerPlugin.ts +3 -3
  64. package/src/ts-builder/SdTsCompiler.ts +282 -261
  65. package/src/types/build-runner.type.ts +8 -0
  66. package/src/types/workers.type.ts +14 -1
  67. package/src/workers/build-runner-worker.ts +52 -0
  68. package/tsconfig.json +1 -1
  69. package/dist/ts-builder/SdTsCompileWorker.d.ts +0 -9
  70. package/dist/ts-builder/SdTsCompileWorker.js +0 -16
  71. package/dist/ts-builder/SdTsCompileWorker.js.map +0 -1
  72. package/dist/workers/compile-worker.js +0 -27
  73. package/dist/workers/compile-worker.js.map +0 -1
  74. package/lib/dev-worker.cjs +0 -5
  75. package/src/ts-builder/SdTsCompileWorker.ts +0 -21
  76. package/src/workers/compile-worker.ts +0 -31
  77. /package/dist/workers/{compile-worker.d.ts → build-runner-worker.d.ts} +0 -0
@@ -1,14 +1,11 @@
1
1
  import { FsUtil, Logger, PathUtil, SdWorker, TNormPath } from "@simplysm/sd-core-node";
2
2
  import path from "path";
3
3
  import { EventEmitter } from "events";
4
- import { SdServerBuildRunner } from "./server/SdServerBuildRunner";
5
- import { SdClientBuildRunner } from "./client/SdClientBuildRunner";
6
- import { SdTsLibBuildRunner } from "./lib/SdTsLibBuildRunner";
7
- import { SdJsLibBuildRunner } from "./lib/SdJsLibBuildRunner";
8
- import { ISdProjectConfig, ISdServerPackageConfig } from "../types/sd-configs.type";
4
+ import { ISdServerPackageConfig } from "../types/sd-configs.type";
9
5
  import { ISdBuildMessage, ISdBuildRunnerResult } from "../types/build.type";
10
- import { TServerWorkerType } from "../types/workers.type";
6
+ import { TSdBuildRunnerWorkerType, TServerWorkerType } from "../types/workers.type";
11
7
  import { INpmConfig } from "../types/common-configs.type";
8
+ import { ISdBuildRunnerWorkerRequest } from "../types/build-runner.type";
12
9
 
13
10
  export class SdMultiBuildRunner extends EventEmitter {
14
11
  #logger = Logger.get(["simplysm", "sd-cli", "SdMultiBuildRunner"]);
@@ -43,10 +40,20 @@ export class SdMultiBuildRunner extends EventEmitter {
43
40
  return this;
44
41
  }
45
42
 
46
- async runAsync(req: IRequest & { cmd: "watch" }): Promise<void>;
47
- async runAsync(req: IRequest & { cmd: "build" }): Promise<ISdBuildMessage[]>;
48
- async runAsync(req: IRequest): Promise<ISdBuildMessage[] | void> {
49
- const pkgConf = req.projConf.packages[path.basename(req.pkgPath)]!;
43
+ async runAsync(req: ISdBuildRunnerWorkerRequest & { cmd: "watch" }): Promise<void>;
44
+ async runAsync(req: ISdBuildRunnerWorkerRequest & { cmd: "build" }): Promise<ISdBuildMessage[]>;
45
+ async runAsync(req: ISdBuildRunnerWorkerRequest): Promise<ISdBuildMessage[] | void> {
46
+ const worker = new SdWorker<TSdBuildRunnerWorkerType>(import.meta.resolve("../workers/build-runner-worker"))
47
+ .on("change", () => {
48
+ if (this.#busyCount === 0) {
49
+ this.emit("change");
50
+ }
51
+ this.#busyCount++;
52
+ })
53
+ .on("complete", (result) => this.#onComplete(req, result));
54
+
55
+ return await worker.run("run", [req]);
56
+ /*const pkgConf = req.projConf.packages[path.basename(req.pkgPath)]!;
50
57
 
51
58
  const buildRunnerType =
52
59
  pkgConf.type === "server"
@@ -67,140 +74,133 @@ export class SdMultiBuildRunner extends EventEmitter {
67
74
  } else {
68
75
  await builder.watchAsync();
69
76
  return;
70
- }
77
+ }*/
71
78
  }
72
79
 
73
- #onMessage(req: IRequest, res: TResponse) {
74
- if (res.type === "change") {
75
- if (this.#busyCount === 0) {
76
- this.emit("change");
77
- }
78
- this.#busyCount++;
79
- } else {
80
- this.#resultCache.delete(req.pkgPath);
81
- for (const affectedFilePath of res.result.affectedFilePathSet) {
82
- if (PathUtil.isChildPath(affectedFilePath, req.pkgPath)) {
83
- this.#resultCache.delete(affectedFilePath);
84
- }
80
+ #onComplete(req: ISdBuildRunnerWorkerRequest, result: ISdBuildRunnerResult) {
81
+ this.#resultCache.delete(req.pkgPath);
82
+ for (const affectedFilePath of result.affectedFilePathSet) {
83
+ if (PathUtil.isChildPath(affectedFilePath, req.pkgPath)) {
84
+ this.#resultCache.delete(affectedFilePath);
85
85
  }
86
+ }
86
87
 
87
- for (const buildMessage of res.result.buildMessages) {
88
- const cacheItem = this.#resultCache.getOrCreate(buildMessage.filePath ?? req.pkgPath, []);
89
- cacheItem.push(buildMessage);
90
- }
88
+ for (const buildMessage of result.buildMessages) {
89
+ const cacheItem = this.#resultCache.getOrCreate(buildMessage.filePath ?? req.pkgPath, []);
90
+ cacheItem.push(buildMessage);
91
+ }
92
+
93
+ const pkgConf = req.projConf.packages[path.basename(req.pkgPath)]!;
91
94
 
92
- const pkgConf = req.projConf.packages[path.basename(req.pkgPath)]!;
95
+ if (pkgConf.type === "server") {
96
+ const pkgName = path.basename(req.pkgPath);
97
+ const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
98
+ hasChanges: true,
99
+ clientChangedFileSet: new Set(),
100
+ clients: {},
101
+ });
102
+
103
+ const serverPkgConf = req.projConf.packages[pkgName] as ISdServerPackageConfig;
104
+ serverInfo.pkgInfo = {
105
+ path: req.pkgPath,
106
+ conf: serverPkgConf,
107
+ };
108
+
109
+ serverInfo.hasChanges = true;
110
+ } else if (pkgConf.type === "client") {
111
+ const pkgName = path.basename(req.pkgPath);
112
+
113
+ if (pkgConf.server !== undefined) {
114
+ const serverInfo = this.#serverInfoMap.getOrCreate(
115
+ typeof pkgConf.server === "string" ? pkgConf.server : pkgConf.server.port.toString(),
116
+ {
117
+ hasChanges: true,
118
+ clientChangedFileSet: new Set(),
119
+ clients: {},
120
+ },
121
+ );
93
122
 
94
- if (pkgConf.type === "server") {
95
- const pkgName = path.basename(req.pkgPath);
123
+ if (typeof pkgConf.server !== "string") {
124
+ serverInfo.pkgInfo = pkgConf.server;
125
+ }
126
+
127
+ serverInfo.clients[pkgName] = {
128
+ path: path.resolve(req.pkgPath, "dist"),
129
+ buildTypes: (pkgConf.builder ? Object.keys(pkgConf.builder) : ["web"]) as any,
130
+ };
131
+
132
+ serverInfo.clientChangedFileSet.adds(...result.emitFileSet);
133
+ } else {
96
134
  const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
97
135
  hasChanges: true,
98
136
  clientChangedFileSet: new Set(),
99
137
  clients: {},
100
138
  });
101
139
 
102
- const serverPkgConf = req.projConf.packages[pkgName] as ISdServerPackageConfig;
103
- serverInfo.pkgInfo = {
104
- path: req.pkgPath,
105
- conf: serverPkgConf,
106
- };
107
-
108
- serverInfo.hasChanges = true;
109
- } else if (pkgConf.type === "client") {
110
- const pkgName = path.basename(req.pkgPath);
111
-
112
- if (pkgConf.server !== undefined) {
113
- const serverInfo = this.#serverInfoMap.getOrCreate(
114
- typeof pkgConf.server === "string" ? pkgConf.server : pkgConf.server.port.toString(),
115
- {
116
- hasChanges: true,
117
- clientChangedFileSet: new Set(),
118
- clients: {},
119
- },
120
- );
121
-
122
- if (typeof pkgConf.server !== "string") {
123
- serverInfo.pkgInfo = pkgConf.server;
124
- }
125
-
126
- serverInfo.clients[pkgName] = {
127
- path: path.resolve(req.pkgPath, "dist"),
128
- buildTypes: (pkgConf.builder ? Object.keys(pkgConf.builder) : ["web"]) as any,
129
- };
130
-
131
- serverInfo.clientChangedFileSet.adds(...res.result.emitFileSet);
132
- } else {
133
- const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
134
- hasChanges: true,
135
- clientChangedFileSet: new Set(),
136
- clients: {},
137
- });
138
-
139
- serverInfo.clientChangedFileSet.adds(...res.result.emitFileSet);
140
- }
140
+ serverInfo.clientChangedFileSet.adds(...result.emitFileSet);
141
141
  }
142
+ }
142
143
 
143
- setTimeout(async () => {
144
- this.#busyCount--;
145
- if (this.#busyCount === 0) {
146
- for (const serverPkgNameOrPort of this.#serverInfoMap.keys()) {
147
- const serverInfo = this.#serverInfoMap.get(serverPkgNameOrPort)!;
148
- if (serverInfo.pkgInfo && serverInfo.hasChanges) {
149
- this.#logger.debug("서버 재시작...");
150
- try {
151
- const restartServerResult = await this.#restartServerAsync(serverInfo.pkgInfo, serverInfo.worker);
152
- serverInfo.worker = restartServerResult.worker;
153
- serverInfo.port = restartServerResult.port;
154
- serverInfo.hasChanges = false;
155
- } catch (err) {
156
- this.#logger.error(err);
157
- }
144
+ setTimeout(async () => {
145
+ this.#busyCount--;
146
+ if (this.#busyCount === 0) {
147
+ for (const serverPkgNameOrPort of this.#serverInfoMap.keys()) {
148
+ const serverInfo = this.#serverInfoMap.get(serverPkgNameOrPort)!;
149
+ if (serverInfo.pkgInfo && serverInfo.hasChanges) {
150
+ this.#logger.debug("서버 재시작...");
151
+ try {
152
+ const restartServerResult = await this.#restartServerAsync(serverInfo.pkgInfo, serverInfo.worker);
153
+ serverInfo.worker = restartServerResult.worker;
154
+ serverInfo.port = restartServerResult.port;
155
+ serverInfo.hasChanges = false;
156
+ } catch (err) {
157
+ this.#logger.error(err);
158
158
  }
159
+ }
159
160
 
160
- if (serverInfo.worker) {
161
- this.#logger.debug("클라이언트 설정...");
162
- await serverInfo.worker.run("setPathProxy", [
163
- {
164
- ...Object.keys(serverInfo.clients).toObject(
165
- (key) => key,
166
- (key) => serverInfo.clients[key].path,
167
- ),
168
- node_modules: path.resolve(process.cwd(), "node_modules"),
169
- },
170
- ]);
171
-
172
- if (serverInfo.clientChangedFileSet.size > 0) {
173
- this.#logger.debug("클라이언트 새로고침...");
174
- await serverInfo.worker.run("broadcastReload", [serverInfo.clientChangedFileSet]);
175
- }
161
+ if (serverInfo.worker) {
162
+ this.#logger.debug("클라이언트 설정...");
163
+ await serverInfo.worker.run("setPathProxy", [
164
+ {
165
+ ...Object.keys(serverInfo.clients).toObject(
166
+ (key) => key,
167
+ (key) => serverInfo.clients[key].path,
168
+ ),
169
+ node_modules: path.resolve(process.cwd(), "node_modules"),
170
+ },
171
+ ]);
172
+
173
+ if (serverInfo.clientChangedFileSet.size > 0) {
174
+ this.#logger.debug("클라이언트 새로고침...");
175
+ await serverInfo.worker.run("broadcastReload", [serverInfo.clientChangedFileSet]);
176
176
  }
177
177
  }
178
+ }
178
179
 
179
- const clientPaths: string[] = [];
180
- for (const serverInfo of this.#serverInfoMap.values()) {
181
- if (Object.keys(serverInfo.clients).length > 0) {
182
- for (const clientPkgName of Object.keys(serverInfo.clients)) {
183
- for (const buildType of serverInfo.clients[clientPkgName].buildTypes) {
184
- if (buildType === "web") {
185
- clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/`);
186
- } else {
187
- clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/${buildType}/`);
188
- }
180
+ const clientPaths: string[] = [];
181
+ for (const serverInfo of this.#serverInfoMap.values()) {
182
+ if (Object.keys(serverInfo.clients).length > 0) {
183
+ for (const clientPkgName of Object.keys(serverInfo.clients)) {
184
+ for (const buildType of serverInfo.clients[clientPkgName].buildTypes) {
185
+ if (buildType === "web") {
186
+ clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/`);
187
+ } else {
188
+ clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/${buildType}/`);
189
189
  }
190
190
  }
191
- } else {
192
- clientPaths.push(`http://localhost:${serverInfo.port}/`);
193
191
  }
192
+ } else {
193
+ clientPaths.push(`http://localhost:${serverInfo.port}/`);
194
194
  }
195
- if (clientPaths.length > 0) {
196
- this.#logger.info("클라이언트 개발 서버 접속 주소\n" + clientPaths.join("\n"));
197
- }
198
-
199
- const messages = Array.from(this.#resultCache.values()).mapMany();
200
- this.emit("complete", messages);
201
195
  }
202
- }, 300);
203
- }
196
+ if (clientPaths.length > 0) {
197
+ this.#logger.info("클라이언트 개발 서버 접속 주소\n" + clientPaths.join("\n"));
198
+ }
199
+
200
+ const messages = Array.from(this.#resultCache.values()).mapMany();
201
+ this.emit("complete", messages);
202
+ }
203
+ }, 300);
204
204
  }
205
205
 
206
206
  async #restartServerAsync(
@@ -213,7 +213,7 @@ export class SdMultiBuildRunner extends EventEmitter {
213
213
  const logger = Logger.get(["simplysm", "sd-cli", "SdMultiBuildRunner", "#restartServerAsync"]);
214
214
 
215
215
  if (prevWorker) {
216
- prevWorker.kill();
216
+ await prevWorker.killAsync();
217
217
  }
218
218
 
219
219
  const npmConf =
@@ -234,6 +234,7 @@ export class SdMultiBuildRunner extends EventEmitter {
234
234
  }
235
235
  }
236
236
 
237
+ /*
237
238
  interface IRequest {
238
239
  cmd: "watch" | "build";
239
240
  pkgPath: TNormPath;
@@ -248,3 +249,4 @@ type TResponse =
248
249
  type: "complete";
249
250
  result: ISdBuildRunnerResult;
250
251
  };
252
+ */
@@ -7,7 +7,7 @@ export class SdCliNgRoutesFileGenerator {
7
7
  const routesFilePath = path.resolve(pkgPath, "src/routes.ts");
8
8
  let cache = FsUtil.exists(routesFilePath) ? FsUtil.readFile(routesFilePath) : undefined;
9
9
 
10
- SdFsWatcher.watch([path.resolve(pkgPath, "src")]).onChange({ delay: 100 }, () => {
10
+ SdFsWatcher.watch([path.resolve(pkgPath, "src")]).onChange({ delay: 50 }, () => {
11
11
  cache = this.run(pkgPath, cache, noLazyRoute);
12
12
  });
13
13
 
@@ -10,19 +10,27 @@ import { INpmConfig } from "../../types/common-configs.type";
10
10
  import { ISdBuildMessage, ISdBuildRunnerResult } from "../../types/build.type";
11
11
 
12
12
  export class SdClientBuildRunner extends EventEmitter {
13
- private readonly _logger = Logger.get(["simplysm", "sd-cli", "SdClientBuildRunner"]);
14
- private readonly _pkgConf: ISdClientPackageConfig;
15
- private readonly _npmConf: INpmConfig;
13
+ private _logger = Logger.get(["simplysm", "sd-cli", "SdClientBuildRunner"]);
14
+ private _pkgConf: ISdClientPackageConfig;
15
+ private _npmConf: INpmConfig;
16
16
  private _ngBundlers?: SdNgBundler[];
17
17
  private _cordova?: SdCliCordova;
18
+ private _watchScopePathSet: Set<TNormPath>;
18
19
 
19
20
  public constructor(
20
- private readonly _projConf: ISdProjectConfig,
21
- private readonly _pkgPath: TNormPath,
21
+ private _projConf: ISdProjectConfig,
22
+ private _pkgPath: TNormPath,
22
23
  ) {
23
24
  super();
24
25
  this._pkgConf = this._projConf.packages[path.basename(_pkgPath)] as ISdClientPackageConfig;
25
26
  this._npmConf = FsUtil.readJson(path.resolve(_pkgPath, "package.json")) as INpmConfig;
27
+
28
+ const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {}).mapMany((key) =>
29
+ FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)),
30
+ );
31
+ this._watchScopePathSet = new Set(
32
+ [path.resolve(this._pkgPath, "../"), ...localUpdatePaths].map((item) => PathUtil.norm(item)),
33
+ );
26
34
  }
27
35
 
28
36
  public override on(event: "change", listener: () => void): this;
@@ -77,11 +85,15 @@ export class SdClientBuildRunner extends EventEmitter {
77
85
  this.emit("complete", res);
78
86
 
79
87
  this._debug("WATCH...");
80
- const watcher = SdFsWatcher.watch(Array.from(result.watchFileSet)).onChange({ delay: 300 }, async (changeInfos) => {
88
+ let lastWatchFileSet = result.watchFileSet;
89
+ SdFsWatcher.watch(Array.from(this._watchScopePathSet)).onChange({ delay: 100 }, async (changeInfos) => {
90
+ const currentChangeInfos = changeInfos.filter((item) => lastWatchFileSet.has(item.path));
91
+ if (currentChangeInfos.length < 1) return;
92
+
81
93
  this.emit("change");
82
94
 
83
95
  for (const ngBundler of this._ngBundlers!) {
84
- ngBundler.markForChanges(changeInfos.map((item) => item.path));
96
+ ngBundler.markForChanges(currentChangeInfos.map((item) => item.path));
85
97
  }
86
98
 
87
99
  const watchResult = await this._runAsync({ dev: !this._pkgConf.forceProductionMode });
@@ -92,7 +104,7 @@ export class SdClientBuildRunner extends EventEmitter {
92
104
  };
93
105
  this.emit("complete", watchRes);
94
106
 
95
- watcher.replaceWatchPaths(watchResult.watchFileSet);
107
+ lastWatchFileSet = watchResult.watchFileSet;
96
108
  });
97
109
  }
98
110
 
@@ -102,10 +114,6 @@ export class SdClientBuildRunner extends EventEmitter {
102
114
  buildMessages: ISdBuildMessage[];
103
115
  emitFileSet: Set<TNormPath>;
104
116
  }> {
105
- const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {}).mapMany((key) =>
106
- FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)),
107
- );
108
-
109
117
  const ngBundlerBuilderTypes = Object.keys(this._pkgConf.builder ?? { web: {} }) as (
110
118
  | "web"
111
119
  | "electron"
@@ -142,9 +150,7 @@ export class SdClientBuildRunner extends EventEmitter {
142
150
  ...this._pkgConf.builder?.[ngBundlerBuilderType]?.env,
143
151
  },
144
152
  cordovaConfig: ngBundlerBuilderType === "cordova" ? this._pkgConf.builder!.cordova : undefined,
145
- watchScopePaths: [path.resolve(this._pkgPath, "../"), ...localUpdatePaths].map((item) =>
146
- PathUtil.norm(item),
147
- ),
153
+ watchScopePaths: Array.from(this._watchScopePathSet),
148
154
  }),
149
155
  );
150
156
  }
@@ -170,15 +176,13 @@ export class SdClientBuildRunner extends EventEmitter {
170
176
  }
171
177
 
172
178
  this._debug(`빌드 완료`);
173
- const currWatchFileSet = new Set(
174
- Array.from(watchFileSet).filter(
175
- (item) =>
176
- PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
177
- localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu)),
179
+ /*const currWatchFileSet = new Set(
180
+ Array.from(watchFileSet).filter((item) =>
181
+ Array.from(this._watchScopePathSet).some((scope) => PathUtil.isChildPath(item, scope)),
178
182
  ),
179
- );
183
+ );*/
180
184
  return {
181
- watchFileSet: currWatchFileSet,
185
+ watchFileSet,
182
186
  affectedFileSet,
183
187
  buildMessages: results, //.filter((item) => item.filePath !== path.resolve(this._pkgPath, "src/routes.ts")),
184
188
  emitFileSet,
@@ -18,14 +18,9 @@ import {
18
18
  InitialFileRecord,
19
19
  } from "@angular/build/src/tools/esbuild/bundler-context";
20
20
  import { extractLicenses } from "@angular/build/src/tools/esbuild/license-extractor";
21
- import {
22
- HintMode,
23
- IndexHtmlGenerator,
24
- IndexHtmlProcessResult,
25
- } from "@angular/build/src/utils/index-file/index-html-generator";
21
+ import { IndexHtmlGenerator, IndexHtmlProcessResult } from "@angular/build/src/utils/index-file/index-html-generator";
26
22
  import { Entrypoint } from "@angular/build/src/utils/index-file/augment-index-html";
27
23
  import { CrossOrigin } from "@angular/build/src/builders/application/schema";
28
- import { InlineCriticalCssProcessor } from "@angular/build/src/utils/index-file/inline-critical-css";
29
24
  import { augmentAppWithServiceWorkerEsbuild } from "@angular/build/src/utils/service-worker";
30
25
  import { createSourcemapIgnorelistPlugin } from "@angular/build/src/tools/esbuild/sourcemap-ignorelist-plugin";
31
26
  import { StylesheetPluginFactory } from "@angular/build/src/tools/esbuild/stylesheets/stylesheet-plugin-factory";
@@ -43,10 +38,6 @@ import { ISdBuildMessage } from "../../types/build.type";
43
38
  export class SdNgBundler {
44
39
  readonly #logger = Logger.get(["simplysm", "sd-cli", "SdNgBundler"]);
45
40
 
46
- // private readonly _sourceFileCache = new SourceFileCache(
47
- // path.resolve(this._opt.pkgPath, ".cache")
48
- // );
49
-
50
41
  readonly #modifiedFileSet = new Set<TNormPath>();
51
42
  readonly #ngResultCache: ISdCliNgPluginResultCache = {
52
43
  affectedFileSet: new Set<TNormPath>(),
@@ -155,7 +146,7 @@ export class SdNgBundler {
155
146
 
156
147
  this.#debug(`create index.html...`);
157
148
  await perf.run("create index.html", async () => {
158
- const genIndexHtmlResult = await this._genIndexHtmlAsync(outputFiles, initialFiles);
149
+ const genIndexHtmlResult = await this._genIndexHtmlAsync(initialFiles);
159
150
  for (const warning of genIndexHtmlResult.warnings) {
160
151
  results.push({
161
152
  filePath: undefined,
@@ -251,6 +242,7 @@ export class SdNgBundler {
251
242
  watchFileSet: new Set([
252
243
  ...this.#ngResultCache.watchFileSet!,
253
244
  ...this.#styleLoadResultCache.watchFiles.map((item) => PathUtil.norm(item)),
245
+ ...assetFiles.map((item) => PathUtil.norm(item.source)),
254
246
  PathUtil.norm(this.#indexHtmlFilePath),
255
247
  ]),
256
248
  affectedFileSet: this.#ngResultCache.affectedFileSet!,
@@ -259,60 +251,30 @@ export class SdNgBundler {
259
251
  };
260
252
  }
261
253
 
262
- private async _genIndexHtmlAsync(
263
- outputFiles: esbuild.OutputFile[],
264
- initialFiles: Map<string, InitialFileRecord>,
265
- ): Promise<IndexHtmlProcessResult> {
266
- const readAsset = (filePath: string): Promise<string> => {
267
- const relFilePath = path.relative("/", filePath);
268
- const currFile = outputFiles.find((outputFile) => outputFile.path === relFilePath);
269
- if (currFile) {
270
- return Promise.resolve(currFile.text);
271
- }
272
-
273
- throw new Error(`Output file does not exist: ${relFilePath}`);
274
- };
275
-
254
+ private async _genIndexHtmlAsync(initialFiles: Map<string, InitialFileRecord>): Promise<IndexHtmlProcessResult> {
276
255
  const indexHtmlGenerator = new IndexHtmlGenerator({
277
256
  indexPath: this.#indexHtmlFilePath,
278
257
  entrypoints: [
279
- ["runtime", true],
280
258
  ["polyfills", true],
281
259
  ["styles", false],
282
- ["vendor", true],
283
260
  ["main", true],
284
261
  ...(this._opt.builderType === "cordova" ? [["cordova-entry", true] as Entrypoint] : []),
285
262
  ],
263
+ sri: false,
286
264
  optimization: {
287
265
  scripts: !this._opt.dev,
288
- fonts: { inline: !this._opt.dev },
289
266
  styles: {
290
267
  minify: !this._opt.dev,
291
- inlineCritical: false,
268
+ inlineCritical: !this._opt.dev,
269
+ removeSpecialComments: !this._opt.dev,
292
270
  },
271
+ fonts: { inline: !this._opt.dev },
293
272
  },
294
273
  crossOrigin: CrossOrigin.None,
274
+ generateDedicatedSSRContent: false,
295
275
  });
296
- indexHtmlGenerator.readAsset = readAsset;
297
-
298
- const hints: { url: string; mode: HintMode; as?: string }[] = [];
299
- if (!this._opt.dev) {
300
- for (const [key, value] of initialFiles) {
301
- if (value.entrypoint) {
302
- continue;
303
- }
304
276
 
305
- if (value.type === "script") {
306
- hints.push({ url: key, mode: "modulepreload" as const });
307
- }
308
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
309
- else if (value.type === "style") {
310
- hints.push({ url: key, mode: "preload" as const, as: "style" });
311
- }
312
- }
313
- }
314
-
315
- const transformResult = await indexHtmlGenerator.process({
277
+ return await indexHtmlGenerator.process({
316
278
  baseHref: this.#baseHref,
317
279
  lang: undefined,
318
280
  outputPath: "/",
@@ -321,29 +283,9 @@ export class SdNgBundler {
321
283
  file,
322
284
  extension: path.extname(file),
323
285
  })),
324
- hints,
325
286
  });
326
-
327
- if (this._opt.dev) {
328
- return transformResult;
329
- } else {
330
- const inlineCriticalCssProcessor = new InlineCriticalCssProcessor({
331
- minify: false,
332
- readAsset,
333
- });
334
- const { content, errors, warnings } = await inlineCriticalCssProcessor.process(transformResult.csrContent, {
335
- outputPath: "/",
336
- });
337
-
338
- return {
339
- warnings: [...transformResult.warnings, ...warnings],
340
- errors: [...transformResult.errors, ...errors],
341
- csrContent: content,
342
- };
343
- }
344
287
  }
345
288
 
346
- //TODO: index.html 파일에 manifest.json 정보 추가? manifest.webmanifest ? PWA?
347
289
  private async _copyAssetsAsync(): Promise<
348
290
  {
349
291
  source: string;
@@ -352,11 +294,8 @@ export class SdNgBundler {
352
294
  > {
353
295
  return await resolveAssets(
354
296
  [
355
- { input: "src", glob: "favicon.ico", output: "" },
356
- { input: "src", glob: "manifest.webmanifest", output: "" },
357
- { input: "src", glob: "manifest.json", output: "" },
358
- { input: "src/assets", glob: "**/*", output: "assets" },
359
- ...(this._opt.dev ? [{ input: "src/assets-dev", glob: "**/*", output: "assets-dev" }] : []),
297
+ { input: "public", glob: "**/*", output: "." },
298
+ ...(this._opt.dev ? [{ input: "public-dev", glob: "**/*", output: "." }] : []),
360
299
  ...(this._opt.dev && this._opt.builderType === "cordova"
361
300
  ? Object.keys(this._opt.cordovaConfig?.platform ?? { browser: {} }).mapMany((platform) => [
362
301
  {
@@ -461,7 +400,10 @@ export class SdNgBundler {
461
400
  polyfills: path.resolve(this._opt.pkgPath, "src/polyfills.ts"),
462
401
  ...(this._opt.builderType === "cordova"
463
402
  ? {
464
- "cordova-entry": path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../lib/cordova-entry.js`),
403
+ "cordova-entry": path.resolve(
404
+ path.dirname(fileURLToPath(import.meta.url)),
405
+ `../../../lib/cordova-entry.js`,
406
+ ),
465
407
  }
466
408
  : {}),
467
409
  ...workerEntries,
@@ -7,7 +7,7 @@ import { SdCliPerformanceTimer } from "../../utils/SdCliPerformanceTime";
7
7
  import { SdCliConvertMessageUtil } from "../../utils/SdCliConvertMessageUtil";
8
8
  import { ISdCliNgPluginResultCache } from "../../types/build-plugin.type";
9
9
  import { ISdTsCompilerResult } from "../../types/ts-compiler.type";
10
- import { SdTsCompileWorker } from "../../ts-builder/SdTsCompileWorker";
10
+ import { SdTsCompiler } from "../../ts-builder/SdTsCompiler";
11
11
 
12
12
  export function createSdNgPlugin(conf: {
13
13
  pkgPath: TNormPath;
@@ -25,8 +25,8 @@ export function createSdNgPlugin(conf: {
25
25
 
26
26
  return {
27
27
  name: "sd-ng-compile",
28
- setup: async (build: esbuild.PluginBuild) => {
29
- const tsCompiler = await SdTsCompileWorker.new({
28
+ setup: (build: esbuild.PluginBuild) => {
29
+ const tsCompiler = new SdTsCompiler({
30
30
  pkgPath: conf.pkgPath,
31
31
  additionalOptions: { declaration: false },
32
32
  isDevMode: conf.dev,
@@ -6,7 +6,7 @@ export class SdCliIndexFileGenerator {
6
6
  const indexFilePath = path.resolve(pkgPath, "src/index.ts");
7
7
  let cache = FsUtil.exists(indexFilePath) ? FsUtil.readFile(indexFilePath) : undefined;
8
8
 
9
- SdFsWatcher.watch([path.resolve(pkgPath, "src")]).onChange({ delay: 100 }, () => {
9
+ SdFsWatcher.watch([path.resolve(pkgPath, "src")]).onChange({ delay: 50 }, () => {
10
10
  cache = this.run(pkgPath, polyfills, cache);
11
11
  });
12
12
 
@@ -71,7 +71,7 @@ export class SdJsLibBuildRunner extends EventEmitter {
71
71
  };
72
72
  this.emit("complete", res);
73
73
 
74
- SdFsWatcher.watch([srcGlobPath]).onChange({ delay: 300 }, async (changeInfos) => {
74
+ SdFsWatcher.watch([srcGlobPath]).onChange({ delay: 100 }, async (changeInfos) => {
75
75
  const watchFilePaths = changeInfos.filter((item) => FsUtil.exists(item.path)).map((item) => item.path);
76
76
  if (watchFilePaths.length < 1) return;
77
77