@nativescript/vite 8.0.0-alpha.0 → 8.0.0-alpha.10
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/configuration/angular.d.ts +1 -1
- package/configuration/angular.js +486 -140
- package/configuration/angular.js.map +1 -1
- package/configuration/base.js +159 -41
- package/configuration/base.js.map +1 -1
- package/configuration/javascript.js +3 -3
- package/configuration/javascript.js.map +1 -1
- package/configuration/solid.js +7 -0
- package/configuration/solid.js.map +1 -1
- package/configuration/typescript.js +4 -4
- package/configuration/typescript.js.map +1 -1
- package/helpers/angular/angular-linker.js +38 -42
- package/helpers/angular/angular-linker.js.map +1 -1
- package/helpers/angular/inject-component-hmr-registration.d.ts +112 -0
- package/helpers/angular/inject-component-hmr-registration.js +359 -0
- package/helpers/angular/inject-component-hmr-registration.js.map +1 -0
- package/helpers/angular/inline-decorator-component-templates.d.ts +3 -0
- package/helpers/angular/inline-decorator-component-templates.js +400 -0
- package/helpers/angular/inline-decorator-component-templates.js.map +1 -0
- package/helpers/angular/shared-linker.d.ts +7 -0
- package/helpers/angular/shared-linker.js +37 -1
- package/helpers/angular/shared-linker.js.map +1 -1
- package/helpers/angular/synthesize-decorator-ctor-parameters.d.ts +1 -0
- package/helpers/angular/synthesize-decorator-ctor-parameters.js +256 -0
- package/helpers/angular/synthesize-decorator-ctor-parameters.js.map +1 -0
- package/helpers/angular/synthesize-injectable-factories.d.ts +3 -0
- package/helpers/angular/synthesize-injectable-factories.js +414 -0
- package/helpers/angular/synthesize-injectable-factories.js.map +1 -0
- package/helpers/angular/util.d.ts +1 -0
- package/helpers/angular/util.js +88 -0
- package/helpers/angular/util.js.map +1 -1
- package/helpers/commonjs-plugins.d.ts +5 -2
- package/helpers/commonjs-plugins.js +126 -0
- package/helpers/commonjs-plugins.js.map +1 -1
- package/helpers/config-as-json.js +10 -0
- package/helpers/config-as-json.js.map +1 -1
- package/helpers/esbuild-platform-resolver.js +5 -5
- package/helpers/esbuild-platform-resolver.js.map +1 -1
- package/helpers/external-configs.d.ts +9 -1
- package/helpers/external-configs.js +31 -6
- package/helpers/external-configs.js.map +1 -1
- package/helpers/global-defines.d.ts +51 -0
- package/helpers/global-defines.js +77 -0
- package/helpers/global-defines.js.map +1 -1
- package/helpers/import-meta-path.d.ts +4 -0
- package/helpers/import-meta-path.js +5 -0
- package/helpers/import-meta-path.js.map +1 -0
- package/helpers/import-specifier.d.ts +1 -0
- package/helpers/import-specifier.js +18 -0
- package/helpers/import-specifier.js.map +1 -0
- package/helpers/logging.d.ts +1 -0
- package/helpers/logging.js +63 -3
- package/helpers/logging.js.map +1 -1
- package/helpers/main-entry.d.ts +5 -2
- package/helpers/main-entry.js +365 -116
- package/helpers/main-entry.js.map +1 -1
- package/helpers/nativeclass-transform.js +8 -127
- package/helpers/nativeclass-transform.js.map +1 -1
- package/helpers/nativeclass-transformer-plugin.d.ts +19 -1
- package/helpers/nativeclass-transformer-plugin.js +318 -31
- package/helpers/nativeclass-transformer-plugin.js.map +1 -1
- package/helpers/ns-core-url.d.ts +83 -0
- package/helpers/ns-core-url.js +167 -0
- package/helpers/ns-core-url.js.map +1 -0
- package/helpers/prelink-angular.js +1 -4
- package/helpers/prelink-angular.js.map +1 -1
- package/helpers/preserve-imports.js +2 -17
- package/helpers/preserve-imports.js.map +1 -1
- package/helpers/project.d.ts +35 -0
- package/helpers/project.js +120 -2
- package/helpers/project.js.map +1 -1
- package/helpers/ts-config-paths.js +50 -2
- package/helpers/ts-config-paths.js.map +1 -1
- package/helpers/workers.d.ts +20 -19
- package/helpers/workers.js +620 -3
- package/helpers/workers.js.map +1 -1
- package/hmr/client/css-handler.js +60 -19
- package/hmr/client/css-handler.js.map +1 -1
- package/hmr/client/hmr-pending-overlay.d.ts +27 -0
- package/hmr/client/hmr-pending-overlay.js +50 -0
- package/hmr/client/hmr-pending-overlay.js.map +1 -0
- package/hmr/client/index.js +597 -24
- package/hmr/client/index.js.map +1 -1
- package/hmr/client/utils.d.ts +5 -0
- package/hmr/client/utils.js +212 -21
- package/hmr/client/utils.js.map +1 -1
- package/hmr/entry-runtime.d.ts +10 -0
- package/hmr/entry-runtime.js +330 -42
- package/hmr/entry-runtime.js.map +1 -1
- package/hmr/frameworks/angular/client/index.d.ts +3 -1
- package/hmr/frameworks/angular/client/index.js +821 -25
- package/hmr/frameworks/angular/client/index.js.map +1 -1
- package/hmr/frameworks/angular/server/linker.js +37 -6
- package/hmr/frameworks/angular/server/linker.js.map +1 -1
- package/hmr/frameworks/angular/server/strategy.js +30 -6
- package/hmr/frameworks/angular/server/strategy.js.map +1 -1
- package/hmr/frameworks/typescript/server/strategy.js +8 -2
- package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
- package/hmr/frameworks/vue/client/index.js +18 -42
- package/hmr/frameworks/vue/client/index.js.map +1 -1
- package/hmr/helpers/ast-normalizer.js +22 -10
- package/hmr/helpers/ast-normalizer.js.map +1 -1
- package/hmr/helpers/cjs-named-exports.d.ts +23 -0
- package/hmr/helpers/cjs-named-exports.js +152 -0
- package/hmr/helpers/cjs-named-exports.js.map +1 -0
- package/hmr/server/constants.d.ts +1 -0
- package/hmr/server/constants.js +14 -3
- package/hmr/server/constants.js.map +1 -1
- package/hmr/server/core-sanitize.d.ts +49 -2
- package/hmr/server/core-sanitize.js +267 -24
- package/hmr/server/core-sanitize.js.map +1 -1
- package/hmr/server/import-map.d.ts +65 -0
- package/hmr/server/import-map.js +222 -0
- package/hmr/server/import-map.js.map +1 -0
- package/hmr/server/index.d.ts +2 -1
- package/hmr/server/index.js.map +1 -1
- package/hmr/server/ns-core-cjs-shape.d.ts +204 -0
- package/hmr/server/ns-core-cjs-shape.js +271 -0
- package/hmr/server/ns-core-cjs-shape.js.map +1 -0
- package/hmr/server/perf-instrumentation.d.ts +114 -0
- package/hmr/server/perf-instrumentation.js +195 -0
- package/hmr/server/perf-instrumentation.js.map +1 -0
- package/hmr/server/runtime-graph-filter.d.ts +5 -0
- package/hmr/server/runtime-graph-filter.js +21 -0
- package/hmr/server/runtime-graph-filter.js.map +1 -0
- package/hmr/server/shared-transform-request.d.ts +12 -0
- package/hmr/server/shared-transform-request.js +144 -0
- package/hmr/server/shared-transform-request.js.map +1 -0
- package/hmr/server/vite-plugin.d.ts +21 -1
- package/hmr/server/vite-plugin.js +461 -22
- package/hmr/server/vite-plugin.js.map +1 -1
- package/hmr/server/websocket-angular-entry.d.ts +2 -0
- package/hmr/server/websocket-angular-entry.js +68 -0
- package/hmr/server/websocket-angular-entry.js.map +1 -0
- package/hmr/server/websocket-angular-hot-update.d.ts +78 -0
- package/hmr/server/websocket-angular-hot-update.js +413 -0
- package/hmr/server/websocket-angular-hot-update.js.map +1 -0
- package/hmr/server/websocket-core-bridge.d.ts +21 -0
- package/hmr/server/websocket-core-bridge.js +357 -0
- package/hmr/server/websocket-core-bridge.js.map +1 -0
- package/hmr/server/websocket-graph-upsert.d.ts +21 -0
- package/hmr/server/websocket-graph-upsert.js +33 -0
- package/hmr/server/websocket-graph-upsert.js.map +1 -0
- package/hmr/server/websocket-hmr-pending.d.ts +43 -0
- package/hmr/server/websocket-hmr-pending.js +55 -0
- package/hmr/server/websocket-hmr-pending.js.map +1 -0
- package/hmr/server/websocket-module-bindings.d.ts +6 -0
- package/hmr/server/websocket-module-bindings.js +471 -0
- package/hmr/server/websocket-module-bindings.js.map +1 -0
- package/hmr/server/websocket-module-specifiers.d.ts +101 -0
- package/hmr/server/websocket-module-specifiers.js +820 -0
- package/hmr/server/websocket-module-specifiers.js.map +1 -0
- package/hmr/server/websocket-ns-m-finalize.d.ts +22 -0
- package/hmr/server/websocket-ns-m-finalize.js +88 -0
- package/hmr/server/websocket-ns-m-finalize.js.map +1 -0
- package/hmr/server/websocket-ns-m-paths.d.ts +3 -0
- package/hmr/server/websocket-ns-m-paths.js +92 -0
- package/hmr/server/websocket-ns-m-paths.js.map +1 -0
- package/hmr/server/websocket-ns-m-request.d.ts +45 -0
- package/hmr/server/websocket-ns-m-request.js +196 -0
- package/hmr/server/websocket-ns-m-request.js.map +1 -0
- package/hmr/server/websocket-runtime-compat.d.ts +19 -0
- package/hmr/server/websocket-runtime-compat.js +287 -0
- package/hmr/server/websocket-runtime-compat.js.map +1 -0
- package/hmr/server/websocket-served-module-helpers.d.ts +36 -0
- package/hmr/server/websocket-served-module-helpers.js +631 -0
- package/hmr/server/websocket-served-module-helpers.js.map +1 -0
- package/hmr/server/websocket-txn.d.ts +6 -0
- package/hmr/server/websocket-txn.js +45 -0
- package/hmr/server/websocket-txn.js.map +1 -0
- package/hmr/server/websocket-vendor-unifier.d.ts +10 -0
- package/hmr/server/websocket-vendor-unifier.js +51 -0
- package/hmr/server/websocket-vendor-unifier.js.map +1 -0
- package/hmr/server/websocket-vue-sfc.d.ts +27 -0
- package/hmr/server/websocket-vue-sfc.js +1069 -0
- package/hmr/server/websocket-vue-sfc.js.map +1 -0
- package/hmr/server/websocket.d.ts +26 -3
- package/hmr/server/websocket.js +2233 -796
- package/hmr/server/websocket.js.map +1 -1
- package/hmr/shared/package-classifier.d.ts +9 -0
- package/hmr/shared/package-classifier.js +58 -0
- package/hmr/shared/package-classifier.js.map +1 -0
- package/hmr/shared/runtime/boot-timeline.d.ts +17 -0
- package/hmr/shared/runtime/boot-timeline.js +51 -0
- package/hmr/shared/runtime/boot-timeline.js.map +1 -0
- package/hmr/shared/runtime/browser-runtime-contract.d.ts +64 -0
- package/hmr/shared/runtime/browser-runtime-contract.js +54 -0
- package/hmr/shared/runtime/browser-runtime-contract.js.map +1 -0
- package/hmr/shared/runtime/dev-overlay.d.ts +85 -0
- package/hmr/shared/runtime/dev-overlay.js +1236 -0
- package/hmr/shared/runtime/dev-overlay.js.map +1 -0
- package/hmr/shared/runtime/http-only-boot.d.ts +1 -0
- package/hmr/shared/runtime/http-only-boot.js +53 -6
- package/hmr/shared/runtime/http-only-boot.js.map +1 -1
- package/hmr/shared/runtime/module-provenance.d.ts +1 -0
- package/hmr/shared/runtime/module-provenance.js +63 -0
- package/hmr/shared/runtime/module-provenance.js.map +1 -0
- package/hmr/shared/runtime/platform-polyfills.d.ts +26 -0
- package/hmr/shared/runtime/platform-polyfills.js +122 -0
- package/hmr/shared/runtime/platform-polyfills.js.map +1 -0
- package/hmr/shared/runtime/root-placeholder.d.ts +1 -0
- package/hmr/shared/runtime/root-placeholder.js +552 -82
- package/hmr/shared/runtime/root-placeholder.js.map +1 -1
- package/hmr/shared/runtime/session-bootstrap.d.ts +1 -0
- package/hmr/shared/runtime/session-bootstrap.js +195 -0
- package/hmr/shared/runtime/session-bootstrap.js.map +1 -0
- package/hmr/shared/runtime/vendor-bootstrap.js +52 -15
- package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -1
- package/hmr/shared/vendor/manifest.d.ts +37 -0
- package/hmr/shared/vendor/manifest.js +677 -57
- package/hmr/shared/vendor/manifest.js.map +1 -1
- package/hmr/shared/vendor/registry.js +104 -7
- package/hmr/shared/vendor/registry.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.js +5 -0
- package/index.js.map +1 -1
- package/package.json +14 -2
- package/runtime/core-aliases-early.js +94 -67
- package/runtime/core-aliases-early.js.map +1 -1
- package/shims/solid-jsx-runtime.d.ts +7 -0
- package/shims/solid-jsx-runtime.js +17 -0
- package/shims/solid-jsx-runtime.js.map +1 -0
package/configuration/angular.js
CHANGED
|
@@ -4,14 +4,42 @@ import fs from 'node:fs';
|
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
5
|
import angular from '@analogjs/vite-plugin-angular';
|
|
6
6
|
import { angularLinkerVitePlugin, angularLinkerVitePluginPost } from '../helpers/angular/angular-linker.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { synthesizeMissingInjectableFactories } from '../helpers/angular/synthesize-injectable-factories.js';
|
|
8
|
+
import { ensureSharedAngularLinker, resolveAngularFileSystem } from '../helpers/angular/shared-linker.js';
|
|
9
|
+
import { inlineDecoratorComponentTemplates } from '../helpers/angular/inline-decorator-component-templates.js';
|
|
10
|
+
import { appendComponentHmrRegistration, findComponentClassNames, INJECTION_MARKER as HMR_REGISTER_MARKER } from '../helpers/angular/inject-component-hmr-registration.js';
|
|
11
|
+
import { synthesizeDecoratorCtorParameters } from '../helpers/angular/synthesize-decorator-ctor-parameters.js';
|
|
12
|
+
import { containsRealNgDeclare, stripJsComments } from '../helpers/angular/util.js';
|
|
9
13
|
import { baseConfig } from './base.js';
|
|
10
14
|
import { getCliFlags } from '../helpers/cli-flags.js';
|
|
15
|
+
import { resolveRelativeToImportMeta } from '../helpers/import-meta-path.js';
|
|
16
|
+
import { resolveVerboseFlag } from '../helpers/logging.js';
|
|
17
|
+
// Lazily import the Angular linker factory function. Used by chunk-level linkers
|
|
18
|
+
// to create FRESH plugin instances per invocation (avoiding stale state in watch mode).
|
|
19
|
+
let _cachedLinkerFactory = null;
|
|
20
|
+
async function importLinkerFactory() {
|
|
21
|
+
if (_cachedLinkerFactory)
|
|
22
|
+
return _cachedLinkerFactory;
|
|
23
|
+
const req = createRequire(process.cwd() + '/package.json');
|
|
24
|
+
try {
|
|
25
|
+
const linkerPath = req.resolve('@angular/compiler-cli/linker/babel');
|
|
26
|
+
const linkerMod = await import(linkerPath);
|
|
27
|
+
_cachedLinkerFactory = linkerMod.createLinkerPlugin || linkerMod.createEs2015LinkerPlugin || null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
try {
|
|
31
|
+
const linkerMod = await import('@angular/compiler-cli/linker/babel');
|
|
32
|
+
_cachedLinkerFactory = linkerMod.createLinkerPlugin || linkerMod.createEs2015LinkerPlugin || null;
|
|
33
|
+
}
|
|
34
|
+
catch { }
|
|
35
|
+
}
|
|
36
|
+
return _cachedLinkerFactory;
|
|
37
|
+
}
|
|
11
38
|
// Rollup-level linker to guarantee Angular libraries are linked when included in the bundle graph.
|
|
12
39
|
function angularRollupLinker(projectRoot) {
|
|
13
40
|
let babel = null;
|
|
14
41
|
let createLinker = null;
|
|
42
|
+
let angularFileSystem = null;
|
|
15
43
|
const FILTER = /node_modules\/(?:@angular|@nativescript\/angular)\/.*\.[mc]?js$/;
|
|
16
44
|
async function ensureDeps() {
|
|
17
45
|
if (babel && createLinker)
|
|
@@ -35,6 +63,9 @@ function angularRollupLinker(projectRoot) {
|
|
|
35
63
|
}
|
|
36
64
|
catch { }
|
|
37
65
|
}
|
|
66
|
+
if (!angularFileSystem) {
|
|
67
|
+
angularFileSystem = await resolveAngularFileSystem(projectRoot);
|
|
68
|
+
}
|
|
38
69
|
}
|
|
39
70
|
return {
|
|
40
71
|
name: 'ns-angular-linker-rollup',
|
|
@@ -56,12 +87,9 @@ function angularRollupLinker(projectRoot) {
|
|
|
56
87
|
return null;
|
|
57
88
|
if (!forceLink && code.indexOf('\u0275\u0275ngDeclare') === -1 && code.indexOf('ɵɵngDeclare') === -1 && code.indexOf('ngDeclare') === -1)
|
|
58
89
|
return null;
|
|
59
|
-
const plugin = createLinker({ sourceMapping: false });
|
|
90
|
+
const plugin = createLinker({ sourceMapping: false, fileSystem: angularFileSystem });
|
|
60
91
|
if (debug) {
|
|
61
|
-
|
|
62
|
-
console.log('[ns-angular-linker][rollup-load] linking', cleanId);
|
|
63
|
-
}
|
|
64
|
-
catch { }
|
|
92
|
+
console.log('[ns-angular-linker][rollup-load] linking', cleanId);
|
|
65
93
|
}
|
|
66
94
|
const result = await babel.transformAsync(code, {
|
|
67
95
|
filename: cleanId,
|
|
@@ -92,12 +120,9 @@ function angularRollupLinker(projectRoot) {
|
|
|
92
120
|
if (!babel || !createLinker)
|
|
93
121
|
return null;
|
|
94
122
|
try {
|
|
95
|
-
const plugin = createLinker({ sourceMapping: false });
|
|
123
|
+
const plugin = createLinker({ sourceMapping: false, fileSystem: angularFileSystem });
|
|
96
124
|
if (debug) {
|
|
97
|
-
|
|
98
|
-
console.log('[ns-angular-linker][rollup] linking', cleanId);
|
|
99
|
-
}
|
|
100
|
-
catch { }
|
|
125
|
+
console.log('[ns-angular-linker][rollup] linking', cleanId);
|
|
101
126
|
}
|
|
102
127
|
const result = await babel.transformAsync(code, {
|
|
103
128
|
filename: cleanId,
|
|
@@ -126,76 +151,367 @@ let tsConfig = tsConfigAppPath;
|
|
|
126
151
|
if (!fs.existsSync(tsConfigAppPath) && fs.existsSync(tsConfigPath)) {
|
|
127
152
|
tsConfig = tsConfigPath;
|
|
128
153
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
154
|
+
function normalizeAngularWatchPath(filePath) {
|
|
155
|
+
return filePath
|
|
156
|
+
.split('?', 1)[0]
|
|
157
|
+
.replace(/\\/g, '/')
|
|
158
|
+
.replace(/^file:\/\//, '');
|
|
159
|
+
}
|
|
160
|
+
function normalizeAngularWatchKey(filePath) {
|
|
161
|
+
const normalizedPath = normalizeAngularWatchPath(filePath);
|
|
162
|
+
const fileSystemPath = normalizedPath.startsWith('/@fs/') ? normalizedPath.slice('/@fs'.length) : normalizedPath;
|
|
163
|
+
const normalizedProjectRoot = projectRoot.replace(/\\/g, '/').replace(/\/$/, '');
|
|
164
|
+
if (normalizedProjectRoot && fileSystemPath.startsWith(normalizedProjectRoot)) {
|
|
165
|
+
const relative = fileSystemPath.slice(normalizedProjectRoot.length);
|
|
166
|
+
return relative.startsWith('/') ? relative : `/${relative}`;
|
|
167
|
+
}
|
|
168
|
+
return fileSystemPath;
|
|
169
|
+
}
|
|
170
|
+
function getAngularWatchKeys(filePath) {
|
|
171
|
+
const normalizedPath = normalizeAngularWatchPath(filePath);
|
|
172
|
+
const keys = new Set();
|
|
173
|
+
keys.add(normalizedPath);
|
|
174
|
+
keys.add(normalizeAngularWatchKey(normalizedPath));
|
|
175
|
+
return Array.from(keys).filter(Boolean);
|
|
176
|
+
}
|
|
177
|
+
function resolveAngularWatchFilePath(filePath) {
|
|
178
|
+
const normalizedPath = normalizeAngularWatchPath(filePath);
|
|
179
|
+
const fileSystemPath = normalizedPath.startsWith('/@fs/') ? normalizedPath.slice('/@fs'.length) : normalizedPath;
|
|
180
|
+
if (path.isAbsolute(fileSystemPath) && fs.existsSync(fileSystemPath)) {
|
|
181
|
+
return fileSystemPath;
|
|
182
|
+
}
|
|
183
|
+
if (fileSystemPath.startsWith('/')) {
|
|
184
|
+
return path.resolve(projectRoot, `.${fileSystemPath}`);
|
|
185
|
+
}
|
|
186
|
+
return path.resolve(projectRoot, fileSystemPath);
|
|
187
|
+
}
|
|
188
|
+
function extractComponentAssetPaths(code, componentId) {
|
|
189
|
+
const componentPath = normalizeAngularWatchPath(componentId);
|
|
190
|
+
const assetPaths = new Set();
|
|
191
|
+
const resolveAssetPath = (assetPath) => normalizeAngularWatchPath(path.resolve(path.dirname(componentPath), assetPath));
|
|
192
|
+
// Blank out `//` and `/* */` comments before scanning. The regexes below
|
|
193
|
+
// are intentionally simple (no JS parser) so they would otherwise match
|
|
194
|
+
// commented-out `templateUrl` / `styleUrls` declarations and register
|
|
195
|
+
// phantom asset deps via `addWatchFile`. In current Rolldown-Vite that
|
|
196
|
+
// also enrolls them as `_addedImports`, which `vite:import-analysis`
|
|
197
|
+
// then tries to resolve — surfacing as a misleading
|
|
198
|
+
// `Failed to resolve import "<file>" from "<importer>". Does the file
|
|
199
|
+
// exist?` pre-transform error if the file (predictably) doesn't exist.
|
|
200
|
+
const scanCode = stripJsComments(code);
|
|
201
|
+
const templateUrlMatch = scanCode.match(/templateUrl\s*:\s*['"](.+?\.(?:html|htm))['"]/);
|
|
202
|
+
if (templateUrlMatch) {
|
|
203
|
+
assetPaths.add(resolveAssetPath(templateUrlMatch[1]));
|
|
204
|
+
}
|
|
205
|
+
const styleUrlMatch = scanCode.match(/styleUrl\s*:\s*['"](.+?\.(?:css|less|sass|scss))['"]/);
|
|
206
|
+
if (styleUrlMatch) {
|
|
207
|
+
assetPaths.add(resolveAssetPath(styleUrlMatch[1]));
|
|
208
|
+
}
|
|
209
|
+
const styleUrlsMatch = scanCode.match(/styleUrls\s*:\s*\[([\s\S]*?)\]/m);
|
|
210
|
+
if (styleUrlsMatch) {
|
|
211
|
+
for (const match of styleUrlsMatch[1].matchAll(/['"](.+?\.(?:css|less|sass|scss))['"]/g)) {
|
|
212
|
+
assetPaths.add(resolveAssetPath(match[1]));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return Array.from(assetPaths);
|
|
216
|
+
}
|
|
217
|
+
function createAngularPlugins(opts) {
|
|
218
|
+
const verbose = resolveVerboseFlag();
|
|
219
|
+
const assetToComponents = new Map();
|
|
220
|
+
const componentToAssets = new Map();
|
|
221
|
+
const pendingComponentInvalidations = new Set();
|
|
222
|
+
// Shared state between the `enforce: 'pre'` discovery plugin and the
|
|
223
|
+
// `enforce: 'post'` injection plugin. Maps a clean (no-querystring)
|
|
224
|
+
// .ts file id to the list of `@Component`-decorated class names found
|
|
225
|
+
// in its RAW TypeScript source. The pre plugin populates this map;
|
|
226
|
+
// the post plugin reads it to know which class names to register
|
|
227
|
+
// against the compiled output. Cleared on each pre-plugin invocation
|
|
228
|
+
// so renames or `@Component` removals don't leave stale entries.
|
|
229
|
+
const componentsByCleanId = new Map();
|
|
230
|
+
const untrackComponentAssets = (componentPath) => {
|
|
231
|
+
const previousAssets = componentToAssets.get(componentPath);
|
|
232
|
+
if (!previousAssets)
|
|
233
|
+
return;
|
|
234
|
+
for (const assetPath of previousAssets) {
|
|
235
|
+
const components = assetToComponents.get(assetPath);
|
|
236
|
+
if (!components)
|
|
237
|
+
continue;
|
|
238
|
+
components.delete(componentPath);
|
|
239
|
+
if (components.size === 0) {
|
|
240
|
+
assetToComponents.delete(assetPath);
|
|
142
241
|
}
|
|
143
|
-
|
|
242
|
+
}
|
|
243
|
+
componentToAssets.delete(componentPath);
|
|
244
|
+
};
|
|
245
|
+
const trackComponentAssets = (componentPath, assetPaths) => {
|
|
246
|
+
untrackComponentAssets(componentPath);
|
|
247
|
+
if (assetPaths.length === 0)
|
|
248
|
+
return;
|
|
249
|
+
const normalizedAssets = new Set(assetPaths.flatMap((assetPath) => getAngularWatchKeys(assetPath)));
|
|
250
|
+
componentToAssets.set(componentPath, normalizedAssets);
|
|
251
|
+
for (const assetPath of normalizedAssets) {
|
|
252
|
+
const components = assetToComponents.get(assetPath) || new Set();
|
|
253
|
+
components.add(componentPath);
|
|
254
|
+
assetToComponents.set(assetPath, components);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
const isCandidateComponentTs = (cleanId) => {
|
|
258
|
+
if (!cleanId.endsWith('.ts'))
|
|
259
|
+
return false;
|
|
260
|
+
if (cleanId.includes('/node_modules/'))
|
|
261
|
+
return false;
|
|
262
|
+
if (cleanId.endsWith('.d.ts'))
|
|
263
|
+
return false;
|
|
264
|
+
if (cleanId.endsWith('.spec.ts') || cleanId.endsWith('.test.ts'))
|
|
265
|
+
return false;
|
|
266
|
+
return true;
|
|
267
|
+
};
|
|
268
|
+
return [
|
|
269
|
+
// HMR self-registration runs in two phases:
|
|
270
|
+
//
|
|
271
|
+
// 1. (this plugin, `enforce: 'pre'`) Walk the raw TypeScript
|
|
272
|
+
// source for each user `.ts` file and record the names of
|
|
273
|
+
// any `@Component`-decorated classes into the shared
|
|
274
|
+
// `componentsByCleanId` map. Discovery has to happen on the
|
|
275
|
+
// raw source because the Analog Angular plugin rewrites
|
|
276
|
+
// `@Component(...)` into static metadata calls and removes
|
|
277
|
+
// the textual decorator pattern.
|
|
278
|
+
//
|
|
279
|
+
// 2. (`ns-component-hmr-register-post`, `enforce: 'post'`)
|
|
280
|
+
// After the Analog Angular plugin has compiled the file,
|
|
281
|
+
// append the global `__NS_HMR_REGISTER_COMPONENT__`
|
|
282
|
+
// registration calls keyed by the names recorded in step 1.
|
|
283
|
+
//
|
|
284
|
+
// Why the two-phase split: the Analog Angular plugin's `transform`
|
|
285
|
+
// returns its OWN regenerated compiled output (from its internal
|
|
286
|
+
// `outputFiles` cache populated at `buildStart`), discarding any
|
|
287
|
+
// code modifications applied earlier in the pipeline. We
|
|
288
|
+
// previously appended the registration snippet here, in the pre
|
|
289
|
+
// plugin, and the snippet was silently dropped — leaving the
|
|
290
|
+
// HMR class registry empty and `getFreshComponentClass` returning
|
|
291
|
+
// `found=false reason=no-registry` after every reboot.
|
|
292
|
+
//
|
|
293
|
+
// Placement notes that still apply:
|
|
294
|
+
// - `apply: 'serve'`: the registry runtime hook is dev-only;
|
|
295
|
+
// production builds never need self-registration.
|
|
296
|
+
// - Intentionally NOT gated on `hmrActive`. The injected
|
|
297
|
+
// snippet self-guards with
|
|
298
|
+
// `typeof globalThis.__NS_HMR_REGISTER_COMPONENT__ === 'function'`,
|
|
299
|
+
// so it's a no-op when the runtime hook isn't installed
|
|
300
|
+
// (e.g. `--no-hmr` users still serving modules through
|
|
301
|
+
// Vite). Gating the transform itself on `hmrActive` produced
|
|
302
|
+
// a silent failure mode where `--no-hmr` users got HMR
|
|
303
|
+
// machinery up but never got the registration calls
|
|
304
|
+
// injected, leaving the registry empty.
|
|
305
|
+
{
|
|
306
|
+
name: 'ns-component-hmr-register',
|
|
307
|
+
enforce: 'pre',
|
|
308
|
+
apply: 'serve',
|
|
309
|
+
transform(code, id) {
|
|
310
|
+
const cleanId = id.split('?', 1)[0];
|
|
311
|
+
if (!isCandidateComponentTs(cleanId))
|
|
312
|
+
return null;
|
|
313
|
+
const componentNames = findComponentClassNames(code);
|
|
314
|
+
if (componentNames.length === 0) {
|
|
315
|
+
// Drop any stale entry from a previous transform
|
|
316
|
+
// pass; the file may have lost its `@Component`
|
|
317
|
+
// decorator across a rename/refactor.
|
|
318
|
+
componentsByCleanId.delete(cleanId);
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
componentsByCleanId.set(cleanId, componentNames);
|
|
322
|
+
if (verbose) {
|
|
323
|
+
console.info(`[ns-hmr-diag][ns-component-hmr-register] discovered ${componentNames.length} component(s) in ${cleanId} (${componentNames.join(', ')})`);
|
|
324
|
+
}
|
|
325
|
+
// Discovery only — never modify the raw TS source. Any
|
|
326
|
+
// modification here is discarded by the Analog Angular
|
|
327
|
+
// plugin downstream; the actual snippet append happens
|
|
328
|
+
// in `ns-component-hmr-register-post`.
|
|
329
|
+
return null;
|
|
330
|
+
},
|
|
144
331
|
},
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
332
|
+
// Phase 2: append the HMR registration snippet to the compiled
|
|
333
|
+
// JS output produced by `@analogjs/vite-plugin-angular`. Runs
|
|
334
|
+
// `enforce: 'post'` so we see the post-Angular code (where the
|
|
335
|
+
// pre plugin's work would otherwise be discarded). Reads the
|
|
336
|
+
// component names recorded by the pre plugin via
|
|
337
|
+
// `componentsByCleanId`.
|
|
338
|
+
{
|
|
339
|
+
name: 'ns-component-hmr-register-post',
|
|
340
|
+
enforce: 'post',
|
|
341
|
+
apply: 'serve',
|
|
342
|
+
transform(code, id) {
|
|
343
|
+
const cleanId = id.split('?', 1)[0];
|
|
344
|
+
if (!isCandidateComponentTs(cleanId))
|
|
345
|
+
return null;
|
|
346
|
+
const componentNames = componentsByCleanId.get(cleanId);
|
|
347
|
+
if (!componentNames || componentNames.length === 0)
|
|
348
|
+
return null;
|
|
349
|
+
// Idempotency: the Vite cache may replay the transform
|
|
350
|
+
// pipeline on cached modules. The marker comment is
|
|
351
|
+
// inserted by `appendComponentHmrRegistration` and
|
|
352
|
+
// guards against double-injection. We also defensively
|
|
353
|
+
// short-circuit here so we don't have to allocate the
|
|
354
|
+
// suffix string on every cached re-run.
|
|
355
|
+
if (code.includes(HMR_REGISTER_MARKER))
|
|
356
|
+
return null;
|
|
357
|
+
const result = appendComponentHmrRegistration(code, componentNames);
|
|
358
|
+
if (!result.code)
|
|
359
|
+
return null;
|
|
360
|
+
if (verbose) {
|
|
361
|
+
console.info(`[ns-hmr-diag][ns-component-hmr-register-post] appended registrations for ${result.componentNames.length} component(s) in ${cleanId} (${result.componentNames.join(', ')})`);
|
|
362
|
+
}
|
|
363
|
+
// Returning `null` for the source map is acceptable for
|
|
364
|
+
// dev: lines 1..N (the original compiled body) keep
|
|
365
|
+
// the upstream Angular source map; the appended snippet
|
|
366
|
+
// is invisible to debuggers but harmless. For
|
|
367
|
+
// production-grade source maps a MagicString-based
|
|
368
|
+
// pass-through could be used; not required for HMR.
|
|
369
|
+
return { code: result.code, map: null };
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
// Allow external html template changes to trigger hot reload: Make .ts files depend on their .html templates
|
|
373
|
+
{
|
|
374
|
+
name: 'angular-template-deps',
|
|
375
|
+
enforce: 'pre',
|
|
376
|
+
transform(code, id) {
|
|
377
|
+
const componentPath = normalizeAngularWatchPath(id);
|
|
378
|
+
const componentKey = normalizeAngularWatchKey(id);
|
|
379
|
+
if (!componentKey.endsWith('.ts'))
|
|
380
|
+
return null;
|
|
381
|
+
const assetPaths = extractComponentAssetPaths(code, componentPath);
|
|
382
|
+
trackComponentAssets(componentKey, assetPaths);
|
|
383
|
+
for (const assetPath of assetPaths) {
|
|
384
|
+
this.addWatchFile(assetPath);
|
|
385
|
+
}
|
|
386
|
+
// Diagnostic: surface which .ts files we've registered
|
|
387
|
+
// asset (template/styleUrls) dependencies for. This is
|
|
388
|
+
// the first fence the HTML→TS invalidation pipeline must
|
|
389
|
+
// pass — if we never see a [tracking] log for the
|
|
390
|
+
// component we're editing, the watcher will never fire
|
|
391
|
+
// and `pendingComponentInvalidations` stays empty.
|
|
392
|
+
if (verbose) {
|
|
393
|
+
console.info(`[ns-hmr-diag][angular-template-deps] [tracking] componentKey=${componentKey} assets=${assetPaths.length} (${assetPaths.slice(0, 4).join(', ')})`);
|
|
394
|
+
}
|
|
395
|
+
return null;
|
|
396
|
+
},
|
|
397
|
+
watchChange(id) {
|
|
398
|
+
const changedPath = normalizeAngularWatchPath(id);
|
|
399
|
+
const components = new Set();
|
|
400
|
+
for (const assetKey of getAngularWatchKeys(changedPath)) {
|
|
401
|
+
for (const componentPath of assetToComponents.get(assetKey) || []) {
|
|
402
|
+
components.add(componentPath);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (components?.size) {
|
|
406
|
+
for (const componentPath of components) {
|
|
407
|
+
pendingComponentInvalidations.add(componentPath);
|
|
408
|
+
}
|
|
409
|
+
if (verbose) {
|
|
410
|
+
console.info(`[ns-hmr-diag][angular-template-deps] watchChange [via assetToComponents] changed=${changedPath} → invalidating ${components.size} component(s):`, Array.from(components));
|
|
411
|
+
}
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
if (/\.(html|htm)$/i.test(changedPath)) {
|
|
415
|
+
const componentPath = changedPath.replace(/\.(html|htm)$/i, '.ts');
|
|
416
|
+
const exists = fs.existsSync(resolveAngularWatchFilePath(componentPath));
|
|
417
|
+
if (exists) {
|
|
418
|
+
const componentKey = normalizeAngularWatchKey(componentPath);
|
|
419
|
+
pendingComponentInvalidations.add(componentKey);
|
|
420
|
+
if (verbose) {
|
|
421
|
+
console.info(`[ns-hmr-diag][angular-template-deps] watchChange [via fallback .html→.ts] changed=${changedPath} componentKey=${componentKey}`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
else if (verbose) {
|
|
425
|
+
console.info(`[ns-hmr-diag][angular-template-deps] watchChange [no companion .ts found] changed=${changedPath} expectedTs=${componentPath}`);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
shouldTransformCachedModule({ id }) {
|
|
430
|
+
const componentPath = normalizeAngularWatchKey(id);
|
|
431
|
+
if (!pendingComponentInvalidations.has(componentPath))
|
|
432
|
+
return null;
|
|
433
|
+
pendingComponentInvalidations.delete(componentPath);
|
|
434
|
+
if (verbose) {
|
|
435
|
+
console.info(`[ns-hmr-diag][angular-template-deps] shouldTransformCachedModule → re-transform componentKey=${componentPath}`);
|
|
436
|
+
}
|
|
437
|
+
return true;
|
|
438
|
+
},
|
|
179
439
|
},
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
440
|
+
// Transform Angular partial declarations in node_modules to avoid runtime JIT
|
|
441
|
+
// Pass the project root so linker deps resolve from the app, not the plugin package.
|
|
442
|
+
angularLinkerVitePlugin(process.cwd()),
|
|
443
|
+
// Simplify: rely on Vite pre plugin (load/transform) for linking; Rollup safety net disabled unless re-enabled later
|
|
444
|
+
// angularRollupLinker(process.cwd()),
|
|
445
|
+
...angular({
|
|
446
|
+
experimental: {
|
|
447
|
+
useAngularCompilationAPI: opts.useAngularCompilationAPI,
|
|
448
|
+
},
|
|
449
|
+
liveReload: false, // Disable live reload in favor of HMR
|
|
450
|
+
tsconfig: tsConfig,
|
|
451
|
+
}),
|
|
452
|
+
// Post-phase linker to catch any declarations introduced after other transforms (including project code)
|
|
453
|
+
angularLinkerVitePluginPost(process.cwd()),
|
|
454
|
+
// Enforce: fully disable dependency optimization during serve to avoid rxjs esm5 crawling and OOM
|
|
455
|
+
{
|
|
456
|
+
name: 'ns-disable-optimize-deps',
|
|
457
|
+
enforce: 'post',
|
|
458
|
+
apply: 'serve',
|
|
459
|
+
config(userConfig) {
|
|
460
|
+
const od = userConfig?.optimizeDeps || {};
|
|
461
|
+
const prevExclude = Array.isArray(od.exclude) ? od.exclude : [];
|
|
462
|
+
const exclude = new Set(prevExclude);
|
|
463
|
+
['@nativescript/core', 'rxjs', '@valor/nativescript-websockets', 'set-value', 'react', 'react-reconciler', 'react-nativescript'].forEach((x) => exclude.add(x));
|
|
464
|
+
return {
|
|
465
|
+
optimizeDeps: {
|
|
466
|
+
noDiscovery: true,
|
|
467
|
+
entries: [],
|
|
468
|
+
include: [],
|
|
469
|
+
exclude: Array.from(exclude),
|
|
470
|
+
rolldownOptions: {
|
|
471
|
+
...(od.rolldownOptions || {}),
|
|
472
|
+
plugins: [],
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
};
|
|
476
|
+
},
|
|
477
|
+
configResolved(resolved) {
|
|
478
|
+
const resolvedConfig = resolved;
|
|
479
|
+
const deps = (resolvedConfig.optimizeDeps || (resolvedConfig.optimizeDeps = {}));
|
|
480
|
+
deps.noDiscovery = true;
|
|
481
|
+
deps.entries = [];
|
|
482
|
+
deps.include = [];
|
|
483
|
+
const exclude = new Set(Array.isArray(deps.exclude) ? deps.exclude : []);
|
|
484
|
+
['@nativescript/core', 'rxjs', '@valor/nativescript-websockets', 'set-value', 'react', 'react-reconciler', 'react-nativescript'].forEach((x) => exclude.add(x));
|
|
485
|
+
deps.exclude = Array.from(exclude);
|
|
486
|
+
const rolldownOptions = (deps.rolldownOptions || (deps.rolldownOptions = {}));
|
|
487
|
+
rolldownOptions.plugins = [];
|
|
488
|
+
},
|
|
190
489
|
},
|
|
191
|
-
|
|
192
|
-
|
|
490
|
+
];
|
|
491
|
+
}
|
|
193
492
|
export const angularConfig = ({ mode }) => {
|
|
493
|
+
const useSingleBundleDevOutput = mode === 'development' && !hmrActive;
|
|
494
|
+
const plugins = createAngularPlugins({
|
|
495
|
+
// Vite build --watch with the legacy Analog compilation path can regress
|
|
496
|
+
// Angular app sources from Ivy output back to decorator emit on rebuild.
|
|
497
|
+
// Restrict the newer compilation API to NativeScript's development no-HMR
|
|
498
|
+
// flow, which is where the unstable rebuilds occur today.
|
|
499
|
+
useAngularCompilationAPI: useSingleBundleDevOutput,
|
|
500
|
+
});
|
|
194
501
|
const disableAnimations = true;
|
|
195
502
|
//process.env.NS_DISABLE_NG_ANIMATIONS === "1" ||
|
|
196
503
|
//process.env.NS_DISABLE_NG_ANIMATIONS === "true";
|
|
197
504
|
// Post-link emitted chunks to catch any remaining partial declarations that slipped through
|
|
198
505
|
// due to plugin order or external transforms.
|
|
506
|
+
const applyAngularChunkPostProcessing = (code, options = {}) => {
|
|
507
|
+
const codeWithInjectables = synthesizeMissingInjectableFactories(code, {
|
|
508
|
+
vendorInjectExport: options.vendorInjectExport,
|
|
509
|
+
});
|
|
510
|
+
const codeWithCtorParameters = synthesizeDecoratorCtorParameters(codeWithInjectables);
|
|
511
|
+
return inlineDecoratorComponentTemplates(codeWithCtorParameters, {
|
|
512
|
+
projectRoot: process.cwd(),
|
|
513
|
+
});
|
|
514
|
+
};
|
|
199
515
|
const postLinker = {
|
|
200
516
|
name: 'ns-angular-linker-post',
|
|
201
517
|
apply: 'build',
|
|
@@ -206,13 +522,22 @@ export const angularConfig = ({ mode }) => {
|
|
|
206
522
|
return false;
|
|
207
523
|
return Object.keys(chunk.modules).some((m) => m.includes('node_modules/@nativescript/angular/fesm2022/nativescript-angular-polyfills.mjs'));
|
|
208
524
|
}
|
|
209
|
-
const { babel
|
|
210
|
-
if (!babel
|
|
525
|
+
const { babel } = await ensureSharedAngularLinker(process.cwd());
|
|
526
|
+
if (!babel)
|
|
527
|
+
return;
|
|
528
|
+
const fileSystem = await resolveAngularFileSystem(process.cwd());
|
|
529
|
+
const linkerFactory = await importLinkerFactory();
|
|
530
|
+
if (!linkerFactory)
|
|
211
531
|
return;
|
|
212
532
|
const strict = process.env.NS_STRICT_NG_LINK === '1' || process.env.NS_STRICT_NG_LINK === 'true';
|
|
213
533
|
const enforceStrict = process.env.NS_STRICT_NG_LINK_ENFORCE === '1' || process.env.NS_STRICT_NG_LINK_ENFORCE === 'true';
|
|
214
534
|
const debug = process.env.VITE_DEBUG_LOGS === '1' || process.env.VITE_DEBUG_LOGS === 'true';
|
|
215
535
|
const unlinked = [];
|
|
536
|
+
const vendorInjectExport = (() => {
|
|
537
|
+
const vendorChunk = Object.entries(bundle).find(([name, value]) => value && value.type === 'chunk' && /(^|\/)vendor\.mjs$/.test(name));
|
|
538
|
+
const vendorCode = vendorChunk ? vendorChunk[1].code : undefined;
|
|
539
|
+
return vendorCode?.match(/\binject as ([A-Za-z_$][\w$]*)/)?.[1];
|
|
540
|
+
})();
|
|
216
541
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
217
542
|
if (!fileName.endsWith('.mjs') && !fileName.endsWith('.js'))
|
|
218
543
|
continue;
|
|
@@ -222,29 +547,31 @@ export const angularConfig = ({ mode }) => {
|
|
|
222
547
|
continue;
|
|
223
548
|
const isNsPolyfills = isNsAngularPolyfillsChunk(chunk);
|
|
224
549
|
try {
|
|
550
|
+
// Create a FRESH linker plugin per chunk — the linker may have
|
|
551
|
+
// internal state that becomes stale across watch-mode rebuild cycles.
|
|
552
|
+
const freshPlugin = linkerFactory({ sourceMapping: false, fileSystem });
|
|
225
553
|
const res = await babel.transformAsync(code, {
|
|
226
554
|
filename: fileName,
|
|
227
555
|
configFile: false,
|
|
228
556
|
babelrc: false,
|
|
229
557
|
sourceMaps: false,
|
|
230
558
|
compact: false,
|
|
231
|
-
plugins: [
|
|
559
|
+
plugins: [freshPlugin],
|
|
232
560
|
});
|
|
233
|
-
const
|
|
561
|
+
const linkedCode = res?.code && res.code !== code ? res.code : code;
|
|
562
|
+
const finalCode = applyAngularChunkPostProcessing(linkedCode, { vendorInjectExport });
|
|
234
563
|
if (finalCode !== code) {
|
|
235
564
|
chunk.code = finalCode;
|
|
236
565
|
if (debug) {
|
|
237
|
-
|
|
238
|
-
console.log('[ns-angular-linker][post] linked', fileName, isNsPolyfills ? '(polyfills)' : '');
|
|
239
|
-
}
|
|
240
|
-
catch { }
|
|
566
|
+
console.log('[ns-angular-linker][post] linked', fileName, isNsPolyfills ? '(polyfills)' : '');
|
|
241
567
|
}
|
|
242
568
|
}
|
|
243
569
|
if (strict && !isNsPolyfills && containsRealNgDeclare(finalCode)) {
|
|
244
570
|
unlinked.push(fileName);
|
|
245
571
|
}
|
|
246
572
|
}
|
|
247
|
-
catch {
|
|
573
|
+
catch (e) {
|
|
574
|
+
console.warn(`[ns-angular-linker][post] linking FAILED for ${fileName}:`, e?.message || e);
|
|
248
575
|
if (strict)
|
|
249
576
|
unlinked.push(fileName);
|
|
250
577
|
}
|
|
@@ -282,89 +609,94 @@ export const angularConfig = ({ mode }) => {
|
|
|
282
609
|
throw new Error(message);
|
|
283
610
|
}
|
|
284
611
|
else {
|
|
285
|
-
|
|
286
|
-
console.warn(`[ns-angular-linker-post] ${message}`);
|
|
287
|
-
}
|
|
288
|
-
catch { }
|
|
612
|
+
console.warn(`[ns-angular-linker-post] ${message}`);
|
|
289
613
|
}
|
|
290
614
|
}
|
|
291
615
|
},
|
|
292
616
|
};
|
|
293
|
-
// Safety net: transform each rendered chunk to link any remaining ɵɵngDeclare* call sites
|
|
617
|
+
// Safety net: transform each rendered chunk to link any remaining ɵɵngDeclare* call sites.
|
|
618
|
+
// IMPORTANT: create a FRESH linker plugin per invocation — the shared instance may have
|
|
619
|
+
// stale internal state from a prior build cycle, causing silent failures in watch-mode rebuilds.
|
|
294
620
|
const renderChunkLinker = {
|
|
295
621
|
name: 'ns-angular-linker-render',
|
|
296
622
|
apply: 'build',
|
|
297
623
|
enforce: 'post',
|
|
298
624
|
async renderChunk(code, chunk) {
|
|
625
|
+
if (!code)
|
|
626
|
+
return null;
|
|
627
|
+
const filename = chunk.fileName || chunk.name || 'chunk.mjs';
|
|
628
|
+
const debug = process.env.VITE_DEBUG_LOGS === '1' || process.env.VITE_DEBUG_LOGS === 'true';
|
|
299
629
|
try {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
630
|
+
let transformed = code;
|
|
631
|
+
if (containsRealNgDeclare(code)) {
|
|
632
|
+
const { babel } = await ensureSharedAngularLinker(process.cwd());
|
|
633
|
+
if (!babel)
|
|
634
|
+
return null;
|
|
635
|
+
const fileSystem = await resolveAngularFileSystem(process.cwd());
|
|
636
|
+
// Fresh plugin per chunk — avoids stale linker state across watch-mode rebuilds
|
|
637
|
+
const freshPlugin = (await importLinkerFactory())?.({ sourceMapping: false, fileSystem });
|
|
638
|
+
if (!freshPlugin)
|
|
639
|
+
return null;
|
|
640
|
+
const runLink = async (input) => {
|
|
641
|
+
const result = await babel.transformAsync(input, {
|
|
642
|
+
filename,
|
|
643
|
+
configFile: false,
|
|
644
|
+
babelrc: false,
|
|
645
|
+
sourceMaps: false,
|
|
646
|
+
compact: false,
|
|
647
|
+
plugins: [freshPlugin],
|
|
648
|
+
});
|
|
649
|
+
return result?.code ?? input;
|
|
650
|
+
};
|
|
651
|
+
transformed = await runLink(code);
|
|
652
|
+
if (containsRealNgDeclare(transformed)) {
|
|
653
|
+
transformed = await runLink(transformed);
|
|
654
|
+
}
|
|
323
655
|
}
|
|
656
|
+
transformed = applyAngularChunkPostProcessing(transformed);
|
|
324
657
|
if (transformed !== code) {
|
|
325
658
|
if (debug) {
|
|
326
|
-
|
|
327
|
-
console.log('[ns-angular-linker][render] linked', filename);
|
|
328
|
-
}
|
|
329
|
-
catch { }
|
|
659
|
+
console.log('[ns-angular-linker][render] linked', filename);
|
|
330
660
|
}
|
|
331
661
|
return { code: transformed, map: null };
|
|
332
662
|
}
|
|
333
663
|
}
|
|
334
|
-
catch {
|
|
664
|
+
catch (e) {
|
|
665
|
+
console.warn(`[ns-angular-linker][render] linking FAILED for ${filename}:`, e?.message || e);
|
|
666
|
+
}
|
|
335
667
|
return null;
|
|
336
668
|
},
|
|
337
669
|
};
|
|
338
670
|
const enableRollupLinker = process.env.NS_ENABLE_ROLLUP_LINKER === '1' || process.env.NS_ENABLE_ROLLUP_LINKER === 'true' || hmrActive;
|
|
339
|
-
|
|
671
|
+
// Build a single merged alias array to avoid property override conflicts.
|
|
672
|
+
// Previously the disableAnimations spread added a second `resolve` key
|
|
673
|
+
// that silently clobbered the fesm2022 and RxJS aliases.
|
|
674
|
+
const angularAliases = [
|
|
675
|
+
// Map Angular deep ESM paths to bare package ids
|
|
676
|
+
{ find: /^@angular\/([^/]+)\/fesm2022\/.*\.mjs$/, replacement: '@angular/$1' },
|
|
677
|
+
{ find: /^@nativescript\/angular\/fesm2022\/.*\.mjs$/, replacement: '@nativescript/angular' },
|
|
678
|
+
// RxJS esm5 → esm redirects removed: Vite 8 enforces the rxjs `exports` field,
|
|
679
|
+
// blocking deep path aliases. Instead, the `es2015` resolve condition is added
|
|
680
|
+
// below so rxjs resolves to its modern ESM builds via the exports map.
|
|
681
|
+
];
|
|
682
|
+
if (disableAnimations) {
|
|
683
|
+
angularAliases.push({
|
|
684
|
+
find: /^@angular\/animations(\/.+)?$/, // match subpaths too
|
|
685
|
+
replacement: resolveRelativeToImportMeta(import.meta.url, '../shims/angular-animations-stub.js'),
|
|
686
|
+
}, {
|
|
687
|
+
find: /^@angular\/platform-browser\/animations(\/.+)?$/,
|
|
688
|
+
replacement: resolveRelativeToImportMeta(import.meta.url, '../shims/angular-animations-stub.js'),
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
const config = mergeConfig(baseConfig({ mode, flavor: 'angular' }), {
|
|
340
692
|
plugins: [...plugins, ...(enableRollupLinker ? [angularRollupLinker(process.cwd())] : []), renderChunkLinker, postLinker],
|
|
341
|
-
// Always alias fesm2022 deep imports to package root so vendor bridge can externalize properly
|
|
342
693
|
resolve: {
|
|
343
|
-
alias:
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
{ find: /^rxjs\/dist\/esm5\/(.*)$/, replacement: 'rxjs/dist/esm2015/$1' },
|
|
349
|
-
{ find: /^rxjs\/operators$/, replacement: 'rxjs/dist/esm2015/operators/index.js' },
|
|
350
|
-
{ find: /^rxjs$/, replacement: 'rxjs/dist/esm2015/index.js' },
|
|
351
|
-
// Existing optional animations shims
|
|
352
|
-
],
|
|
694
|
+
alias: angularAliases,
|
|
695
|
+
// Add 'es2015' condition so RxJS resolves to dist/esm (modern ESM) rather
|
|
696
|
+
// than dist/esm5 via the 'default' condition. This avoids the esm5 module
|
|
697
|
+
// explosion and OOM while respecting the package's exports field in Vite 8.
|
|
698
|
+
conditions: ['es2015'],
|
|
353
699
|
},
|
|
354
|
-
...(disableAnimations && {
|
|
355
|
-
resolve: {
|
|
356
|
-
alias: [
|
|
357
|
-
{
|
|
358
|
-
find: /^@angular\/animations(\/.+)?$/, // match subpaths too
|
|
359
|
-
replacement: new URL('../shims/angular-animations-stub.js', import.meta.url).pathname,
|
|
360
|
-
},
|
|
361
|
-
{
|
|
362
|
-
find: /^@angular\/platform-browser\/animations(\/.+)?$/,
|
|
363
|
-
replacement: new URL('../shims/angular-animations-stub.js', import.meta.url).pathname,
|
|
364
|
-
},
|
|
365
|
-
],
|
|
366
|
-
},
|
|
367
|
-
}),
|
|
368
700
|
// Disable dependency optimization entirely for NativeScript Angular HMR.
|
|
369
701
|
// Vite 5.1+: use noDiscovery with an empty include list (disabled was removed).
|
|
370
702
|
// The HTTP loader + vendor bridge manage dependencies; pre-bundling can OOM.
|
|
@@ -376,5 +708,19 @@ export const angularConfig = ({ mode }) => {
|
|
|
376
708
|
rolldownOptions: { plugins: [] },
|
|
377
709
|
},
|
|
378
710
|
});
|
|
711
|
+
if (useSingleBundleDevOutput) {
|
|
712
|
+
const build = (config.build ?? (config.build = {}));
|
|
713
|
+
const rolldownOptions = (build.rolldownOptions ?? (build.rolldownOptions = {}));
|
|
714
|
+
const outputConfigs = Array.isArray(rolldownOptions.output) ? rolldownOptions.output : [rolldownOptions.output ?? {}];
|
|
715
|
+
for (const output of outputConfigs) {
|
|
716
|
+
// Angular non-HMR reloads are more reliable when rebuilds keep a single boot bundle.
|
|
717
|
+
// This avoids watch-time chunk alias/name drift that can leave the native app reloading into stale split points.
|
|
718
|
+
delete output.manualChunks;
|
|
719
|
+
delete output.chunkFileNames;
|
|
720
|
+
output.codeSplitting = false;
|
|
721
|
+
}
|
|
722
|
+
rolldownOptions.output = Array.isArray(rolldownOptions.output) ? outputConfigs : outputConfigs[0];
|
|
723
|
+
}
|
|
724
|
+
return config;
|
|
379
725
|
};
|
|
380
726
|
//# sourceMappingURL=angular.js.map
|