@simplysm/sd-cli 11.0.40 → 11.1.1

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 (51) hide show
  1. package/dist/build-cluster.d.ts +1 -1
  2. package/dist/build-cluster.js +181 -181
  3. package/dist/build-tools/SdCliCordova.d.ts +21 -21
  4. package/dist/build-tools/SdCliCordova.js +217 -217
  5. package/dist/build-tools/SdCliIndexFileGenerator.d.ts +5 -5
  6. package/dist/build-tools/SdCliIndexFileGenerator.js +50 -50
  7. package/dist/build-tools/SdCliNgRoutesFileGenerator.d.ts +4 -4
  8. package/dist/build-tools/SdCliNgRoutesFileGenerator.js +57 -57
  9. package/dist/build-tools/SdLinter.d.ts +5 -5
  10. package/dist/build-tools/SdLinter.js +54 -54
  11. package/dist/build-tools/SdNgBundler.d.ts +35 -35
  12. package/dist/build-tools/SdNgBundler.js +545 -533
  13. package/dist/build-tools/SdNgBundler.js.map +1 -1
  14. package/dist/build-tools/SdNgBundlerContext.d.ts +16 -16
  15. package/dist/build-tools/SdNgBundlerContext.js +97 -97
  16. package/dist/build-tools/SdTsBundler.d.ts +15 -15
  17. package/dist/build-tools/SdTsBundler.js +87 -87
  18. package/dist/build-tools/SdTsCompiler.d.ts +29 -29
  19. package/dist/build-tools/SdTsCompiler.js +227 -227
  20. package/dist/builders/SdCliClientBuilder.d.ts +18 -18
  21. package/dist/builders/SdCliClientBuilder.js +129 -129
  22. package/dist/builders/SdCliJsLibLinter.d.ts +14 -14
  23. package/dist/builders/SdCliJsLibLinter.js +59 -59
  24. package/dist/builders/SdCliServerBuilder.d.ts +20 -20
  25. package/dist/builders/SdCliServerBuilder.js +215 -215
  26. package/dist/builders/SdCliTsLibBuilder.d.ts +17 -17
  27. package/dist/builders/SdCliTsLibBuilder.js +79 -79
  28. package/dist/commons.d.ts +132 -132
  29. package/dist/commons.js +1 -1
  30. package/dist/entry/SdCliElectron.d.ts +12 -12
  31. package/dist/entry/SdCliElectron.js +99 -99
  32. package/dist/entry/SdCliLocalUpdate.d.ts +12 -12
  33. package/dist/entry/SdCliLocalUpdate.js +90 -90
  34. package/dist/entry/SdCliProject.d.ts +26 -26
  35. package/dist/entry/SdCliProject.js +477 -477
  36. package/dist/index.d.ts +19 -19
  37. package/dist/index.js +19 -19
  38. package/dist/sd-cli.d.ts +2 -2
  39. package/dist/sd-cli.js +210 -210
  40. package/dist/server-worker.d.ts +1 -1
  41. package/dist/server-worker.js +38 -38
  42. package/dist/utils/SdCliBuildResultUtil.d.ts +6 -6
  43. package/dist/utils/SdCliBuildResultUtil.js +37 -37
  44. package/dist/utils/SdMemoryLoadResultCache.d.ts +9 -9
  45. package/dist/utils/SdMemoryLoadResultCache.js +34 -34
  46. package/dist/utils/SdSourceFileCache.d.ts +6 -6
  47. package/dist/utils/SdSourceFileCache.js +14 -14
  48. package/dist/utils/SdSourceFileCache.js.map +1 -1
  49. package/package.json +18 -18
  50. package/src/build-tools/SdNgBundler.ts +21 -12
  51. package/src/utils/SdSourceFileCache.ts +1 -1
@@ -1,534 +1,546 @@
1
- import { createCompilerPlugin } from "@angular-devkit/build-angular/src/tools/esbuild/angular/compiler-plugin";
2
- import path from "path";
3
- import esbuild from "esbuild";
4
- import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
5
- import { fileURLToPath, pathToFileURL } from "url";
6
- import { createVirtualModulePlugin } from "@angular-devkit/build-angular/src/tools/esbuild/virtual-module-plugin";
7
- import { createSourcemapIgnorelistPlugin } from "@angular-devkit/build-angular/src/tools/esbuild/sourcemap-ignorelist-plugin";
8
- import nodeStdLibBrowser from "node-stdlib-browser";
9
- import nodeStdLibBrowserPlugin from "node-stdlib-browser/helpers/esbuild/plugin";
10
- import { copyAssets } from "@angular-devkit/build-angular/src/utils/copy-assets";
11
- import { extractLicenses } from "@angular-devkit/build-angular/src/tools/esbuild/license-extractor";
12
- import { augmentAppWithServiceWorkerEsbuild } from "@angular-devkit/build-angular/src/utils/service-worker";
13
- import browserslist from "browserslist";
14
- import { createOutputFileFromText, transformSupportedBrowsersToTargets } from "@angular-devkit/build-angular/src/tools/esbuild/utils";
15
- import { createCssResourcePlugin } from "@angular-devkit/build-angular/src/tools/esbuild/stylesheets/css-resource-plugin";
16
- import { CssStylesheetLanguage } from "@angular-devkit/build-angular/src/tools/esbuild/stylesheets/css-language";
17
- import { SassStylesheetLanguage } from "@angular-devkit/build-angular/src/tools/esbuild/stylesheets/sass-language";
18
- import { StylesheetPluginFactory } from "@angular-devkit/build-angular/src/tools/esbuild/stylesheets/stylesheet-plugin-factory";
19
- import { IndexHtmlGenerator } from "@angular-devkit/build-angular/src/utils/index-file/index-html-generator";
20
- import { CrossOrigin } from "@angular-devkit/build-angular";
21
- import { InlineCriticalCssProcessor } from "@angular-devkit/build-angular/src/utils/index-file/inline-critical-css";
22
- import { SdSourceFileCache } from "../utils/SdSourceFileCache";
23
- import { SdNgBundlerContext } from "./SdNgBundlerContext";
24
- export class SdNgBundler {
25
- constructor(_opt) {
26
- this._opt = _opt;
27
- this._sourceFileCache = new SdSourceFileCache(path.resolve(this._opt.pkgPath, ".cache"));
28
- this._outputCache = new Map();
29
- this._customDepsCache = new Map();
30
- this._pkgNpmConf = FsUtil.readJson(path.resolve(this._opt.pkgPath, "package.json"));
31
- this._mainFilePath = path.resolve(this._opt.pkgPath, "src/main.ts");
32
- this._tsConfigFilePath = path.resolve(this._opt.pkgPath, "tsconfig.json");
33
- this._swConfFilePath = path.resolve(this._opt.pkgPath, "ngsw-config.json");
34
- this._browserTarget = transformSupportedBrowsersToTargets(browserslist("defaults and fully supports es6-module"));
35
- this._indexHtmlFilePath = path.resolve(this._opt.pkgPath, "src/index.html");
36
- this._pkgName = path.basename(this._opt.pkgPath);
37
- this._baseHref = this._opt.builderType === "web" ? `/${this._pkgName}/` : this._opt.dev ? `/${this._pkgName}/${this._opt.builderType}/` : ``;
38
- }
39
- removeCache(filePaths) {
40
- for (const filePath of filePaths) {
41
- const depsSet = this._customDepsCache.get(filePath);
42
- if (depsSet) {
43
- for (const depFile of depsSet) {
44
- this._sourceFileCache.invalidate([depFile]);
45
- }
46
- }
47
- else {
48
- this._sourceFileCache.invalidate([filePath]);
49
- }
50
- }
51
- }
52
- async bundleAsync() {
53
- if (!this._contexts) {
54
- this._contexts = [];
55
- this._contexts.push(await this._getAppContextAsync());
56
- this._contexts.push(this._getStyleContext());
57
- }
58
- //-- build
59
- const bundlingResults = await this._contexts.mapAsync(async (ctx) => await ctx.bundleAsync());
60
- const results = bundlingResults.mapMany(bundlingResult => bundlingResult.results);
61
- const watchFilePaths = [
62
- ...this._sourceFileCache.keys(),
63
- ...this._sourceFileCache.babelFileCache.keys(),
64
- ...this._sourceFileCache.loadResultCache.fileDependencies.keys(),
65
- ...this._customDepsCache.keys()
66
- ].map((item) => path.resolve(item)).distinct();
67
- let affectedSourceFilePaths = watchFilePaths.filter((item) => PathUtil.isChildPath(item, this._opt.pkgPath));
68
- if (this._sourceFileCache.modifiedFiles.size > 0) {
69
- const depMap = new Map();
70
- for (const bundlingResult of bundlingResults) {
71
- for (const [k, v] of bundlingResult.dependencyMap) {
72
- const currSet = depMap.getOrCreate(k, new Set());
73
- currSet.adds(...v);
74
- }
75
- }
76
- for (const [k, v] of this._sourceFileCache.loadResultCache.fileDependencies) {
77
- const currSet = depMap.getOrCreate(k, new Set());
78
- currSet.adds(...Array.from(v).map((item) => item.startsWith("file:") ? fileURLToPath(item) : undefined).filterExists());
79
- }
80
- for (const [k, v] of this._customDepsCache) {
81
- const currSet = depMap.getOrCreate(k, new Set());
82
- currSet.adds(...v);
83
- }
84
- const searchAffectedFiles = (filePath, prev) => {
85
- const result = new Set(prev);
86
- const importerPaths = depMap.get(filePath);
87
- if (!importerPaths)
88
- return result;
89
- for (const importerPath of importerPaths) {
90
- if (result.has(importerPath))
91
- continue;
92
- result.adds(importerPath);
93
- result.adds(...searchAffectedFiles(importerPath, result));
94
- }
95
- return result;
96
- };
97
- const affectedFilePathSet = new Set();
98
- for (const modFile of this._sourceFileCache.modifiedFiles) {
99
- affectedFilePathSet.add(path.resolve(modFile));
100
- affectedFilePathSet.adds(...searchAffectedFiles(path.resolve(modFile)));
101
- }
102
- affectedSourceFilePaths = Array.from(affectedFilePathSet.values()).filter((item) => PathUtil.isChildPath(item, this._opt.pkgPath));
103
- }
104
- /*const executionResult = new ExecutionResult(this._contexts, this._sourceFileCache);
105
- executionResult.outputFiles.push(...bundlingResult.outputFiles);*/
106
- const outputFiles = bundlingResults.mapMany(item => item.outputFiles ?? []);
107
- const initialFiles = new Map();
108
- const metafile = {
109
- inputs: {},
110
- outputs: {}
111
- };
112
- for (const bundlingResult of bundlingResults) {
113
- bundlingResult.initialFiles.forEach((v, k) => initialFiles.set(k, v));
114
- metafile.inputs = { ...metafile.inputs, ...bundlingResult.metafile?.inputs };
115
- metafile.outputs = { ...metafile.outputs, ...bundlingResult.metafile?.outputs };
116
- }
117
- const assetFiles = [];
118
- //-- Check commonjs
119
- // if (!this._opt.dev) {
120
- // const messages = checkCommonJSModules(bundlingResult.metafile, []);
121
- // for (const msg of messages) {
122
- // results.push({
123
- // filePath: msg.location?.file,
124
- // line: msg.location?.line,
125
- // char: msg.location?.column,
126
- // code: msg.pluginName,
127
- // severity: "warning",
128
- // message: msg.text ?? "",
129
- // type: "build"
130
- // });
131
- // }
132
- // }
133
- //-- cordova empty
134
- if (this._opt.cordovaConfig?.plugins) {
135
- outputFiles.push(createOutputFileFromText("cordova-empty.js", "export default {};"));
136
- }
137
- //-- index
138
- const genIndexHtmlResult = await this._genIndexHtmlAsync(outputFiles, initialFiles);
139
- for (const warning of genIndexHtmlResult.warnings) {
140
- results.push({
141
- filePath: undefined,
142
- line: undefined,
143
- char: undefined,
144
- code: undefined,
145
- severity: "warning",
146
- message: `(gen-index) ${warning}`,
147
- type: "build",
148
- });
149
- }
150
- for (const error of genIndexHtmlResult.errors) {
151
- results.push({
152
- filePath: undefined,
153
- line: undefined,
154
- char: undefined,
155
- code: undefined,
156
- severity: "error",
157
- message: `(gen-index) ${error}`,
158
- type: "build",
159
- });
160
- }
161
- outputFiles.push(createOutputFileFromText("index.html", genIndexHtmlResult.content));
162
- //-- copy assets
163
- assetFiles.push(...(await this._copyAssetsAsync()));
164
- //-- extract 3rdpartylicenses
165
- if (!this._opt.dev) {
166
- outputFiles.push(createOutputFileFromText('3rdpartylicenses.txt', await extractLicenses(metafile, this._opt.pkgPath)));
167
- }
168
- //-- service worker
169
- if (FsUtil.exists(this._swConfFilePath)) {
170
- try {
171
- const serviceWorkerResult = await this._genServiceWorkerAsync(outputFiles, assetFiles);
172
- outputFiles.push(createOutputFileFromText('ngsw.json', serviceWorkerResult.manifest));
173
- assetFiles.push(...serviceWorkerResult.assetFiles);
174
- }
175
- catch (err) {
176
- results.push({
177
- filePath: undefined,
178
- line: undefined,
179
- char: undefined,
180
- code: undefined,
181
- severity: "error",
182
- message: `(gen-sw) ${err.toString()}`,
183
- type: "build",
184
- });
185
- }
186
- }
187
- //-- write
188
- for (const outputFile of outputFiles) {
189
- const distFilePath = path.resolve(this._opt.outputPath, outputFile.path);
190
- const prev = this._outputCache.get(distFilePath);
191
- if (prev !== Buffer.from(outputFile.contents).toString("base64")) {
192
- await FsUtil.writeFileAsync(distFilePath, outputFile.contents);
193
- this._outputCache.set(distFilePath, Buffer.from(outputFile.contents).toString("base64"));
194
- }
195
- }
196
- for (const assetFile of assetFiles) {
197
- const prev = this._outputCache.get(assetFile.source);
198
- const curr = FsUtil.lstat(assetFile.source).mtime.getTime();
199
- if (prev !== curr) {
200
- await FsUtil.copyAsync(assetFile.source, path.resolve(this._opt.outputPath, assetFile.destination));
201
- this._outputCache.set(assetFile.source, curr);
202
- }
203
- }
204
- return {
205
- filePaths: watchFilePaths,
206
- affectedFilePaths: affectedSourceFilePaths,
207
- results
208
- };
209
- }
210
- async _genIndexHtmlAsync(outputFiles, initialFiles) {
211
- const readAsset = (filePath) => {
212
- const relFilePath = path.relative("/", filePath);
213
- const currFile = outputFiles.find((outputFile) => outputFile.path === relFilePath);
214
- if (currFile) {
215
- return Promise.resolve(currFile.text);
216
- }
217
- throw new Error(`Output file does not exist: ${relFilePath}`);
218
- };
219
- const indexHtmlGenerator = new IndexHtmlGenerator({
220
- indexPath: this._indexHtmlFilePath,
221
- entrypoints: [
222
- ['runtime', true],
223
- ['polyfills', true],
224
- ['styles', false],
225
- ['vendor', true],
226
- ['main', true],
227
- ...this._opt.builderType === "cordova" ? [
228
- ["cordova-entry", true]
229
- ] : []
230
- ],
231
- optimization: {
232
- scripts: !this._opt.dev,
233
- fonts: { inline: !this._opt.dev },
234
- styles: {
235
- minify: !this._opt.dev,
236
- inlineCritical: false
237
- },
238
- },
239
- crossOrigin: CrossOrigin.None,
240
- });
241
- indexHtmlGenerator.readAsset = readAsset;
242
- const hints = [];
243
- if (!this._opt.dev) {
244
- for (const [key, value] of initialFiles) {
245
- if (value.entrypoint) {
246
- continue;
247
- }
248
- if (value.type === 'script') {
249
- hints.push({ url: key, mode: 'modulepreload' });
250
- }
251
- else if (value.type === 'style') {
252
- hints.push({ url: key, mode: 'preload', as: 'style' });
253
- }
254
- }
255
- }
256
- const transformResult = await indexHtmlGenerator.process({
257
- baseHref: this._baseHref,
258
- lang: undefined,
259
- outputPath: "/",
260
- files: [...initialFiles].map(([file, record]) => ({
261
- name: record.name ?? '',
262
- file,
263
- extension: path.extname(file),
264
- })),
265
- hints,
266
- });
267
- if (this._opt.dev) {
268
- return transformResult;
269
- }
270
- else {
271
- const inlineCriticalCssProcessor = new InlineCriticalCssProcessor({
272
- minify: false,
273
- readAsset,
274
- });
275
- const { content, errors, warnings } = await inlineCriticalCssProcessor.process(transformResult.content, { outputPath: "/", });
276
- return {
277
- warnings: [...transformResult.warnings, ...warnings],
278
- errors: [...transformResult.errors, ...errors],
279
- content
280
- };
281
- }
282
- }
283
- async _copyAssetsAsync() {
284
- return await copyAssets([
285
- { input: 'src', glob: 'favicon.ico', output: '' },
286
- { input: 'src', glob: 'manifest.webmanifest', output: '' },
287
- { input: 'src/assets', glob: '**/*', output: 'assets' },
288
- ...this._opt.dev && this._opt.builderType === "cordova" ? Object.keys(this._opt.cordovaConfig?.platform ?? { browser: {} }).mapMany((platform) => [
289
- {
290
- input: `.cordova/platforms/${platform}/platform_www/plugins`,
291
- glob: '**/*',
292
- output: `cordova-${platform}/plugins`
293
- },
294
- {
295
- input: `.cordova/platforms/${platform}/platform_www`,
296
- glob: 'cordova.js',
297
- output: `cordova-${platform}`
298
- },
299
- {
300
- input: `.cordova/platforms/${platform}/platform_www`,
301
- glob: 'cordova_plugins.js',
302
- output: `cordova-${platform}`
303
- },
304
- {
305
- input: `.cordova/platforms/${platform}/www`,
306
- glob: 'config.xml',
307
- output: `cordova-${platform}`
308
- },
309
- ]) : []
310
- ], [], this._opt.pkgPath);
311
- }
312
- async _genServiceWorkerAsync(outputFiles, assetFiles) {
313
- return await augmentAppWithServiceWorkerEsbuild(this._opt.pkgPath, this._swConfFilePath, this._baseHref, outputFiles, assetFiles);
314
- }
315
- async _getAppContextAsync() {
316
- return new SdNgBundlerContext(this._opt.pkgPath, {
317
- absWorkingDir: this._opt.pkgPath,
318
- bundle: true,
319
- keepNames: true,
320
- format: 'esm',
321
- assetNames: 'media/[name]',
322
- conditions: ['es2020', 'es2015', 'module'],
323
- resolveExtensions: ['.ts', '.tsx', '.mjs', '.js'],
324
- metafile: true,
325
- legalComments: this._opt.dev ? 'eof' : 'none',
326
- logLevel: 'silent',
327
- minifyIdentifiers: !this._opt.dev,
328
- minifySyntax: !this._opt.dev,
329
- minifyWhitespace: !this._opt.dev,
330
- pure: ['forwardRef'],
331
- outdir: this._opt.pkgPath,
332
- outExtension: undefined,
333
- sourcemap: this._opt.dev,
334
- splitting: true,
335
- chunkNames: 'chunk-[hash]',
336
- tsconfig: this._tsConfigFilePath,
337
- /*external: [
338
- ...this._opt.cordovaConfig?.plugins ?? []
339
- ],*/
340
- write: false,
341
- preserveSymlinks: false,
342
- define: {
343
- ...!this._opt.dev ? { ngDevMode: 'false' } : {},
344
- ngJitMode: 'false',
345
- global: 'global',
346
- process: 'process',
347
- Buffer: 'Buffer',
348
- 'process.env.SD_VERSION': JSON.stringify(this._pkgNpmConf.version),
349
- "process.env.NODE_ENV": JSON.stringify(this._opt.dev ? "development" : "production"),
350
- ...this._opt.env ? Object.keys(this._opt.env).toObject(key => `process.env.${key}`, key => JSON.stringify(this._opt.env[key])) : {}
351
- },
352
- platform: 'browser',
353
- mainFields: ['es2020', 'es2015', 'browser', 'module', 'main'],
354
- entryNames: '[name]',
355
- entryPoints: {
356
- main: this._mainFilePath,
357
- polyfills: 'angular:polyfills',
358
- ...this._opt.builderType === "cordova" ? {
359
- "cordova-entry": path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../lib/cordova-entry.js`)
360
- } : {}
361
- },
362
- target: this._browserTarget,
363
- supported: { 'async-await': false, 'object-rest-spread': false },
364
- loader: {
365
- ".png": "file",
366
- ".jpeg": "file",
367
- ".jpg": "file",
368
- ".jfif": "file",
369
- ".gif": "file",
370
- ".svg": "file",
371
- ".woff": "file",
372
- ".woff2": "file",
373
- ".ttf": "file",
374
- ".eot": "file",
375
- ".ico": "file",
376
- ".otf": "file",
377
- ".csv": "file",
378
- ".xlsx": "file",
379
- ".xls": "file",
380
- ".pptx": "file",
381
- ".ppt": "file",
382
- ".docx": "file",
383
- ".doc": "file",
384
- ".zip": "file",
385
- ".pfx": "file",
386
- ".pkl": "file"
387
- },
388
- inject: [PathUtil.posix(fileURLToPath(await import.meta.resolve("node-stdlib-browser/helpers/esbuild/shim")))],
389
- plugins: [
390
- {
391
- name: "sd-worker",
392
- setup: ({ onLoad }) => {
393
- onLoad({ filter: /\.ts$/ }, async (args) => {
394
- if (args.path.endsWith(".d.ts"))
395
- return;
396
- // ts sourefile Worker사용여부 확인 (URL, import.meta.url)
397
- let contents = this._sourceFileCache.typeScriptFileCache.get(pathToFileURL(args.path).toString());
398
- if (typeof contents !== "string")
399
- return;
400
- const regexp = /new Worker\(new URL\("(.*\.ts)", import\.meta\.url\)/;
401
- const matches = contents.match(new RegExp(regexp, "g"));
402
- if (!matches)
403
- return;
404
- for (const match of matches) {
405
- const urlPath = match.match(regexp)[1];
406
- // 해당 URL의 파일을 esbuild로 빌드
407
- const outFileName = path.basename(urlPath, path.extname(urlPath)) + ".js";
408
- await esbuild.build({
409
- entryPoints: [path.resolve(path.dirname(args.path), urlPath)],
410
- outfile: path.resolve(this._opt.pkgPath, "dist", outFileName),
411
- target: this._browserTarget,
412
- format: "esm",
413
- bundle: true,
414
- keepNames: true,
415
- minifyIdentifiers: !this._opt.dev,
416
- minifySyntax: !this._opt.dev,
417
- minifyWhitespace: !this._opt.dev,
418
- sourcemap: this._opt.dev,
419
- platform: 'browser',
420
- conditions: ['es2020', 'es2015', 'module'],
421
- mainFields: ['es2020', 'es2015', 'browser', 'module', 'main'],
422
- resolveExtensions: ['.ts', '.tsx', '.mjs', '.js'],
423
- tsconfig: this._tsConfigFilePath,
424
- preserveSymlinks: false,
425
- define: {
426
- ...!this._opt.dev ? { ngDevMode: 'false' } : {},
427
- ngJitMode: 'false',
428
- global: 'global',
429
- process: 'process',
430
- Buffer: 'Buffer',
431
- 'process.env.SD_VERSION': JSON.stringify(this._pkgNpmConf.version),
432
- "process.env.NODE_ENV": JSON.stringify(this._opt.dev ? "development" : "production"),
433
- ...this._opt.env ? Object.keys(this._opt.env).toObject(key => `process.env.${key}`, key => JSON.stringify(this._opt.env[key])) : {}
434
- },
435
- inject: [PathUtil.posix(fileURLToPath(await import.meta.resolve("node-stdlib-browser/helpers/esbuild/shim")))],
436
- });
437
- // 빌드된 파일을 가리키도록 URL변경
438
- contents = contents.replace(urlPath, "./" + outFileName);
439
- const currSet = this._customDepsCache.getOrCreate(path.resolve(path.dirname(args.path), urlPath), new Set());
440
- currSet.add(path.resolve(args.path));
441
- }
442
- this._sourceFileCache.typeScriptFileCache.set(pathToFileURL(args.path).toString(), contents);
443
- return undefined;
444
- });
445
- }
446
- },
447
- ...this._opt.cordovaConfig?.plugins ? [{
448
- name: "cordova:plugin-empty",
449
- setup: ({ onResolve }) => {
450
- onResolve({ filter: new RegExp("(" + this._opt.cordovaConfig.plugins.join("|") + ")") }, () => {
451
- return {
452
- path: `./cordova-empty.js`,
453
- external: true
454
- };
455
- });
456
- }
457
- }] : [],
458
- createVirtualModulePlugin({
459
- namespace: "angular:polyfills",
460
- loadContent: () => ({
461
- contents: `import "./src/polyfills.ts";`,
462
- loader: 'js',
463
- resolveDir: this._opt.pkgPath
464
- })
465
- }),
466
- createSourcemapIgnorelistPlugin(),
467
- createCompilerPlugin({
468
- sourcemap: this._opt.dev,
469
- thirdPartySourcemaps: false,
470
- tsconfig: this._tsConfigFilePath,
471
- jit: false,
472
- advancedOptimizations: true,
473
- fileReplacements: undefined,
474
- sourceFileCache: this._sourceFileCache,
475
- loadResultCache: this._sourceFileCache.loadResultCache
476
- }, {
477
- workspaceRoot: this._opt.pkgPath,
478
- optimization: !this._opt.dev,
479
- sourcemap: this._opt.dev ? 'inline' : false,
480
- outputNames: { bundles: '[name]', media: 'media/[name]' },
481
- includePaths: [],
482
- externalDependencies: [],
483
- target: this._browserTarget,
484
- inlineStyleLanguage: 'scss',
485
- preserveSymlinks: false,
486
- tailwindConfiguration: undefined
487
- }),
488
- nodeStdLibBrowserPlugin(nodeStdLibBrowser),
489
- ]
490
- });
491
- }
492
- _getStyleContext() {
493
- const browserTarget = transformSupportedBrowsersToTargets(browserslist("defaults and fully supports es6-module"));
494
- const pluginFactory = new StylesheetPluginFactory({
495
- sourcemap: this._opt.dev,
496
- includePaths: []
497
- }, this._sourceFileCache.loadResultCache);
498
- return new SdNgBundlerContext(this._opt.pkgPath, {
499
- absWorkingDir: this._opt.pkgPath,
500
- bundle: true,
501
- entryNames: '[name]',
502
- assetNames: 'media/[name]',
503
- logLevel: 'silent',
504
- minify: !this._opt.dev,
505
- metafile: true,
506
- sourcemap: this._opt.dev,
507
- outdir: this._opt.pkgPath,
508
- write: false,
509
- platform: 'browser',
510
- target: browserTarget,
511
- preserveSymlinks: false,
512
- external: [],
513
- conditions: ['style', 'sass'],
514
- mainFields: ['style', 'sass'],
515
- legalComments: !this._opt.dev ? "none" : "eof",
516
- entryPoints: { styles: 'angular:styles/global;styles' },
517
- plugins: [
518
- createVirtualModulePlugin({
519
- namespace: "angular:styles/global",
520
- transformPath: (currPath) => currPath.split(';', 2)[1],
521
- loadContent: () => ({
522
- contents: `@import 'src/styles.scss';`,
523
- loader: 'css',
524
- resolveDir: this._opt.pkgPath
525
- }),
526
- }),
527
- pluginFactory.create(SassStylesheetLanguage),
528
- pluginFactory.create(CssStylesheetLanguage),
529
- createCssResourcePlugin(this._sourceFileCache.loadResultCache),
530
- ],
531
- });
532
- }
533
- }
1
+ import { createCompilerPlugin } from "@angular-devkit/build-angular/src/tools/esbuild/angular/compiler-plugin";
2
+ import path from "path";
3
+ import { BuildOutputFileType } from "@angular-devkit/build-angular/src/tools/esbuild/bundler-context";
4
+ import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
5
+ import { fileURLToPath } from "url";
6
+ import { createVirtualModulePlugin } from "@angular-devkit/build-angular/src/tools/esbuild/virtual-module-plugin";
7
+ import { createSourcemapIgnorelistPlugin } from "@angular-devkit/build-angular/src/tools/esbuild/sourcemap-ignorelist-plugin";
8
+ import nodeStdLibBrowser from "node-stdlib-browser";
9
+ import nodeStdLibBrowserPlugin from "node-stdlib-browser/helpers/esbuild/plugin";
10
+ import { copyAssets } from "@angular-devkit/build-angular/src/utils/copy-assets";
11
+ import { extractLicenses } from "@angular-devkit/build-angular/src/tools/esbuild/license-extractor";
12
+ import { augmentAppWithServiceWorkerEsbuild } from "@angular-devkit/build-angular/src/utils/service-worker";
13
+ import browserslist from "browserslist";
14
+ import { convertOutputFile, createOutputFileFromText, transformSupportedBrowsersToTargets } from "@angular-devkit/build-angular/src/tools/esbuild/utils";
15
+ import { createCssResourcePlugin } from "@angular-devkit/build-angular/src/tools/esbuild/stylesheets/css-resource-plugin";
16
+ import { CssStylesheetLanguage } from "@angular-devkit/build-angular/src/tools/esbuild/stylesheets/css-language";
17
+ import { SassStylesheetLanguage } from "@angular-devkit/build-angular/src/tools/esbuild/stylesheets/sass-language";
18
+ import { StylesheetPluginFactory } from "@angular-devkit/build-angular/src/tools/esbuild/stylesheets/stylesheet-plugin-factory";
19
+ import { IndexHtmlGenerator } from "@angular-devkit/build-angular/src/utils/index-file/index-html-generator";
20
+ import { CrossOrigin } from "@angular-devkit/build-angular";
21
+ import { InlineCriticalCssProcessor } from "@angular-devkit/build-angular/src/utils/index-file/inline-critical-css";
22
+ import { SdSourceFileCache } from "../utils/SdSourceFileCache";
23
+ import { SdNgBundlerContext } from "./SdNgBundlerContext";
24
+ export class SdNgBundler {
25
+ constructor(_opt) {
26
+ this._opt = _opt;
27
+ this._sourceFileCache = new SdSourceFileCache(path.resolve(this._opt.pkgPath, ".cache"));
28
+ this._outputCache = new Map();
29
+ this._customDepsCache = new Map();
30
+ this._pkgNpmConf = FsUtil.readJson(path.resolve(this._opt.pkgPath, "package.json"));
31
+ this._mainFilePath = path.resolve(this._opt.pkgPath, "src/main.ts");
32
+ this._tsConfigFilePath = path.resolve(this._opt.pkgPath, "tsconfig.json");
33
+ this._swConfFilePath = path.resolve(this._opt.pkgPath, "ngsw-config.json");
34
+ this._browserTarget = transformSupportedBrowsersToTargets(browserslist("defaults and fully supports es6-module"));
35
+ this._indexHtmlFilePath = path.resolve(this._opt.pkgPath, "src/index.html");
36
+ this._pkgName = path.basename(this._opt.pkgPath);
37
+ this._baseHref = this._opt.builderType === "web" ? `/${this._pkgName}/` : this._opt.dev ? `/${this._pkgName}/${this._opt.builderType}/` : ``;
38
+ }
39
+ removeCache(filePaths) {
40
+ for (const filePath of filePaths) {
41
+ const depsSet = this._customDepsCache.get(filePath);
42
+ if (depsSet) {
43
+ for (const depFile of depsSet) {
44
+ this._sourceFileCache.invalidate([depFile]);
45
+ }
46
+ }
47
+ else {
48
+ this._sourceFileCache.invalidate([filePath]);
49
+ }
50
+ }
51
+ }
52
+ async bundleAsync() {
53
+ if (!this._contexts) {
54
+ this._contexts = [];
55
+ this._contexts.push(await this._getAppContextAsync());
56
+ this._contexts.push(this._getStyleContext());
57
+ }
58
+ //-- build
59
+ const bundlingResults = await this._contexts.mapAsync(async (ctx) => await ctx.bundleAsync());
60
+ const results = bundlingResults.mapMany(bundlingResult => bundlingResult.results);
61
+ const watchFilePaths = [
62
+ ...this._sourceFileCache.keys(),
63
+ ...this._sourceFileCache.babelFileCache.keys(),
64
+ ...this._sourceFileCache.loadResultCache.fileDependencies.keys(),
65
+ ...this._customDepsCache.keys()
66
+ ].map((item) => path.resolve(item)).distinct();
67
+ let affectedSourceFilePaths = watchFilePaths.filter((item) => PathUtil.isChildPath(item, this._opt.pkgPath));
68
+ if (this._sourceFileCache.modifiedFiles.size > 0) {
69
+ const depMap = new Map();
70
+ for (const bundlingResult of bundlingResults) {
71
+ for (const [k, v] of bundlingResult.dependencyMap) {
72
+ const currSet = depMap.getOrCreate(k, new Set());
73
+ currSet.adds(...v);
74
+ }
75
+ }
76
+ for (const [k, v] of this._sourceFileCache.loadResultCache.fileDependencies) {
77
+ const currSet = depMap.getOrCreate(k, new Set());
78
+ currSet.adds(...Array.from(v).map((item) => item.startsWith("file:") ? fileURLToPath(item) : undefined).filterExists());
79
+ }
80
+ for (const [k, v] of this._customDepsCache) {
81
+ const currSet = depMap.getOrCreate(k, new Set());
82
+ currSet.adds(...v);
83
+ }
84
+ const searchAffectedFiles = (filePath, prev) => {
85
+ const result = new Set(prev);
86
+ const importerPaths = depMap.get(filePath);
87
+ if (!importerPaths)
88
+ return result;
89
+ for (const importerPath of importerPaths) {
90
+ if (result.has(importerPath))
91
+ continue;
92
+ result.adds(importerPath);
93
+ result.adds(...searchAffectedFiles(importerPath, result));
94
+ }
95
+ return result;
96
+ };
97
+ const affectedFilePathSet = new Set();
98
+ for (const modFile of this._sourceFileCache.modifiedFiles) {
99
+ affectedFilePathSet.add(path.resolve(modFile));
100
+ affectedFilePathSet.adds(...searchAffectedFiles(path.resolve(modFile)));
101
+ }
102
+ affectedSourceFilePaths = Array.from(affectedFilePathSet.values()).filter((item) => PathUtil.isChildPath(item, this._opt.pkgPath));
103
+ }
104
+ /*const executionResult = new ExecutionResult(this._contexts, this._sourceFileCache);
105
+ executionResult.outputFiles.push(...bundlingResult.outputFiles);*/
106
+ const outputFiles = bundlingResults.mapMany(item => item.outputFiles?.map(file => {
107
+ const fileType = path.dirname(file.path) === 'media' ? BuildOutputFileType.Media : BuildOutputFileType.Browser;
108
+ return convertOutputFile(file, fileType);
109
+ }) ?? []);
110
+ const initialFiles = new Map();
111
+ const metafile = {
112
+ inputs: {},
113
+ outputs: {}
114
+ };
115
+ for (const bundlingResult of bundlingResults) {
116
+ bundlingResult.initialFiles.forEach((v, k) => initialFiles.set(k, v));
117
+ metafile.inputs = { ...metafile.inputs, ...bundlingResult.metafile?.inputs };
118
+ metafile.outputs = { ...metafile.outputs, ...bundlingResult.metafile?.outputs };
119
+ }
120
+ const assetFiles = [];
121
+ //-- Check commonjs
122
+ // if (!this._opt.dev) {
123
+ // const messages = checkCommonJSModules(bundlingResult.metafile, []);
124
+ // for (const msg of messages) {
125
+ // results.push({
126
+ // filePath: msg.location?.file,
127
+ // line: msg.location?.line,
128
+ // char: msg.location?.column,
129
+ // code: msg.pluginName,
130
+ // severity: "warning",
131
+ // message: msg.text ?? "",
132
+ // type: "build"
133
+ // });
134
+ // }
135
+ // }
136
+ //-- cordova empty
137
+ if (this._opt.cordovaConfig?.plugins) {
138
+ outputFiles.push(createOutputFileFromText("cordova-empty.js", "export default {};", BuildOutputFileType.Browser));
139
+ }
140
+ //-- index
141
+ const genIndexHtmlResult = await this._genIndexHtmlAsync(outputFiles, initialFiles);
142
+ for (const warning of genIndexHtmlResult.warnings) {
143
+ results.push({
144
+ filePath: undefined,
145
+ line: undefined,
146
+ char: undefined,
147
+ code: undefined,
148
+ severity: "warning",
149
+ message: `(gen-index) ${warning}`,
150
+ type: "build",
151
+ });
152
+ }
153
+ for (const error of genIndexHtmlResult.errors) {
154
+ results.push({
155
+ filePath: undefined,
156
+ line: undefined,
157
+ char: undefined,
158
+ code: undefined,
159
+ severity: "error",
160
+ message: `(gen-index) ${error}`,
161
+ type: "build",
162
+ });
163
+ }
164
+ outputFiles.push(createOutputFileFromText("index.html", genIndexHtmlResult.content, BuildOutputFileType.Browser));
165
+ //-- copy assets
166
+ assetFiles.push(...(await this._copyAssetsAsync()));
167
+ //-- extract 3rdpartylicenses
168
+ if (!this._opt.dev) {
169
+ outputFiles.push(createOutputFileFromText('3rdpartylicenses.txt', await extractLicenses(metafile, this._opt.pkgPath), BuildOutputFileType.Root));
170
+ }
171
+ //-- service worker
172
+ if (FsUtil.exists(this._swConfFilePath)) {
173
+ try {
174
+ const serviceWorkerResult = await this._genServiceWorkerAsync(outputFiles, assetFiles);
175
+ outputFiles.push(createOutputFileFromText('ngsw.json', serviceWorkerResult.manifest, BuildOutputFileType.Browser));
176
+ assetFiles.push(...serviceWorkerResult.assetFiles);
177
+ }
178
+ catch (err) {
179
+ results.push({
180
+ filePath: undefined,
181
+ line: undefined,
182
+ char: undefined,
183
+ code: undefined,
184
+ severity: "error",
185
+ message: `(gen-sw) ${err.toString()}`,
186
+ type: "build",
187
+ });
188
+ }
189
+ }
190
+ //-- write
191
+ for (const outputFile of outputFiles) {
192
+ const distFilePath = path.resolve(this._opt.outputPath, outputFile.path);
193
+ const prev = this._outputCache.get(distFilePath);
194
+ if (prev !== Buffer.from(outputFile.contents).toString("base64")) {
195
+ await FsUtil.writeFileAsync(distFilePath, outputFile.contents);
196
+ this._outputCache.set(distFilePath, Buffer.from(outputFile.contents).toString("base64"));
197
+ }
198
+ }
199
+ for (const assetFile of assetFiles) {
200
+ const prev = this._outputCache.get(assetFile.source);
201
+ const curr = FsUtil.lstat(assetFile.source).mtime.getTime();
202
+ if (prev !== curr) {
203
+ await FsUtil.copyAsync(assetFile.source, path.resolve(this._opt.outputPath, assetFile.destination));
204
+ this._outputCache.set(assetFile.source, curr);
205
+ }
206
+ }
207
+ return {
208
+ filePaths: watchFilePaths,
209
+ affectedFilePaths: affectedSourceFilePaths,
210
+ results
211
+ };
212
+ }
213
+ async _genIndexHtmlAsync(outputFiles, initialFiles) {
214
+ const readAsset = (filePath) => {
215
+ const relFilePath = path.relative("/", filePath);
216
+ const currFile = outputFiles.find((outputFile) => outputFile.path === relFilePath);
217
+ if (currFile) {
218
+ return Promise.resolve(currFile.text);
219
+ }
220
+ throw new Error(`Output file does not exist: ${relFilePath}`);
221
+ };
222
+ const indexHtmlGenerator = new IndexHtmlGenerator({
223
+ indexPath: this._indexHtmlFilePath,
224
+ entrypoints: [
225
+ ['runtime', true],
226
+ ['polyfills', true],
227
+ ['styles', false],
228
+ ['vendor', true],
229
+ ['main', true],
230
+ ...this._opt.builderType === "cordova" ? [
231
+ ["cordova-entry", true]
232
+ ] : []
233
+ ],
234
+ optimization: {
235
+ scripts: !this._opt.dev,
236
+ fonts: { inline: !this._opt.dev },
237
+ styles: {
238
+ minify: !this._opt.dev,
239
+ inlineCritical: false
240
+ },
241
+ },
242
+ crossOrigin: CrossOrigin.None,
243
+ });
244
+ indexHtmlGenerator.readAsset = readAsset;
245
+ const hints = [];
246
+ if (!this._opt.dev) {
247
+ for (const [key, value] of initialFiles) {
248
+ if (value.entrypoint) {
249
+ continue;
250
+ }
251
+ if (value.type === 'script') {
252
+ hints.push({ url: key, mode: 'modulepreload' });
253
+ }
254
+ else if (value.type === 'style') {
255
+ hints.push({ url: key, mode: 'preload', as: 'style' });
256
+ }
257
+ }
258
+ }
259
+ const transformResult = await indexHtmlGenerator.process({
260
+ baseHref: this._baseHref,
261
+ lang: undefined,
262
+ outputPath: "/",
263
+ files: [...initialFiles].map(([file, record]) => ({
264
+ name: record.name ?? '',
265
+ file,
266
+ extension: path.extname(file),
267
+ })),
268
+ hints,
269
+ });
270
+ if (this._opt.dev) {
271
+ return transformResult;
272
+ }
273
+ else {
274
+ const inlineCriticalCssProcessor = new InlineCriticalCssProcessor({
275
+ minify: false,
276
+ readAsset,
277
+ });
278
+ const { content, errors, warnings } = await inlineCriticalCssProcessor.process(transformResult.content, { outputPath: "/", });
279
+ return {
280
+ warnings: [...transformResult.warnings, ...warnings],
281
+ errors: [...transformResult.errors, ...errors],
282
+ content
283
+ };
284
+ }
285
+ }
286
+ async _copyAssetsAsync() {
287
+ return await copyAssets([
288
+ { input: 'src', glob: 'favicon.ico', output: '' },
289
+ { input: 'src', glob: 'manifest.webmanifest', output: '' },
290
+ { input: 'src/assets', glob: '**/*', output: 'assets' },
291
+ ...this._opt.dev && this._opt.builderType === "cordova" ? Object.keys(this._opt.cordovaConfig?.platform ?? { browser: {} }).mapMany((platform) => [
292
+ {
293
+ input: `.cordova/platforms/${platform}/platform_www/plugins`,
294
+ glob: '**/*',
295
+ output: `cordova-${platform}/plugins`
296
+ },
297
+ {
298
+ input: `.cordova/platforms/${platform}/platform_www`,
299
+ glob: 'cordova.js',
300
+ output: `cordova-${platform}`
301
+ },
302
+ {
303
+ input: `.cordova/platforms/${platform}/platform_www`,
304
+ glob: 'cordova_plugins.js',
305
+ output: `cordova-${platform}`
306
+ },
307
+ {
308
+ input: `.cordova/platforms/${platform}/www`,
309
+ glob: 'config.xml',
310
+ output: `cordova-${platform}`
311
+ },
312
+ ]) : []
313
+ ], [], this._opt.pkgPath);
314
+ }
315
+ async _genServiceWorkerAsync(outputFiles, assetFiles) {
316
+ return await augmentAppWithServiceWorkerEsbuild(this._opt.pkgPath, this._swConfFilePath, this._baseHref, outputFiles, assetFiles);
317
+ }
318
+ async _getAppContextAsync() {
319
+ return new SdNgBundlerContext(this._opt.pkgPath, {
320
+ absWorkingDir: this._opt.pkgPath,
321
+ bundle: true,
322
+ keepNames: true,
323
+ format: 'esm',
324
+ assetNames: 'media/[name]',
325
+ conditions: ['es2020', 'es2015', 'module'],
326
+ resolveExtensions: ['.ts', '.tsx', '.mjs', '.js'],
327
+ metafile: true,
328
+ legalComments: this._opt.dev ? 'eof' : 'none',
329
+ logLevel: 'silent',
330
+ minifyIdentifiers: !this._opt.dev,
331
+ minifySyntax: !this._opt.dev,
332
+ minifyWhitespace: !this._opt.dev,
333
+ pure: ['forwardRef'],
334
+ outdir: this._opt.pkgPath,
335
+ outExtension: undefined,
336
+ sourcemap: this._opt.dev,
337
+ splitting: true,
338
+ chunkNames: 'chunk-[hash]',
339
+ tsconfig: this._tsConfigFilePath,
340
+ /*external: [
341
+ ...this._opt.cordovaConfig?.plugins ?? []
342
+ ],*/
343
+ write: false,
344
+ preserveSymlinks: false,
345
+ define: {
346
+ ...!this._opt.dev ? { ngDevMode: 'false' } : {},
347
+ ngJitMode: 'false',
348
+ global: 'global',
349
+ process: 'process',
350
+ Buffer: 'Buffer',
351
+ 'process.env.SD_VERSION': JSON.stringify(this._pkgNpmConf.version),
352
+ "process.env.NODE_ENV": JSON.stringify(this._opt.dev ? "development" : "production"),
353
+ ...this._opt.env ? Object.keys(this._opt.env).toObject(key => `process.env.${key}`, key => JSON.stringify(this._opt.env[key])) : {}
354
+ },
355
+ platform: 'browser',
356
+ mainFields: ['es2020', 'es2015', 'browser', 'module', 'main'],
357
+ entryNames: '[name]',
358
+ entryPoints: {
359
+ main: this._mainFilePath,
360
+ polyfills: 'angular:polyfills',
361
+ ...this._opt.builderType === "cordova" ? {
362
+ "cordova-entry": path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../lib/cordova-entry.js`)
363
+ } : {}
364
+ },
365
+ target: this._browserTarget,
366
+ supported: { 'async-await': false, 'object-rest-spread': false },
367
+ loader: {
368
+ ".png": "file",
369
+ ".jpeg": "file",
370
+ ".jpg": "file",
371
+ ".jfif": "file",
372
+ ".gif": "file",
373
+ ".svg": "file",
374
+ ".woff": "file",
375
+ ".woff2": "file",
376
+ ".ttf": "file",
377
+ ".eot": "file",
378
+ ".ico": "file",
379
+ ".otf": "file",
380
+ ".csv": "file",
381
+ ".xlsx": "file",
382
+ ".xls": "file",
383
+ ".pptx": "file",
384
+ ".ppt": "file",
385
+ ".docx": "file",
386
+ ".doc": "file",
387
+ ".zip": "file",
388
+ ".pfx": "file",
389
+ ".pkl": "file"
390
+ },
391
+ inject: [PathUtil.posix(fileURLToPath(await import.meta.resolve("node-stdlib-browser/helpers/esbuild/shim")))],
392
+ plugins: [
393
+ /*{
394
+ name: "sd-worker",
395
+ setup: ({onLoad}) => {
396
+ onLoad({filter: /\.ts$/}, async args => {
397
+ if (args.path.endsWith(".d.ts")) return;
398
+
399
+ // ts sourefile 로 Worker사용여부 확인 (URL, import.meta.url)
400
+ let contents = this._sourceFileCache.typeScriptFileCache.get(pathToFileURL(args.path).toString());
401
+ if (typeof contents !== "string") return;
402
+
403
+ const regexp = /new Worker\(new URL\("(.*\.ts)", import\.meta\.url\)/;
404
+ const matches = contents.match(new RegExp(regexp, "g"));
405
+ if (!matches) return;
406
+
407
+ for (const match of matches) {
408
+ const urlPath = match.match(regexp)![1];
409
+
410
+ // 해당 URL의 파일을 esbuild로 빌드
411
+ const outFileName = path.basename(urlPath, path.extname(urlPath)) + ".js";
412
+ await esbuild.build({
413
+ entryPoints: [path.resolve(path.dirname(args.path), urlPath)],
414
+ outfile: path.resolve(this._opt.pkgPath, "dist", outFileName),
415
+ target: this._browserTarget,
416
+ format: "esm",
417
+ bundle: true,
418
+ keepNames: true,
419
+ minifyIdentifiers: !this._opt.dev,
420
+ minifySyntax: !this._opt.dev,
421
+ minifyWhitespace: !this._opt.dev,
422
+ sourcemap: this._opt.dev,
423
+ platform: 'browser',
424
+ conditions: ['es2020', 'es2015', 'module'],
425
+ mainFields: ['es2020', 'es2015', 'browser', 'module', 'main'],
426
+ resolveExtensions: ['.ts', '.tsx', '.mjs', '.js'],
427
+ tsconfig: this._tsConfigFilePath,
428
+ preserveSymlinks: false,
429
+ define: {
430
+ ...!this._opt.dev ? {ngDevMode: 'false'} : {},
431
+ ngJitMode: 'false',
432
+ global: 'global',
433
+ process: 'process',
434
+ Buffer: 'Buffer',
435
+ 'process.env.SD_VERSION': JSON.stringify(this._pkgNpmConf.version),
436
+ "process.env.NODE_ENV": JSON.stringify(this._opt.dev ? "development" : "production"),
437
+ ...this._opt.env ? Object.keys(this._opt.env).toObject(
438
+ key => `process.env.${key}`,
439
+ key => JSON.stringify(this._opt.env![key])
440
+ ) : {}
441
+ },
442
+ inject: [PathUtil.posix(fileURLToPath(await import.meta.resolve!("node-stdlib-browser/helpers/esbuild/shim")))],
443
+ });
444
+
445
+ // 빌드된 파일을 가리키도록 URL변경
446
+ contents = contents.replace(urlPath, "./" + outFileName);
447
+
448
+ const currSet = this._customDepsCache.getOrCreate(path.resolve(path.dirname(args.path), urlPath), new Set());
449
+ currSet.add(path.resolve(args.path));
450
+ }
451
+
452
+ this._sourceFileCache.typeScriptFileCache.set(pathToFileURL(args.path).toString(), contents);
453
+
454
+ return undefined;
455
+ });
456
+ }
457
+ },*/
458
+ ...this._opt.cordovaConfig?.plugins ? [{
459
+ name: "cordova:plugin-empty",
460
+ setup: ({ onResolve }) => {
461
+ onResolve({ filter: new RegExp("(" + this._opt.cordovaConfig.plugins.join("|") + ")") }, () => {
462
+ return {
463
+ path: `./cordova-empty.js`,
464
+ external: true
465
+ };
466
+ });
467
+ }
468
+ }] : [],
469
+ createVirtualModulePlugin({
470
+ namespace: "angular:polyfills",
471
+ loadContent: () => ({
472
+ contents: `import "./src/polyfills.ts";`,
473
+ loader: 'js',
474
+ resolveDir: this._opt.pkgPath
475
+ })
476
+ }),
477
+ createSourcemapIgnorelistPlugin(),
478
+ createCompilerPlugin({
479
+ sourcemap: this._opt.dev,
480
+ tsconfig: this._tsConfigFilePath,
481
+ jit: false,
482
+ advancedOptimizations: true,
483
+ thirdPartySourcemaps: false,
484
+ fileReplacements: undefined,
485
+ sourceFileCache: this._sourceFileCache,
486
+ loadResultCache: this._sourceFileCache.loadResultCache,
487
+ incremental: this._opt.dev
488
+ }, {
489
+ workspaceRoot: this._opt.pkgPath,
490
+ optimization: !this._opt.dev,
491
+ sourcemap: this._opt.dev ? 'inline' : false,
492
+ outputNames: { bundles: '[name]', media: 'media/[name]' },
493
+ includePaths: [],
494
+ externalDependencies: [],
495
+ target: this._browserTarget,
496
+ inlineStyleLanguage: 'scss',
497
+ preserveSymlinks: false,
498
+ tailwindConfiguration: undefined
499
+ }),
500
+ nodeStdLibBrowserPlugin(nodeStdLibBrowser),
501
+ ]
502
+ });
503
+ }
504
+ _getStyleContext() {
505
+ const browserTarget = transformSupportedBrowsersToTargets(browserslist("defaults and fully supports es6-module"));
506
+ const pluginFactory = new StylesheetPluginFactory({
507
+ sourcemap: this._opt.dev,
508
+ includePaths: []
509
+ }, this._sourceFileCache.loadResultCache);
510
+ return new SdNgBundlerContext(this._opt.pkgPath, {
511
+ absWorkingDir: this._opt.pkgPath,
512
+ bundle: true,
513
+ entryNames: '[name]',
514
+ assetNames: 'media/[name]',
515
+ logLevel: 'silent',
516
+ minify: !this._opt.dev,
517
+ metafile: true,
518
+ sourcemap: this._opt.dev,
519
+ outdir: this._opt.pkgPath,
520
+ write: false,
521
+ platform: 'browser',
522
+ target: browserTarget,
523
+ preserveSymlinks: false,
524
+ external: [],
525
+ conditions: ['style', 'sass'],
526
+ mainFields: ['style', 'sass'],
527
+ legalComments: !this._opt.dev ? "none" : "eof",
528
+ entryPoints: { styles: 'angular:styles/global;styles' },
529
+ plugins: [
530
+ createVirtualModulePlugin({
531
+ namespace: "angular:styles/global",
532
+ transformPath: (currPath) => currPath.split(';', 2)[1],
533
+ loadContent: () => ({
534
+ contents: `@import 'src/styles.scss';`,
535
+ loader: 'css',
536
+ resolveDir: this._opt.pkgPath
537
+ }),
538
+ }),
539
+ pluginFactory.create(SassStylesheetLanguage),
540
+ pluginFactory.create(CssStylesheetLanguage),
541
+ createCssResourcePlugin(this._sourceFileCache.loadResultCache),
542
+ ],
543
+ });
544
+ }
545
+ }
534
546
  //# sourceMappingURL=SdNgBundler.js.map