@nativescript/vite 0.0.1-alpha.0 → 0.0.1-alpha.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.
- package/dist/configuration/base.js +44 -35
- package/dist/helpers/main-entry.d.ts +1 -1
- package/dist/helpers/main-entry.js +64 -21
- package/dist/helpers/ns-cli-plugins.d.ts +3 -0
- package/dist/helpers/ns-cli-plugins.js +92 -16
- package/dist/helpers/preserve-imports.d.ts +2 -0
- package/dist/helpers/preserve-imports.js +19 -0
- package/dist/helpers/side-effects.d.ts +14 -0
- package/dist/helpers/side-effects.js +69 -0
- package/dist/helpers/ts-config-paths.js +3 -1
- package/package.json +1 -1
|
@@ -18,6 +18,7 @@ import { hmrPlugin, cliPlugin } from "../helpers/ns-cli-plugins.js";
|
|
|
18
18
|
import { dynamicImportPlugin } from "../helpers/dynamic-import-plugin.js";
|
|
19
19
|
import { mainEntryPlugin } from "../helpers/main-entry.js";
|
|
20
20
|
import { determineProjectFlavor } from "../helpers/flavor.js";
|
|
21
|
+
import { preserveImportsPlugin } from "../helpers/preserve-imports.js";
|
|
21
22
|
import { externalConfigMerges, applyExternalConfigs, } from "../helpers/external-configs.js";
|
|
22
23
|
const debugViteLogs = !!process.env.VITE_DEBUG_PATHS;
|
|
23
24
|
const projectRoot = getProjectRootPath();
|
|
@@ -36,7 +37,7 @@ export const baseConfig = ({ mode }) => {
|
|
|
36
37
|
obj[rawKey] = rest.length === 0 ? true : rest.join("=");
|
|
37
38
|
return obj;
|
|
38
39
|
}, {});
|
|
39
|
-
console.log("cliFlags:", cliFlags);
|
|
40
|
+
// console.log("cliFlags:", cliFlags);
|
|
40
41
|
const debug = !!cliFlags.viteDebug || !!process.env.DEBUG || targetMode === "development";
|
|
41
42
|
if (debug) {
|
|
42
43
|
console.log("--------------");
|
|
@@ -50,6 +51,25 @@ export const baseConfig = ({ mode }) => {
|
|
|
50
51
|
// Create TypeScript aliases with platform support
|
|
51
52
|
const tsConfigData = getTsConfigData(debugViteLogs, platform);
|
|
52
53
|
// Common resolve configuration for both main and worker builds
|
|
54
|
+
// Build platform-aware extension preference order and exclude the opposite platform
|
|
55
|
+
const platformExtensions = (() => {
|
|
56
|
+
const base = [".tsx", ".jsx", ".ts", ".js"];
|
|
57
|
+
const exts = [];
|
|
58
|
+
if (platform === "android") {
|
|
59
|
+
exts.push(".android.tsx", ".tsx", ".android.jsx", ".jsx", ".android.ts", ".ts", ".android.js", ".js");
|
|
60
|
+
}
|
|
61
|
+
else if (platform === "ios" || platform === "visionos") {
|
|
62
|
+
// Treat visionOS like iOS for file resolution
|
|
63
|
+
exts.push(".ios.tsx", ".tsx", ".ios.jsx", ".jsx", ".ios.ts", ".ts", ".ios.js", ".js");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// Fallback: no platform-specific preference
|
|
67
|
+
exts.push(...base);
|
|
68
|
+
}
|
|
69
|
+
// Always allow these last
|
|
70
|
+
exts.push(".mjs", ".json");
|
|
71
|
+
return exts;
|
|
72
|
+
})();
|
|
53
73
|
const resolveConfig = {
|
|
54
74
|
// ensures Vite prefers ESM entry‑points
|
|
55
75
|
mainFields: ["module", "main"],
|
|
@@ -73,22 +93,7 @@ export const baseConfig = ({ mode }) => {
|
|
|
73
93
|
// optional: "@" → src/
|
|
74
94
|
{ find: "@", replacement: path.resolve(projectRoot, "src") },
|
|
75
95
|
],
|
|
76
|
-
extensions:
|
|
77
|
-
".ios.tsx",
|
|
78
|
-
".android.tsx",
|
|
79
|
-
".tsx",
|
|
80
|
-
".ios.jsx",
|
|
81
|
-
".android.jsx",
|
|
82
|
-
".jsx",
|
|
83
|
-
".ios.ts",
|
|
84
|
-
".android.ts",
|
|
85
|
-
".ts",
|
|
86
|
-
".ios.js",
|
|
87
|
-
".android.js",
|
|
88
|
-
".js",
|
|
89
|
-
".mjs",
|
|
90
|
-
".json",
|
|
91
|
-
],
|
|
96
|
+
extensions: platformExtensions,
|
|
92
97
|
preserveSymlinks: true,
|
|
93
98
|
};
|
|
94
99
|
// Common define configuration for both main and worker builds
|
|
@@ -136,8 +141,16 @@ export const baseConfig = ({ mode }) => {
|
|
|
136
141
|
global: "globalThis",
|
|
137
142
|
},
|
|
138
143
|
},
|
|
144
|
+
// Avoid pre-bundling NativeScript core to prevent esbuild from stripping side-effectful modules
|
|
145
|
+
exclude: [
|
|
146
|
+
"@nativescript/core",
|
|
147
|
+
"@nativescript/core/ui/frame",
|
|
148
|
+
"@nativescript/core/ui/frame/activity",
|
|
149
|
+
],
|
|
139
150
|
},
|
|
140
151
|
plugins: [
|
|
152
|
+
// Ensure explicit keep markers are honored
|
|
153
|
+
preserveImportsPlugin(),
|
|
141
154
|
// TODO: make flavor plugins dynamic
|
|
142
155
|
// ...flavorPlugins,
|
|
143
156
|
...commonjsPlugins,
|
|
@@ -151,14 +164,12 @@ export const baseConfig = ({ mode }) => {
|
|
|
151
164
|
defaultIsModuleExports: "auto",
|
|
152
165
|
transformMixedEsModules: true,
|
|
153
166
|
// Ignore optional dependencies that are meant to fail gracefully
|
|
154
|
-
ignore: [
|
|
155
|
-
"@nativescript/android",
|
|
156
|
-
"@nativescript/ios",
|
|
157
|
-
],
|
|
167
|
+
ignore: ["@nativescript/android", "@nativescript/ios"],
|
|
158
168
|
}),
|
|
159
169
|
nsConfigAsJsonPlugin(),
|
|
160
170
|
NativeScriptPlugin({ platform }),
|
|
161
|
-
|
|
171
|
+
// Ensure globals and Android activity are included early via virtual entry
|
|
172
|
+
mainEntryPlugin(cliFlags, debug, platform),
|
|
162
173
|
dynamicImportPlugin(),
|
|
163
174
|
// Transform Vite worker URLs to NativeScript format AFTER bundling
|
|
164
175
|
workerUrlPlugin(),
|
|
@@ -221,6 +232,11 @@ export const baseConfig = ({ mode }) => {
|
|
|
221
232
|
include: [/node_modules/],
|
|
222
233
|
},
|
|
223
234
|
rollupOptions: {
|
|
235
|
+
treeshake: {
|
|
236
|
+
// Preserve side effects for NativeScript core so classes/functions
|
|
237
|
+
// aren't tree-shaken out of vendor.mjs.
|
|
238
|
+
moduleSideEffects: (id) => /node_modules[\\\/]\@nativescript[\\\/]core[\\\/]/.test(id) || null,
|
|
239
|
+
},
|
|
224
240
|
input: "virtual:entry-with-polyfills",
|
|
225
241
|
output: {
|
|
226
242
|
dir: path.resolve(projectRoot, "dist"),
|
|
@@ -239,19 +255,12 @@ export const baseConfig = ({ mode }) => {
|
|
|
239
255
|
// Create single vendor chunk - no separate globals chunk to avoid circular deps
|
|
240
256
|
manualChunks(id) {
|
|
241
257
|
if (id.includes("node_modules")) {
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
if
|
|
245
|
-
|
|
246
|
-
"@nativescript/angular"
|
|
247
|
-
"@nativescript/
|
|
248
|
-
"@valor/nativescript-websockets",
|
|
249
|
-
"make-error",
|
|
250
|
-
// "source-map-js",
|
|
251
|
-
"zone.js",
|
|
252
|
-
"/globals",
|
|
253
|
-
"/polyfills",
|
|
254
|
-
].includes(id)) {
|
|
258
|
+
// Keep common dependencies in the main bundle
|
|
259
|
+
// Very Important: keep Angular, NS Angular and core in main bundle to avoid issues with DI
|
|
260
|
+
// All flavors can do same if encounter ordering issues
|
|
261
|
+
if (id.includes("@angular/") ||
|
|
262
|
+
id.includes("@nativescript/angular") ||
|
|
263
|
+
id.includes("@nativescript/core")) {
|
|
255
264
|
return undefined; // Keep in main bundle
|
|
256
265
|
}
|
|
257
266
|
return "vendor";
|
|
@@ -16,9 +16,9 @@ const polyfillsPath = getProjectFilePath("src/polyfills.ts");
|
|
|
16
16
|
const polyfillsExists = fs.existsSync(polyfillsPath);
|
|
17
17
|
// console.log("polyfillsPath:", polyfillsPath);
|
|
18
18
|
// console.log("polyfillsExists:", polyfillsExists);
|
|
19
|
-
const VIRTUAL_ID =
|
|
20
|
-
const RESOLVED =
|
|
21
|
-
export function mainEntryPlugin(cliFlags, debug) {
|
|
19
|
+
const VIRTUAL_ID = "virtual:entry-with-polyfills";
|
|
20
|
+
const RESOLVED = "\0" + VIRTUAL_ID;
|
|
21
|
+
export function mainEntryPlugin(cliFlags, debug, platform) {
|
|
22
22
|
return {
|
|
23
23
|
name: "main-entry",
|
|
24
24
|
resolveId(id) {
|
|
@@ -30,43 +30,86 @@ export function mainEntryPlugin(cliFlags, debug) {
|
|
|
30
30
|
load(id) {
|
|
31
31
|
if (id === RESOLVED) {
|
|
32
32
|
let imports = "";
|
|
33
|
+
// Align with webpack entry order: core globals and bundle entry points first
|
|
34
|
+
imports += `import '@nativescript/core/globals/index';\n`;
|
|
35
|
+
// // explicit extension helps some bundlers to retain side effects
|
|
36
|
+
imports += `import '@nativescript/core/bundle-entry-points';\n`;
|
|
37
|
+
// Ensure Android app components are included
|
|
38
|
+
if (platform === "android") {
|
|
39
|
+
// Import explicit Android variants with extension to avoid resolution ambiguity
|
|
40
|
+
imports += `import * as __ns_android_frame from '@nativescript/core/ui/frame/index.android.js?ns-keep';\n`;
|
|
41
|
+
imports += `import * as __ns_android_activity from '@nativescript/core/ui/frame/activity.android.js?ns-keep';\n`;
|
|
42
|
+
// Reference bindings to keep the modules in the graph even if they only have side effects
|
|
43
|
+
imports += `void __ns_android_frame; void __ns_android_activity;\n`;
|
|
44
|
+
// This may still be needed - needs more testing
|
|
45
|
+
// Ensure commonly tree-shaken Android UI modules are included so SBG
|
|
46
|
+
// discovers their Java listener/impl classes. Keep imports minimal but
|
|
47
|
+
// comprehensive across the missing bindings list.
|
|
48
|
+
// const __ns_android_modules = [
|
|
49
|
+
// "@nativescript/core/application",
|
|
50
|
+
// "@nativescript/core/text",
|
|
51
|
+
// "@nativescript/core/timer",
|
|
52
|
+
// "@nativescript/core/utils",
|
|
53
|
+
// "@nativescript/core/ui/gestures",
|
|
54
|
+
// "@nativescript/core/ui/action-bar",
|
|
55
|
+
// "@nativescript/core/ui/dialogs",
|
|
56
|
+
// "@nativescript/core/ui/list-view",
|
|
57
|
+
// "@nativescript/core/ui/search-bar",
|
|
58
|
+
// "@nativescript/core/ui/tab-view",
|
|
59
|
+
// "@nativescript/core/ui/web-view",
|
|
60
|
+
// "@nativescript/core/ui/slider",
|
|
61
|
+
// "@nativescript/core/ui/switch",
|
|
62
|
+
// "@nativescript/core/ui/transition",
|
|
63
|
+
// "@nativescript/core/ui/date-picker",
|
|
64
|
+
// "@nativescript/core/ui/time-picker",
|
|
65
|
+
// "@nativescript/core/ui/image",
|
|
66
|
+
// "@nativescript/core/ui/image-cache",
|
|
67
|
+
// "@nativescript/core/ui/text-base",
|
|
68
|
+
// "@nativescript/core/ui/label",
|
|
69
|
+
// "@nativescript/core/ui/text-field",
|
|
70
|
+
// "@nativescript/core/ui/text-view",
|
|
71
|
+
// "@nativescript/core/text/span",
|
|
72
|
+
// "@nativescript/core/text/formatted-string",
|
|
73
|
+
// "@nativescript/core/ui/animation",
|
|
74
|
+
// "@nativescript/core/ui/layouts/layout-base",
|
|
75
|
+
// ];
|
|
76
|
+
// for (const m of __ns_android_modules) {
|
|
77
|
+
// imports += `import '${m}?ns-keep';\n`;
|
|
78
|
+
// }
|
|
79
|
+
}
|
|
33
80
|
if (polyfillsExists) {
|
|
34
81
|
imports += `import '${polyfillsPath}';\n`;
|
|
35
82
|
}
|
|
36
|
-
// Import WebSocket support for HMR in development
|
|
37
|
-
if (debug && cliFlags.hmr) {
|
|
38
|
-
imports += `import '${hmrClientPath}';\n`;
|
|
39
|
-
}
|
|
40
|
-
// Import inspector modules for debugging in development
|
|
41
|
-
if (debug) {
|
|
42
|
-
imports += `import '@nativescript/core/inspector_modules';\n`;
|
|
43
|
-
}
|
|
44
83
|
// Import CSS and apply via Application.addCss before main entry
|
|
45
84
|
const appCssPath = path.resolve(projectRoot, "src/app.css");
|
|
46
85
|
if (fs.existsSync(appCssPath)) {
|
|
47
86
|
imports += `
|
|
48
|
-
// Import and apply global CSS
|
|
87
|
+
// Import and apply global CSS before Angular bootstrap
|
|
49
88
|
import appCssContent from './src/app.css?inline';
|
|
50
89
|
import { Application } from '@nativescript/core';
|
|
51
90
|
|
|
52
|
-
if (
|
|
91
|
+
if (appCssContent) {
|
|
53
92
|
try {
|
|
54
|
-
// Just testing logs if needed
|
|
55
|
-
// console.log('🎨 CSS content length:', appCssContent.length);
|
|
56
|
-
// console.log('🎨 CSS content preview:', appCssContent.substring(0, 200) + '...');
|
|
57
|
-
|
|
58
93
|
Application.addCss(appCssContent);
|
|
59
94
|
// console.log('🎨 Global CSS applied');
|
|
60
95
|
} catch (error) {
|
|
61
96
|
console.error('Error applying CSS:', error);
|
|
62
97
|
}
|
|
63
|
-
}
|
|
64
|
-
`;
|
|
98
|
+
}`;
|
|
65
99
|
}
|
|
66
|
-
|
|
100
|
+
// Import main entry to initialize after all platform setup above
|
|
101
|
+
imports += `import '${mainEntry}';\n`;
|
|
102
|
+
// Import WebSocket support for HMR in development
|
|
103
|
+
if (debug && cliFlags.hmr && hmrClientExists) {
|
|
104
|
+
imports += `import '${hmrClientPath}';\n`;
|
|
105
|
+
}
|
|
106
|
+
// Import inspector modules for debugging in development
|
|
67
107
|
if (debug) {
|
|
68
|
-
|
|
108
|
+
imports += `import '@nativescript/core/inspector_modules';\n`;
|
|
69
109
|
}
|
|
110
|
+
// if (debug) {
|
|
111
|
+
// console.log("🔄 Virtual entry imports:", imports);
|
|
112
|
+
// }
|
|
70
113
|
return imports;
|
|
71
114
|
}
|
|
72
115
|
return null;
|
|
@@ -12,8 +12,11 @@ export declare function hmrPlugin(targetMode: string): {
|
|
|
12
12
|
};
|
|
13
13
|
export declare function cliPlugin(targetMode: string, cliFlags: any): {
|
|
14
14
|
name: string;
|
|
15
|
+
apply: string;
|
|
15
16
|
enforce: "post";
|
|
16
17
|
configResolved(config: any): void;
|
|
17
18
|
buildStart(): void;
|
|
19
|
+
generateBundle(options: any, bundle: any): void;
|
|
20
|
+
writeBundle(options: any, bundle: any): void;
|
|
18
21
|
closeBundle(): void;
|
|
19
22
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import { readdirSync, statSync } from "fs";
|
|
2
|
+
import { readdirSync, statSync, existsSync, mkdirSync } from "fs";
|
|
3
3
|
// NativeScript HMR integration - track changes for incremental builds
|
|
4
4
|
// Track changed files globally for HMR
|
|
5
5
|
let changedFilesTracker = new Set();
|
|
@@ -56,8 +56,13 @@ export function hmrPlugin(targetMode) {
|
|
|
56
56
|
}
|
|
57
57
|
// NativeScript CLI integration - including IPC communication for HMR
|
|
58
58
|
export function cliPlugin(targetMode, cliFlags) {
|
|
59
|
+
// Capture emitted files directly from Rollup hooks to avoid relying on FS state
|
|
60
|
+
const lastBundleFiles = new Set();
|
|
61
|
+
let lastOutDir;
|
|
62
|
+
const debug = !!cliFlags?.viteDebug || !!process.env.DEBUG;
|
|
59
63
|
return {
|
|
60
64
|
name: "nativescript-cli-integration",
|
|
65
|
+
apply: "build",
|
|
61
66
|
// Ensure we run after other plugins (like vite-plugin-static-copy)
|
|
62
67
|
enforce: "post",
|
|
63
68
|
// Resolve build outDir so we can read final outputs after all plugins finish
|
|
@@ -70,15 +75,69 @@ export function cliPlugin(targetMode, cliFlags) {
|
|
|
70
75
|
console.log("🔥 Vite: Build started");
|
|
71
76
|
}
|
|
72
77
|
},
|
|
78
|
+
// Use Rollup hook to record emitted file names (relative to output dir)
|
|
79
|
+
generateBundle(options, bundle) {
|
|
80
|
+
try {
|
|
81
|
+
const keys = Object.keys(bundle);
|
|
82
|
+
for (const k of keys)
|
|
83
|
+
lastBundleFiles.add(k);
|
|
84
|
+
// Remember outDir/file from Rollup options if provided
|
|
85
|
+
lastOutDir =
|
|
86
|
+
options.dir ||
|
|
87
|
+
(options.file && path.dirname(options.file)) ||
|
|
88
|
+
undefined;
|
|
89
|
+
if (debug) {
|
|
90
|
+
console.log(`🔥 [cliPlugin] generateBundle: files=${keys.length}, dir=${lastOutDir ?? "(unknown)"}`);
|
|
91
|
+
if (keys.length) {
|
|
92
|
+
console.log("🔥 [cliPlugin] bundle keys:", keys);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// noop
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
// Also tap writeBundle (called only when writing to disk)
|
|
101
|
+
writeBundle(options, bundle) {
|
|
102
|
+
try {
|
|
103
|
+
const keys = Object.keys(bundle);
|
|
104
|
+
for (const k of keys)
|
|
105
|
+
lastBundleFiles.add(k);
|
|
106
|
+
lastOutDir =
|
|
107
|
+
options.dir ||
|
|
108
|
+
(options.file && path.dirname(options.file)) ||
|
|
109
|
+
lastOutDir;
|
|
110
|
+
if (debug) {
|
|
111
|
+
console.log(`🔥 [cliPlugin] writeBundle: files=${keys.length}, dir=${lastOutDir ?? "(unknown)"}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// noop
|
|
116
|
+
}
|
|
117
|
+
},
|
|
73
118
|
// Defer CLI notification until after all plugins (including static copy) are done.
|
|
74
119
|
closeBundle() {
|
|
75
120
|
if (targetMode !== "development")
|
|
76
121
|
return;
|
|
77
122
|
const buildType = isInitialBuild ? "initial" : "incremental";
|
|
78
123
|
console.log(`🔥 NativeScript: ${buildType} build completed`);
|
|
79
|
-
//
|
|
80
|
-
const distDir = getOutDir();
|
|
81
|
-
|
|
124
|
+
// Determine outDir and ensure it exists in dev for a clean start
|
|
125
|
+
const distDir = lastOutDir || getOutDir();
|
|
126
|
+
if (!existsSync(distDir)) {
|
|
127
|
+
try {
|
|
128
|
+
mkdirSync(distDir, { recursive: true });
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// ignore; listing will just return []
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Prefer Rollup-reported bundle files; fall back to FS scan
|
|
135
|
+
const emittedFiles = lastBundleFiles.size
|
|
136
|
+
? Array.from(lastBundleFiles)
|
|
137
|
+
: listFilesFlat(distDir);
|
|
138
|
+
if (debug) {
|
|
139
|
+
console.log(`🔥 [cliPlugin] closeBundle: distDir=${distDir}, captured=${lastBundleFiles.size}, fsScan=${emittedFiles.length}`);
|
|
140
|
+
}
|
|
82
141
|
// Determine what changed
|
|
83
142
|
const changedFilesList = Array.from(changedFilesTracker);
|
|
84
143
|
const hasHTMLChanges = changedFilesList.some((f) => f.endsWith(".html"));
|
|
@@ -103,26 +162,43 @@ export function cliPlugin(targetMode, cliFlags) {
|
|
|
103
162
|
}
|
|
104
163
|
console.log(`🔥 Emitted ${emittedFiles.length} files in ${buildType} build`);
|
|
105
164
|
if (process.send) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
165
|
+
const sendMessage = (files) => {
|
|
166
|
+
const message = {
|
|
167
|
+
emittedFiles: files,
|
|
168
|
+
chunkFiles: files.filter((f) => f.includes("chunk") || f.includes("vendor")),
|
|
169
|
+
hash: Date.now().toString(),
|
|
170
|
+
isHMR: isHMR && !isInitialBuild,
|
|
171
|
+
changedFiles: changedFilesList,
|
|
172
|
+
buildType,
|
|
173
|
+
timestamp: Date.now(),
|
|
174
|
+
};
|
|
175
|
+
console.log(`🔥 Sending ${buildType} build notification to CLI (isHMR: ${message.isHMR})`);
|
|
176
|
+
if (changedFilesList.length > 0) {
|
|
177
|
+
console.log("🔥 IPC includes changed files:", changedFilesList);
|
|
178
|
+
}
|
|
179
|
+
process.send(message);
|
|
114
180
|
};
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
181
|
+
if (emittedFiles.length === 0) {
|
|
182
|
+
// Allow a short delay for any late FS writes by other post plugins
|
|
183
|
+
setTimeout(() => {
|
|
184
|
+
const rescanned = listFilesFlat(distDir);
|
|
185
|
+
if (debug) {
|
|
186
|
+
console.log(`🔥 [cliPlugin] delayed rescan found ${rescanned.length} files in ${distDir}`);
|
|
187
|
+
}
|
|
188
|
+
sendMessage(rescanned);
|
|
189
|
+
}, 50);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
sendMessage(emittedFiles);
|
|
118
193
|
}
|
|
119
|
-
process.send(message);
|
|
120
194
|
}
|
|
121
195
|
if (isInitialBuild) {
|
|
122
196
|
isInitialBuild = false;
|
|
123
197
|
console.log("🔥 Initial build complete - subsequent changes will trigger fast rebuilds");
|
|
124
198
|
}
|
|
125
199
|
changedFilesTracker.clear();
|
|
200
|
+
lastBundleFiles.clear();
|
|
201
|
+
lastOutDir = undefined;
|
|
126
202
|
},
|
|
127
203
|
};
|
|
128
204
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Marks modules imported with `?ns-keep` as side-effectful so Rollup won't tree-shake them.
|
|
2
|
+
export function preserveImportsPlugin() {
|
|
3
|
+
return {
|
|
4
|
+
name: 'ns-preserve-imports',
|
|
5
|
+
// run early so downstream plugins see the preserved flag
|
|
6
|
+
enforce: 'pre',
|
|
7
|
+
async transform(code, id) {
|
|
8
|
+
if (id.includes('?ns-keep')) {
|
|
9
|
+
return {
|
|
10
|
+
code,
|
|
11
|
+
map: null,
|
|
12
|
+
// ensure side effects are preserved even if bindings are unused
|
|
13
|
+
moduleSideEffects: true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function nsCoreAllVirtual(): {
|
|
2
|
+
name: string;
|
|
3
|
+
buildStart(): void;
|
|
4
|
+
resolveId(id: string): string;
|
|
5
|
+
load(id: string): string;
|
|
6
|
+
};
|
|
7
|
+
export declare function noTreeshakeNSCore(): {
|
|
8
|
+
name: string;
|
|
9
|
+
resolveId(source: string, importer: string | undefined, opts: any): Promise<any>;
|
|
10
|
+
transform(code: string, id: string): {
|
|
11
|
+
code: string;
|
|
12
|
+
moduleSideEffects: true;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
const NS_RE = /node_modules[\\/]\@nativescript[\\/]core[\\/]/;
|
|
5
|
+
export function nsCoreAllVirtual() {
|
|
6
|
+
const VIRT_ID = 'virtual:ns-core-all';
|
|
7
|
+
const RESOLVED = '\0' + VIRT_ID;
|
|
8
|
+
let code = '';
|
|
9
|
+
function walk(dir, out = []) {
|
|
10
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
11
|
+
const abs = path.join(dir, entry.name);
|
|
12
|
+
if (entry.isDirectory()) {
|
|
13
|
+
// skip obviously irrelevant dirs if present
|
|
14
|
+
if (entry.name === 'types' || entry.name === '__tests__')
|
|
15
|
+
continue;
|
|
16
|
+
walk(abs, out);
|
|
17
|
+
}
|
|
18
|
+
else if (/\.(m?js|cjs)$/.test(entry.name)) {
|
|
19
|
+
out.push(abs);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
name: 'ns-core-all-virtual',
|
|
26
|
+
buildStart() {
|
|
27
|
+
// ESM-safe resolve for node_modules
|
|
28
|
+
const require = createRequire(import.meta.url);
|
|
29
|
+
const pkgPath = require.resolve('@nativescript/core/package.json');
|
|
30
|
+
const root = path.dirname(pkgPath);
|
|
31
|
+
const files = walk(root);
|
|
32
|
+
code = files
|
|
33
|
+
.map((abs) => {
|
|
34
|
+
const rel = path.relative(root, abs).split(path.sep).join('/');
|
|
35
|
+
return `import '@nativescript/core/${rel}';`;
|
|
36
|
+
})
|
|
37
|
+
.join('\n');
|
|
38
|
+
this.warn(`[ns-core-all-virtual] including ${files.length} files from @nativescript/core`);
|
|
39
|
+
},
|
|
40
|
+
resolveId(id) {
|
|
41
|
+
if (id === VIRT_ID)
|
|
42
|
+
return RESOLVED;
|
|
43
|
+
},
|
|
44
|
+
load(id) {
|
|
45
|
+
if (id === RESOLVED)
|
|
46
|
+
return code;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function noTreeshakeNSCore() {
|
|
51
|
+
return {
|
|
52
|
+
name: 'ns-core-no-treeshake',
|
|
53
|
+
async resolveId(source, importer, opts) {
|
|
54
|
+
const r = await this.resolve(source, importer, { skipSelf: true, ...opts });
|
|
55
|
+
if (!r)
|
|
56
|
+
return null;
|
|
57
|
+
if (NS_RE.test(r.id)) {
|
|
58
|
+
// Strongest signal to Rollup: do not treeshake this module
|
|
59
|
+
return { ...r, moduleSideEffects: true };
|
|
60
|
+
}
|
|
61
|
+
return r;
|
|
62
|
+
},
|
|
63
|
+
transform(code, id) {
|
|
64
|
+
if (NS_RE.test(id))
|
|
65
|
+
return { code, moduleSideEffects: true };
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -134,7 +134,9 @@ function createTsConfigAliases(paths, baseUrl, platform, debugViteLogs) {
|
|
|
134
134
|
const resolvedDestination = path.isAbsolute(destination)
|
|
135
135
|
? destination
|
|
136
136
|
: path.resolve(projectRoot, baseUrl, destination);
|
|
137
|
-
console.log(
|
|
137
|
+
// console.log(
|
|
138
|
+
// `📁 Creating wildcard alias: ${aliasKey} -> ${resolvedDestination}`,
|
|
139
|
+
// );
|
|
138
140
|
aliases.push({
|
|
139
141
|
find: new RegExp(`^${aliasKey.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?:/(.*))?$`),
|
|
140
142
|
replacement: (match, subpath) => {
|