Skip to content

Commit a2b4ee3

Browse files
committed
feat(vite): bundler handling
1 parent 89e383a commit a2b4ee3

File tree

1 file changed

+51
-179
lines changed

1 file changed

+51
-179
lines changed

lib/services/bundler/bundler-compiler-service.ts

Lines changed: 51 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as path from "path";
22
import * as child_process from "child_process";
33
import * as semver from "semver";
44
import * as _ from "lodash";
5+
// TODO: can switch to file-system service
6+
import { mkdirSync, readdirSync, existsSync, copyFileSync, rmSync } from "fs";
57
import { EventEmitter } from "events";
68
import { performanceLog } from "../../common/decorators";
79
import {
@@ -126,96 +128,37 @@ export class BundlerCompilerService
126128
}
127129

128130
// Copy Vite output files directly to platform destination
129-
const distOutput = path.join(projectData.projectDir, "dist");
131+
const distOutput = path.join(
132+
projectData.projectDir,
133+
".ns-vite-build",
134+
);
130135
const destDir = path.join(
131136
platformData.appDestinationDirectoryPath,
132137
this.$options.hostProjectModuleName,
133138
);
134139

135140
if (debugLog) {
136-
console.log(`🔥 Copying from ${distOutput} to ${destDir}`);
141+
console.log(`Copying from ${distOutput} to ${destDir}.`);
137142
}
138143

139144
// Determine which files to copy based on build type and changes
140-
if (message.isHMR) {
141-
// HMR updates: only copy changed files
142-
if (debugLog) {
143-
console.log(
144-
"🔥 HMR update - copying only changed files for:",
145-
message.changedFiles,
146-
);
147-
}
148-
149-
// For HTML template changes, we need to copy the component files that were rebuilt
150-
let filesToCopy = message.emittedFiles;
151-
152-
// If we have HTML changes, identify which component files need copying
153-
const hasHTMLChanges = message.changedFiles.some((f) =>
154-
f.endsWith(".html"),
155-
);
156-
if (hasHTMLChanges) {
157-
// Copy component-related files (the ones that would have been rebuilt due to template changes)
158-
filesToCopy = message.emittedFiles.filter(
159-
(f) =>
160-
f.includes(".component") ||
161-
f === "bundle.mjs" ||
162-
f === "bundle.mjs.map",
163-
);
164-
if (debugLog) {
165-
console.log(
166-
"🔥 HTML change detected - copying component files:",
167-
filesToCopy,
168-
);
169-
}
170-
}
171-
172-
this.copyViteBundleToNative(distOutput, destDir, filesToCopy);
173-
} else if (
145+
if (
174146
message.buildType === "incremental" &&
175-
message.changedFiles &&
176-
message.changedFiles.length > 0
147+
message.emittedFiles &&
148+
message.emittedFiles.length > 0
177149
) {
178150
// Incremental builds: only copy files that are likely affected by the changes
179-
if (debugLog) {
180-
console.log(
181-
"🔥 Incremental build - copying only relevant files for:",
182-
message.changedFiles,
183-
);
184-
}
185-
186151
const filesToCopy = this.getIncrementalFilesToCopy(
187152
message.emittedFiles,
188-
message.changedFiles,
189153
);
190154
if (debugLog) {
191-
console.log(
192-
"🔥 Incremental build - files to copy:",
193-
filesToCopy,
194-
);
155+
console.log("Incremental build - files to copy:", filesToCopy);
195156
}
196157

197-
this.copyViteBundleToNative(distOutput, destDir, filesToCopy);
198-
} else if (
199-
message.buildType === "incremental" &&
200-
message.changedFiles &&
201-
message.changedFiles.length > 0
202-
) {
203-
// Incremental builds: only copy files that are likely affected by the changes
204-
console.log(
205-
"🔥 Incremental build - copying only relevant files for:",
206-
message.changedFiles,
207-
);
208-
209-
const filesToCopy = this.getIncrementalFilesToCopy(
210-
message.emittedFiles,
211-
message.changedFiles,
212-
);
213-
console.log("🔥 Incremental build - files to copy:", filesToCopy);
214-
215158
this.copyViteBundleToNative(distOutput, destDir, filesToCopy);
216159
} else {
217160
if (debugLog) {
218-
console.log("🔥 Full build - copying all files");
161+
console.log("Full build - copying all files.");
219162
}
220163
this.copyViteBundleToNative(distOutput, destDir);
221164
}
@@ -254,31 +197,14 @@ export class BundlerCompilerService
254197
this.$logger.info(
255198
`Vite build completed! Files copied to native platform.`,
256199
);
257-
// Send HMR notification to connected WebSocket clients first
258-
this.notifyHMRClients({
259-
type: message.isHMR ? "js-update" : "build-complete",
260-
timestamp: Date.now(),
261-
changedFiles: message.changedFiles || [],
262-
buildType: message.buildType || "incremental",
263-
isHMR: message.isHMR || false,
264-
});
265-
266-
if (message.isHMR) {
267-
if (debugLog) {
268-
console.log(
269-
"🔥 Skipping BUNDLER_COMPILATION_COMPLETE for HMR update - app will not restart",
270-
);
271-
}
272-
} else {
273-
// Only emit BUNDLER_COMPILATION_COMPLETE for non-HMR builds
274-
// This prevents the CLI from restarting the app during HMR updates
275-
if (debugLog) {
276-
console.log(
277-
"🔥 Emitting BUNDLER_COMPILATION_COMPLETE for full build",
278-
);
279-
}
280-
this.emit(BUNDLER_COMPILATION_COMPLETE, data);
200+
201+
if (debugLog) {
202+
console.log(
203+
"Emitting BUNDLER_COMPILATION_COMPLETE for full build.",
204+
);
281205
}
206+
this.emit(BUNDLER_COMPILATION_COMPLETE, data);
207+
282208
return;
283209
}
284210

@@ -548,7 +474,7 @@ export class BundlerCompilerService
548474
const args = [
549475
...additionalNodeArgs,
550476
this.getBundlerExecutablePath(projectData),
551-
isVite ? "build" : this.isModernBundler(projectData) ? `build` : null,
477+
isVite || this.isModernBundler(projectData) ? "build" : null,
552478
`--config=${projectData.bundlerConfigPath}`,
553479
...envParams,
554480
].filter(Boolean);
@@ -928,55 +854,53 @@ export class BundlerCompilerService
928854
) {
929855
// Clean and copy Vite output to native platform folder
930856
if (debugLog) {
931-
console.log(`Copying Vite bundle from "${distOutput}" to "${destDir}"`);
857+
console.log(`Copying Vite bundle from "${distOutput}" to "${destDir}".`);
932858
}
933859

934-
const fs = require("fs");
935-
936860
try {
937861
if (specificFiles) {
938-
// Selective mode: only copy specific files (HMR or incremental)
862+
// Selective mode: only copy specific files (incremental)
939863
if (debugLog) {
940864
console.log(
941-
"🔥 Selective copy - copying specific files:",
865+
"Selective copy - copying specific files:",
942866
specificFiles,
943867
);
944868
}
945869

946870
// Ensure destination directory exists
947-
fs.mkdirSync(destDir, { recursive: true });
871+
mkdirSync(destDir, { recursive: true });
948872

949873
// Copy only the specified files
950874
for (const file of specificFiles) {
951875
const srcPath = path.join(distOutput, file);
952876
const destPath = path.join(destDir, file);
953877

954-
if (!fs.existsSync(srcPath)) continue;
878+
if (!existsSync(srcPath)) continue;
955879

956880
// create parent dirs
957-
fs.mkdirSync(path.dirname(destPath), { recursive: true });
881+
mkdirSync(path.dirname(destPath), { recursive: true });
958882

959-
fs.copyFileSync(srcPath, destPath);
883+
copyFileSync(srcPath, destPath);
960884

961885
if (debugLog) {
962-
console.log(`🔥 Copied ${file}`);
886+
console.log(`Copied ${file}`);
963887
}
964888
}
965889
} else {
966890
// Full build mode: clean and copy everything
967891
if (debugLog) {
968-
console.log("🔥 Full build: Copying all files");
892+
console.log("Full build: Copying all files.");
969893
}
970894

971895
// Clean destination directory
972-
if (fs.existsSync(destDir)) {
973-
fs.rmSync(destDir, { recursive: true, force: true });
896+
if (existsSync(destDir)) {
897+
rmSync(destDir, { recursive: true, force: true });
974898
}
975-
fs.mkdirSync(destDir, { recursive: true });
899+
mkdirSync(destDir, { recursive: true });
976900

977901
// Copy all files from dist to platform destination
978-
if (fs.existsSync(distOutput)) {
979-
this.copyRecursiveSync(distOutput, destDir, fs);
902+
if (existsSync(distOutput)) {
903+
this.copyRecursiveSync(distOutput, destDir);
980904
} else {
981905
this.$logger.warn(
982906
`Vite output directory does not exist: ${distOutput}`,
@@ -988,100 +912,48 @@ export class BundlerCompilerService
988912
}
989913
}
990914

991-
private getIncrementalFilesToCopy(
992-
emittedFiles: string[],
993-
changedFiles: string[],
994-
): string[] {
915+
private getIncrementalFilesToCopy(emittedFiles: string[]): string[] {
995916
// For incremental builds, we need to determine which emitted files are likely affected
996917
// by the source file changes
997918

998919
const filesToCopy: string[] = [];
999920

1000-
// Always copy bundle files as they contain the compiled source code
1001-
// ignoring vendor files as they are less likely to change frequently
921+
// default to ignoring vendor files as they are less likely to change during live reloads
1002922
const bundleFiles = emittedFiles.filter(
1003923
(file) =>
1004924
!file.includes("vendor") &&
1005-
(file.includes("bundle") ||
1006-
file.includes("main") ||
1007-
file.includes("app") ||
1008-
file.endsWith(".mjs") ||
1009-
file.endsWith(".js")),
925+
(file.endsWith(".mjs") ||
926+
file.endsWith(".js") ||
927+
file.endsWith(".map")),
1010928
);
1011929
filesToCopy.push(...bundleFiles);
1012930

1013-
// Always copy source maps for debugging
1014-
const sourceMapFiles = emittedFiles.filter(
1015-
(file) => !file.includes("vendor") && file.endsWith(".map"),
1016-
);
1017-
filesToCopy.push(...sourceMapFiles);
1018-
1019-
// Only handle assets if they're explicitly referenced in the changed files
1020-
const hasAssetChanges = changedFiles.some(
931+
// Only copy assets if there are explicit asset-related changes
932+
const assetFiles = emittedFiles.filter(
1021933
(file) =>
1022-
file.includes("/assets/") ||
1023-
file.includes("/static/") ||
1024-
file.includes("/public/"),
934+
file.includes("assets/") ||
935+
file.includes("static/") ||
936+
file.includes("fonts/") ||
937+
file.includes("images/"),
1025938
);
1026-
1027-
if (hasAssetChanges) {
1028-
// Only copy assets if there are explicit asset-related changes
1029-
const assetFiles = emittedFiles.filter(
1030-
(file) =>
1031-
file.includes("assets/") ||
1032-
file.includes("static/") ||
1033-
file.includes("fonts/") ||
1034-
file.includes("images/"),
1035-
);
939+
if (assetFiles.length > 0) {
1036940
filesToCopy.push(...assetFiles);
1037941
}
1038942

1039943
// Remove duplicates and return
1040944
return [...new Set(filesToCopy)];
1041945
}
1042946

1043-
private notifyHMRClients(message: any) {
1044-
// Send WebSocket notification to HMR clients
1045-
try {
1046-
const WebSocket = require("ws");
1047-
1048-
// Try to connect to HMR bridge and send notification
1049-
const ws = new WebSocket("ws://localhost:24678");
1050-
1051-
ws.on("open", () => {
1052-
if (debugLog) {
1053-
console.log("🔥 Sending HMR notification to bridge:", message.type);
1054-
}
1055-
ws.send(JSON.stringify(message));
1056-
ws.close();
1057-
});
1058-
1059-
ws.on("error", () => {
1060-
// HMR bridge not available, which is fine
1061-
if (debugLog) {
1062-
console.log(
1063-
"🔥 HMR bridge not available (this is normal without HMR)",
1064-
);
1065-
}
1066-
});
1067-
} catch (error) {
1068-
// WebSocket not available, which is fine
1069-
if (debugLog) {
1070-
console.log("🔥 WebSocket not available for HMR notifications");
1071-
}
1072-
}
1073-
}
1074-
1075-
private copyRecursiveSync(src: string, dest: string, fs: any) {
1076-
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
947+
private copyRecursiveSync(src: string, dest: string) {
948+
for (const entry of readdirSync(src, { withFileTypes: true })) {
1077949
const srcPath = path.join(src, entry.name);
1078950
const destPath = path.join(dest, entry.name);
1079951

1080952
if (entry.isDirectory()) {
1081-
fs.mkdirSync(destPath, { recursive: true });
1082-
this.copyRecursiveSync(srcPath, destPath, fs);
953+
mkdirSync(destPath, { recursive: true });
954+
this.copyRecursiveSync(srcPath, destPath);
1083955
} else if (entry.isFile() || entry.isSymbolicLink()) {
1084-
fs.copyFileSync(srcPath, destPath);
956+
copyFileSync(srcPath, destPath);
1085957
}
1086958
}
1087959
}

0 commit comments

Comments
 (0)