Skip to content

Commit 6a25723

Browse files
Merge pull request #3350 from NativeScript/kerezov/webpack+livesync
feat(livesync): enable livesync with bundling
2 parents 017e53f + 418fa6b commit 6a25723

File tree

4 files changed

+45
-23
lines changed

4 files changed

+45
-23
lines changed

lib/commands/run.ts

-4
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ export class RunCommandBase extends BundleBase implements ICommand {
4949
}
5050

5151
public async executeCore(args: string[]): Promise<void> {
52-
if (this.$options.bundle) {
53-
this.$options.watch = false;
54-
}
55-
5652
await this.$devicesService.initialize({
5753
deviceId: this.$options.device,
5854
platform: this.platform,

lib/definitions/livesync.d.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,17 @@ interface ILiveSyncDeviceInfo extends IOptionalOutputPath, IOptionalDebuggingOpt
108108
platformSpecificOptions?: IPlatformOptions;
109109
}
110110

111-
/**
112-
* Describes a LiveSync operation.
113-
*/
114-
interface ILiveSyncInfo extends IProjectDir, IEnvOptions, IBundle, IRelease {
111+
interface IOptionalSkipWatcher {
115112
/**
116113
* Defines if the watcher should be skipped. If not passed, fs.Watcher will be started.
117114
*/
118115
skipWatcher?: boolean;
116+
}
119117

118+
/**
119+
* Describes a LiveSync operation.
120+
*/
121+
interface ILiveSyncInfo extends IProjectDir, IEnvOptions, IBundle, IRelease, IOptionalSkipWatcher {
120122
/**
121123
* Defines if all project files should be watched for changes. In case it is not passed, only `app` dir of the project will be watched for changes.
122124
* In case it is set to true, the package.json of the project and node_modules directory will also be watched, so any change there will be transferred to device(s).
@@ -207,6 +209,13 @@ interface ILiveSyncService {
207209
* Describes LiveSync operations while debuggging.
208210
*/
209211
interface IDebugLiveSyncService extends ILiveSyncService {
212+
/**
213+
* Method used to retrieve the glob patterns which CLI will watch for file changes. Defaults to the whole app directory.
214+
* @param {ILiveSyncInfo} liveSyncData Information needed for livesync - for example if bundle is passed or if a release build should be performed.
215+
* @returns {Promise<string[]>} The glob patterns.
216+
*/
217+
getWatcherPatterns(liveSyncData: ILiveSyncInfo): Promise<string[]>;
218+
210219
/**
211220
* Prints debug information.
212221
* @param {IDebugInformation} debugInformation Information to be printed.

lib/services/livesync/livesync-service.ts

+30-13
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import * as choki from "chokidar";
33
import { EOL } from "os";
44
import { EventEmitter } from "events";
55
import { hook } from "../../common/helpers";
6-
import { APP_FOLDER_NAME, PACKAGE_JSON_FILE_NAME, LiveSyncTrackActionNames, USER_INTERACTION_NEEDED_EVENT_NAME, DEBUGGER_ATTACHED_EVENT_NAME, DEBUGGER_DETACHED_EVENT_NAME, TrackActionNames } from "../../constants";
7-
import { FileExtensions, DeviceTypes, DeviceDiscoveryEventNames } from "../../common/constants";
6+
import { APP_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME, PACKAGE_JSON_FILE_NAME, LiveSyncTrackActionNames, USER_INTERACTION_NEEDED_EVENT_NAME, DEBUGGER_ATTACHED_EVENT_NAME, DEBUGGER_DETACHED_EVENT_NAME, TrackActionNames } from "../../constants";
7+
import { DeviceTypes, DeviceDiscoveryEventNames } from "../../common/constants";
88
import { cache } from "../../common/decorators";
99

1010
const deviceDescriptorPrimaryKey = "identifier";
@@ -289,6 +289,12 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
289289
return _.map(deviceOptions, d => this.disableDebuggingCore(d, debuggingAdditionalOptions));
290290
}
291291

292+
@hook('watchPatterns')
293+
public async getWatcherPatterns(liveSyncData: ILiveSyncInfo): Promise<string[]> {
294+
// liveSyncData is used by plugins that make use of the watchPatterns hook
295+
return [APP_FOLDER_NAME, path.join(APP_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME)];
296+
}
297+
292298
public async disableDebuggingCore(deviceOption: IDisableDebuggingDeviceOptions, debuggingAdditionalOptions: IDebuggingAdditionalOptions): Promise<void> {
293299
const liveSyncProcessInfo = this.liveSyncProcessesInfo[debuggingAdditionalOptions.projectDir];
294300
if (liveSyncProcessInfo.currentSyncAction) {
@@ -328,7 +334,10 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
328334
// Should be set after prepare
329335
this.$usbLiveSyncService.isInitialized = true;
330336

331-
await this.startWatcher(projectData, liveSyncData);
337+
const devicesIds = deviceDescriptors.map(dd => dd.identifier);
338+
const devices = _.filter(this.$devicesService.getDeviceInstances(), device => _.includes(devicesIds, device.deviceInfo.identifier));
339+
const platforms = _(devices).map(device => device.deviceInfo.platform).uniq().value();
340+
await this.startWatcher(projectData, liveSyncData, platforms);
332341
}
333342
}
334343

@@ -515,8 +524,8 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
515524
};
516525
}
517526

518-
private async startWatcher(projectData: IProjectData, liveSyncData: ILiveSyncInfo): Promise<void> {
519-
const patterns = [APP_FOLDER_NAME];
527+
private async startWatcher(projectData: IProjectData, liveSyncData: ILiveSyncInfo, platforms: string[]): Promise<void> {
528+
const patterns = await this.getWatcherPatterns(liveSyncData);
520529

521530
if (liveSyncData.watchAllFiles) {
522531
const productionDependencies = this.$nodeModulesDependenciesBuilder.getProductionDependencies(projectData.projectDir);
@@ -535,18 +544,18 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
535544
currentWatcherInfo.watcher.close();
536545
}
537546

538-
let filesToSync: string[] = [];
547+
const filesToSync: string[] = [];
539548
let filesToRemove: string[] = [];
540549
let timeoutTimer: NodeJS.Timer;
541550

542-
const startTimeout = () => {
551+
const startSyncFilesTimeout = () => {
543552
timeoutTimer = setTimeout(async () => {
544553
// Push actions to the queue, do not start them simultaneously
545554
await this.addActionToChain(projectData.projectDir, async () => {
546555
if (filesToSync.length || filesToRemove.length) {
547556
try {
548557
const currentFilesToSync = _.cloneDeep(filesToSync);
549-
filesToSync = [];
558+
filesToSync.splice(0, filesToSync.length);
550559

551560
const currentFilesToRemove = _.cloneDeep(filesToRemove);
552561
filesToRemove = [];
@@ -622,7 +631,18 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
622631

623632
await this.$hooksService.executeBeforeHooks('watch', {
624633
hookArgs: {
625-
projectData
634+
projectData,
635+
config: {
636+
env: liveSyncData.env,
637+
appFilesUpdaterOptions: {
638+
bundle: liveSyncData.bundle,
639+
release: liveSyncData.release
640+
},
641+
platforms
642+
},
643+
filesToSync,
644+
filesToRemove,
645+
startSyncFilesTimeout: startSyncFilesTimeout.bind(this)
626646
}
627647
});
628648

@@ -650,10 +670,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
650670
filesToRemove.push(filePath);
651671
}
652672

653-
// Do not sync typescript files directly - wait for javascript changes to occur in order to restart the app only once
654-
if (path.extname(filePath) !== FileExtensions.TYPESCRIPT_FILE) {
655-
startTimeout();
656-
}
673+
startSyncFilesTimeout();
657674
});
658675

659676
this.liveSyncProcessesInfo[liveSyncData.projectDir].watcherInfo = { watcher, patterns };

lib/services/platform-service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,11 @@ export class PlatformService extends EventEmitter implements IPlatformService {
193193
const changesInfo = await this.initialPrepare(platformInfo.platform, platformData, platformInfo.appFilesUpdaterOptions, platformInfo.platformTemplate, platformInfo.projectData, platformInfo.config, platformInfo.nativePrepare, platformInfo);
194194
const requiresNativePrepare = (!platformInfo.nativePrepare || !platformInfo.nativePrepare.skipNativePrepare) && changesInfo.nativePlatformStatus === constants.NativePlatformStatus.requiresPrepare;
195195

196-
if (changesInfo.hasChanges || platformInfo.appFilesUpdaterOptions.bundle || requiresNativePrepare) {
196+
if (changesInfo.hasChanges || requiresNativePrepare) {
197197
// Always clear up the app directory in platforms if `--bundle` value has changed in between builds or is passed in general
198198
// this is done as user has full control over what goes in platforms when `--bundle` is passed
199199
// and we may end up with duplicate symbols which would fail the build
200-
if (changesInfo.bundleChanged || platformInfo.appFilesUpdaterOptions.bundle) {
200+
if (changesInfo.bundleChanged) {
201201
await this.cleanDestinationApp(platformInfo);
202202
}
203203

0 commit comments

Comments
 (0)