diff --git a/lib/services/livesync/playground/preview-app-livesync-service.ts b/lib/services/livesync/playground/preview-app-livesync-service.ts index efc7571965..51de36f4e3 100644 --- a/lib/services/livesync/playground/preview-app-livesync-service.ts +++ b/lib/services/livesync/playground/preview-app-livesync-service.ts @@ -7,6 +7,7 @@ const isTextOrBinary = require('istextorbinary'); export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { private excludedFileExtensions = [".ts", ".sass", ".scss", ".less"]; private excludedFiles = [".DS_Store"]; + private deviceInitializationPromise: IDictionary> = {}; constructor(private $fs: IFileSystem, private $errors: IErrors, @@ -26,37 +27,51 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { this.$errors.failWithoutHelp("Sending initial preview files without a specified device is not supported."); } - const filesToSyncMap: IDictionary = {}; - let promise = Promise.resolve(null); - const startSyncFilesTimeout = async (platform: string) => { - await promise - .then(async () => { - const projectData = this.$projectDataService.getProjectData(data.projectDir); - promise = this.applyChanges(this.$platformsData.getPlatformData(platform, projectData), projectData, filesToSyncMap[platform]); - await promise; - }); - filesToSyncMap[platform] = []; - }; - await this.$hooksService.executeBeforeHooks("preview-sync", { - hookArgs: { - projectData: this.$projectDataService.getProjectData(data.projectDir), - config: { - env: data.env, - platform: device.platform, - appFilesUpdaterOptions: data.appFilesUpdaterOptions, - }, - externals: this.$previewAppPluginsService.getExternalPlugins(device), - filesToSyncMap, - startSyncFilesTimeout: startSyncFilesTimeout.bind(this) - } - }); - await this.$previewAppPluginsService.comparePluginsOnDevice(data, device); - const payloads = await this.syncFilesForPlatformSafe(data, device.platform); + if (this.deviceInitializationPromise[device.id]) { + return this.deviceInitializationPromise[device.id]; + } - return payloads; + this.deviceInitializationPromise[device.id] = this.initializePreviewForDevice(data, device); + try { + const payloads = await this.deviceInitializationPromise[device.id]; + return payloads; + } finally { + this.deviceInitializationPromise[device.id] = null; + } }); } + private async initializePreviewForDevice(data: IPreviewAppLiveSyncData, device: Device): Promise { + const filesToSyncMap: IDictionary = {}; + let promise = Promise.resolve(null); + const startSyncFilesTimeout = async (platform: string) => { + await promise + .then(async () => { + const projectData = this.$projectDataService.getProjectData(data.projectDir); + promise = this.applyChanges(this.$platformsData.getPlatformData(platform, projectData), projectData, filesToSyncMap[platform]); + await promise; + }); + filesToSyncMap[platform] = []; + }; + await this.$hooksService.executeBeforeHooks("preview-sync", { + hookArgs: { + projectData: this.$projectDataService.getProjectData(data.projectDir), + config: { + env: data.env, + platform: device.platform, + appFilesUpdaterOptions: data.appFilesUpdaterOptions, + }, + externals: this.$previewAppPluginsService.getExternalPlugins(device), + filesToSyncMap, + startSyncFilesTimeout: startSyncFilesTimeout.bind(this) + } + }); + await this.$previewAppPluginsService.comparePluginsOnDevice(data, device); + const payloads = await this.syncFilesForPlatformSafe(data, device.platform); + payloads.deviceId = device.id; + return payloads; + } + public async syncFiles(data: IPreviewAppLiveSyncData, files?: string[]): Promise { this.showWarningsForNativeFiles(files);