Skip to content

Commit 265a492

Browse files
committed
feat(preview): don't prepare the project on preview command
Prepare is needed only to compile typescript and sass files. `preview-sync` hook is added to `nativescript-dev-typescript` and `nativescript-dev-sass` plugins in order to handle the compilation. This way the preview command will be faster as no prepare will be executed.
1 parent 986673d commit 265a492

File tree

5 files changed

+156
-131
lines changed

5 files changed

+156
-131
lines changed

lib/bootstrap.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ $injector.requirePublicClass("androidLivesyncTool", "./services/livesync/android
131131
$injector.require("androidLiveSyncService", "./services/livesync/android-livesync-service");
132132
$injector.require("iOSLiveSyncService", "./services/livesync/ios-livesync-service");
133133
$injector.require("usbLiveSyncService", "./services/livesync/livesync-service"); // The name is used in https://github.com/NativeScript/nativescript-dev-typescript
134+
$injector.require("previewAppFilesService", "./services/livesync/playground/preview-app-files-service");
134135
$injector.require("previewAppLiveSyncService", "./services/livesync/playground/preview-app-livesync-service");
135136
$injector.require("previewAppLogProvider", "./services/livesync/playground/preview-app-log-provider");
136137
$injector.require("previewAppPluginsService", "./services/livesync/playground/preview-app-plugins-service");

lib/definitions/preview-app-livesync.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ declare global {
88
stopLiveSync(): Promise<void>;
99
}
1010

11+
interface IPreviewAppFilesService {
12+
getInitialFilesPayload(data: IPreviewAppLiveSyncData, platform: string, deviceId?: string): FilesPayload;
13+
getFilesPayload(data: IPreviewAppLiveSyncData, filesData: IPreviewAppFilesData, platform: string, deviceId?: string): FilesPayload;
14+
}
15+
16+
interface IPreviewAppFilesData {
17+
filesToSync: string[];
18+
filesToRemove?: string[];
19+
}
20+
1121
interface IPreviewAppLiveSyncData extends IProjectDir, IHasUseHotModuleReloadOption, IBundle, IEnvOptions { }
1222

1323
interface IPreviewSdkService extends EventEmitter {
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import * as path from "path";
2+
import { APP_FOLDER_NAME, TNS_MODULES_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME } from "../../../constants";
3+
import { PreviewSdkEventNames } from "./preview-app-constants";
4+
import { FilePayload, FilesPayload } from "nativescript-preview-sdk";
5+
const isTextOrBinary = require('istextorbinary');
6+
7+
export class PreviewAppFilesService implements IPreviewAppFilesService {
8+
private excludedFileExtensions = [".ts", ".sass", ".scss", ".less"];
9+
private excludedFiles = [".DS_Store"];
10+
11+
constructor(
12+
private $fs: IFileSystem,
13+
private $logger: ILogger,
14+
private $platformsData: IPlatformsData,
15+
private $projectDataService: IProjectDataService,
16+
private $projectFilesManager: IProjectFilesManager
17+
) { }
18+
19+
public getInitialFilesPayload(data: IPreviewAppLiveSyncData, platform: string, deviceId?: string): FilesPayload {
20+
const rootFilesDir = this.getRootFilesDir(data, platform);
21+
const filesToSync = this.$projectFilesManager.getProjectFiles(rootFilesDir);
22+
const payloads = this.getFilesPayload(data, { filesToSync }, platform, deviceId);
23+
return payloads;
24+
}
25+
26+
public getFilesPayload(data: IPreviewAppLiveSyncData, filesData: IPreviewAppFilesData, platform: string, deviceId?: string): FilesPayload {
27+
const { filesToSync, filesToRemove } = filesData;
28+
29+
const filesToTransfer = filesToSync
30+
.filter(file => file.indexOf(TNS_MODULES_FOLDER_NAME) === -1)
31+
.filter(file => file.indexOf(APP_RESOURCES_FOLDER_NAME) === -1)
32+
.filter(file => !_.includes(this.excludedFiles, path.basename(file)))
33+
.filter(file => !_.includes(this.excludedFileExtensions, path.extname(file)));
34+
35+
this.$logger.trace(`Transferring ${filesToTransfer.join("\n")}.`);
36+
37+
const rootFilesDir = this.getRootFilesDir(data, platform);
38+
const payloadsToSync = _.map(filesToTransfer, file => this.createFilePayload(file, rootFilesDir, PreviewSdkEventNames.CHANGE_EVENT_NAME));
39+
const payloadsToRemove = _.map(filesToRemove, file => this.createFilePayload(file, rootFilesDir, PreviewSdkEventNames.UNLINK_EVENT_NAME));
40+
const payloads = payloadsToSync.concat(payloadsToRemove);
41+
42+
return {
43+
files: payloads,
44+
platform: platform,
45+
hmrMode: data.useHotModuleReload ? 1 : 0,
46+
deviceId
47+
};
48+
}
49+
50+
private createFilePayload(file: string, rootFilesDir: string, event: string): FilePayload {
51+
let fileContents = "";
52+
let binary = false;
53+
54+
if (event === PreviewSdkEventNames.CHANGE_EVENT_NAME) {
55+
binary = isTextOrBinary.isBinarySync(file);
56+
if (binary) {
57+
const bitmap = <string>this.$fs.readFile(file);
58+
const base64 = Buffer.from(bitmap).toString('base64');
59+
fileContents = base64;
60+
} else {
61+
fileContents = this.$fs.readText(file);
62+
}
63+
}
64+
65+
const filePayload = {
66+
event,
67+
file: path.relative(rootFilesDir, file),
68+
binary,
69+
fileContents
70+
};
71+
72+
return filePayload;
73+
}
74+
75+
private getRootFilesDir(data: IPreviewAppLiveSyncData, platform: string): string {
76+
const projectData = this.$projectDataService.getProjectData(data.projectDir);
77+
const platformData = this.$platformsData.getPlatformData(platform, projectData);
78+
79+
let rootFilesDir = null;
80+
if (data.bundle) {
81+
rootFilesDir = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME);
82+
} else {
83+
rootFilesDir = projectData.getAppDirectoryPath();
84+
}
85+
86+
return rootFilesDir;
87+
}
88+
}
89+
$injector.register("previewAppFilesService", PreviewAppFilesService);
Lines changed: 55 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,24 @@
11
import * as path from "path";
2-
import { FilePayload, Device, FilesPayload } from "nativescript-preview-sdk";
3-
import { PreviewSdkEventNames } from "./preview-app-constants";
4-
import { APP_FOLDER_NAME, APP_RESOURCES_FOLDER_NAME, TNS_MODULES_FOLDER_NAME } from "../../../constants";
2+
import { Device, FilesPayload } from "nativescript-preview-sdk";
3+
import { APP_RESOURCES_FOLDER_NAME, APP_FOLDER_NAME } from "../../../constants";
54
import { HmrConstants } from "../../../common/constants";
6-
const isTextOrBinary = require('istextorbinary');
7-
8-
interface ISyncFilesOptions {
9-
filesToSync?: string[];
10-
filesToRemove?: string[];
11-
isInitialSync?: boolean;
12-
skipPrepare?: boolean;
13-
useHotModuleReload?: boolean;
14-
deviceId?: string;
15-
}
165

176
export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
18-
private excludedFileExtensions = [".ts", ".sass", ".scss", ".less"];
19-
private excludedFiles = [".DS_Store"];
7+
208
private deviceInitializationPromise: IDictionary<Promise<FilesPayload>> = {};
219

22-
constructor(private $fs: IFileSystem,
10+
constructor(
2311
private $errors: IErrors,
2412
private $hooksService: IHooksService,
2513
private $logger: ILogger,
26-
private $platformService: IPlatformService,
2714
private $platformsData: IPlatformsData,
2815
private $projectDataService: IProjectDataService,
2916
private $previewSdkService: IPreviewSdkService,
17+
private $previewAppFilesService: IPreviewAppFilesService,
3018
private $previewAppPluginsService: IPreviewAppPluginsService,
3119
private $previewDevicesService: IPreviewDevicesService,
32-
private $projectFilesManager: IProjectFilesManager,
3320
private $hmrStatusService: IHmrStatusService,
34-
private $projectFilesProvider: IProjectFilesProvider) { }
21+
) { }
3522

3623
public async initialize(data: IPreviewAppLiveSyncData): Promise<void> {
3724
await this.$previewSdkService.initialize(async (device: Device) => {
@@ -65,8 +52,9 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
6552
.map(device => device.platform)
6653
.uniq()
6754
.value();
55+
6856
for (const platform of platforms) {
69-
await this.syncFilesForPlatformSafe(data, platform, { filesToSync, filesToRemove, useHotModuleReload: data.useHotModuleReload });
57+
await this.syncFilesForPlatformSafe(data, { filesToSync, filesToRemove }, platform);
7058
}
7159
}
7260

@@ -78,7 +66,7 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
7866
const hookArgs = this.getHookArgs(data, device);
7967
await this.$hooksService.executeBeforeHooks("preview-sync", { hookArgs });
8068
await this.$previewAppPluginsService.comparePluginsOnDevice(data, device);
81-
const payloads = await this.syncFilesForPlatformSafe(data, device.platform, { isInitialSync: true, useHotModuleReload: data.useHotModuleReload });
69+
const payloads = await this.syncInitialFilesForPlatformSafe(data, device.platform);
8270
return payloads;
8371
}
8472

@@ -106,14 +94,55 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
10694
return result;
10795
}
10896

97+
private async syncInitialFilesForPlatformSafe(data: IPreviewAppLiveSyncData, platform: string): Promise<FilesPayload> {
98+
this.$logger.info(`Start syncing changes for platform ${platform}.`);
99+
100+
try {
101+
const payloads = this.$previewAppFilesService.getInitialFilesPayload(data, platform);
102+
this.$logger.info(`Successfully synced changes for platform ${platform}.`);
103+
return payloads;
104+
} catch (err) {
105+
this.$logger.warn(`Unable to apply changes for platform ${platform}. Error is: ${err}, ${JSON.stringify(err, null, 2)}.`);
106+
}
107+
}
108+
109+
private async syncFilesForPlatformSafe(data: IPreviewAppLiveSyncData, filesData: IPreviewAppFilesData, platform: string, deviceId?: string): Promise<FilesPayload> {
110+
this.$logger.info(`Start syncing changes for platform ${platform}.`);
111+
112+
try {
113+
const payloads = this.$previewAppFilesService.getFilesPayload(data, filesData, platform);
114+
await this.$previewSdkService.applyChanges(payloads);
115+
this.$logger.info(`Successfully synced ${payloads.files.map(filePayload => filePayload.file.yellow)} for platform ${platform}.`);
116+
return payloads;
117+
} catch (err) {
118+
this.$logger.warn(`Unable to apply changes for platform ${platform}. Error is: ${err}, ${JSON.stringify(err, null, 2)}.`);
119+
}
120+
}
121+
109122
private async onWebpackCompilationComplete(data: IPreviewAppLiveSyncData, hmrData: IDictionary<IPlatformHmrData>, filesToSyncMap: IDictionary<string[]>, promise: Promise<FilesPayload>, platform: string) {
110123
await promise
111124
.then(async () => {
112125
const currentHmrData = _.cloneDeep(hmrData);
113126
const platformHmrData = currentHmrData[platform] || <any>{};
114-
const filesToSync = _.cloneDeep(filesToSyncMap[platform]);
115-
// We don't need to prepare when webpack emits changed files. We just need to send a message to pubnub.
116-
promise = this.syncFilesForPlatformSafe(data, platform, { filesToSync, skipPrepare: true, useHotModuleReload: data.useHotModuleReload });
127+
const projectData = this.$projectDataService.getProjectData(data.projectDir);
128+
const platformData = this.$platformsData.getPlatformData(platform, projectData);
129+
const clonedFiles = _.cloneDeep(filesToSyncMap[platform]);
130+
const filesToSync = _.map(clonedFiles, fileToSync => {
131+
const result = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME, path.relative(projectData.getAppDirectoryPath(), fileToSync));
132+
console.log(result);
133+
return result;
134+
});
135+
136+
// console.log("####### FILES TO SYNC!!!!!!! %%%%%%%% ", filesToSync, data.projectDir, platformData);
137+
// console.log("####### appDestinationDirectoryPath!!!! ", platformData.appDestinationDirectoryPath);
138+
// console.log("hjfjdjgdfjgjfgjgj !!!!! ", projectData.getAppDirectoryPath());
139+
140+
// filesToSync = filesToSync.map(fileToSync => {
141+
// console.log("appDestinationDirectoryPath !!!! ", platformData.appDestinationDirectoryPath);
142+
// console.log("relative path!!!!!", path.relative(projectData.getAppDirectoryPath(), fileToSync));
143+
// return result;
144+
// });
145+
promise = this.syncFilesForPlatformSafe(data, { filesToSync }, platform);
117146
await promise;
118147

119148
if (data.useHotModuleReload && platformHmrData.hash) {
@@ -122,123 +151,18 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService {
122151
await Promise.all(_.map(devices, async (previewDevice: Device) => {
123152
const status = await this.$hmrStatusService.getHmrStatus(previewDevice.id, platformHmrData.hash);
124153
if (status === HmrConstants.HMR_ERROR_STATUS) {
125-
await this.syncFilesForPlatformSafe(data, platform, { filesToSync: platformHmrData.fallbackFiles, useHotModuleReload: false, deviceId: previewDevice.id });
154+
// TODO: SET useHotModuleReload: false,
155+
await this.syncFilesForPlatformSafe(data, { filesToSync: platformHmrData.fallbackFiles }, platform, previewDevice.id );
126156
}
127157
}));
128158
}
129159
});
130160
filesToSyncMap[platform] = [];
131161
}
132162

133-
private async syncFilesForPlatformSafe(data: IPreviewAppLiveSyncData, platform: string, opts?: ISyncFilesOptions): Promise<FilesPayload> {
134-
this.$logger.info(`Start syncing changes for platform ${platform}.`);
135-
136-
opts = opts || {};
137-
let payloads = null;
138-
139-
try {
140-
const { env, projectDir } = data;
141-
const projectData = this.$projectDataService.getProjectData(projectDir);
142-
const platformData = this.$platformsData.getPlatformData(platform, projectData);
143-
144-
if (!opts.skipPrepare) {
145-
await this.preparePlatform(platform, data, env, projectData);
146-
}
147-
148-
if (opts.isInitialSync) {
149-
const platformsAppFolderPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME);
150-
opts.filesToSync = this.$projectFilesManager.getProjectFiles(platformsAppFolderPath);
151-
payloads = this.getFilesPayload(platformData, projectData, opts);
152-
this.$logger.info(`Successfully synced changes for platform ${platform}.`);
153-
} else {
154-
opts.filesToSync = _.map(opts.filesToSync, file => this.$projectFilesProvider.mapFilePath(file, platformData.normalizedPlatformName, projectData));
155-
payloads = this.getFilesPayload(platformData, projectData, opts);
156-
await this.$previewSdkService.applyChanges(payloads);
157-
this.$logger.info(`Successfully synced ${payloads.files.map(filePayload => filePayload.file.yellow)} for platform ${platform}.`);
158-
}
159-
160-
return payloads;
161-
} catch (err) {
162-
this.$logger.warn(`Unable to apply changes for platform ${platform}. Error is: ${err}, ${JSON.stringify(err, null, 2)}.`);
163-
}
164-
}
165-
166-
private getFilesPayload(platformData: IPlatformData, projectData: IProjectData, opts?: ISyncFilesOptions): FilesPayload {
167-
const { filesToSync, filesToRemove, deviceId } = opts;
168-
169-
const filesToTransfer = filesToSync
170-
.filter(file => file.indexOf(TNS_MODULES_FOLDER_NAME) === -1)
171-
.filter(file => file.indexOf(APP_RESOURCES_FOLDER_NAME) === -1)
172-
.filter(file => !_.includes(this.excludedFiles, path.basename(file)))
173-
.filter(file => !_.includes(this.excludedFileExtensions, path.extname(file)));
174-
175-
this.$logger.trace(`Transferring ${filesToTransfer.join("\n")}.`);
176-
177-
const payloadsToSync = filesToTransfer.map(file => this.createFilePayload(file, platformData, projectData, PreviewSdkEventNames.CHANGE_EVENT_NAME));
178-
const payloadsToRemove = _.map(filesToRemove, file => this.createFilePayload(file, platformData, projectData, PreviewSdkEventNames.UNLINK_EVENT_NAME));
179-
const payloads = payloadsToSync.concat(payloadsToRemove);
180-
181-
const hmrMode = opts.useHotModuleReload ? 1 : 0;
182-
return { files: payloads, platform: platformData.normalizedPlatformName.toLowerCase(), hmrMode, deviceId };
183-
}
184-
185-
private async preparePlatform(platform: string, data: IPreviewAppLiveSyncData, env: Object, projectData: IProjectData): Promise<void> {
186-
const appFilesUpdaterOptions = {
187-
bundle: data.bundle,
188-
useHotModuleReload: data.useHotModuleReload,
189-
release: false
190-
};
191-
const nativePrepare = { skipNativePrepare: true };
192-
const config = <IPlatformOptions>{};
193-
const platformTemplate = <string>null;
194-
const prepareInfo = {
195-
platform,
196-
appFilesUpdaterOptions,
197-
env,
198-
projectData,
199-
nativePrepare,
200-
config,
201-
platformTemplate,
202-
skipCopyTnsModules: true,
203-
skipCopyAppResourcesFiles: true
204-
};
205-
await this.$platformService.preparePlatform(prepareInfo);
206-
}
207-
208163
private showWarningsForNativeFiles(files: string[]): void {
209164
_.filter(files, file => file.indexOf(APP_RESOURCES_FOLDER_NAME) > -1)
210165
.forEach(file => this.$logger.warn(`Unable to apply changes from ${APP_RESOURCES_FOLDER_NAME} folder. You need to build your application in order to make changes in ${APP_RESOURCES_FOLDER_NAME} folder.`));
211166
}
212-
213-
private createFilePayload(file: string, platformData: IPlatformData, projectData: IProjectData, event: string): FilePayload {
214-
const projectFileInfo = this.$projectFilesProvider.getProjectFileInfo(file, platformData.normalizedPlatformName, null);
215-
const binary = isTextOrBinary.isBinarySync(file);
216-
let fileContents = "";
217-
let filePath = "";
218-
219-
if (event === PreviewSdkEventNames.CHANGE_EVENT_NAME) {
220-
const relativePath = path.relative(path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME), file);
221-
filePath = path.join(path.dirname(relativePath), projectFileInfo.onDeviceFileName);
222-
223-
if (binary) {
224-
const bitmap = <string>this.$fs.readFile(file);
225-
const base64 = Buffer.from(bitmap).toString('base64');
226-
fileContents = base64;
227-
} else {
228-
fileContents = this.$fs.readText(path.join(path.dirname(projectFileInfo.filePath), projectFileInfo.onDeviceFileName));
229-
}
230-
} else if (event === PreviewSdkEventNames.UNLINK_EVENT_NAME) {
231-
filePath = path.relative(path.join(projectData.projectDir, APP_FOLDER_NAME), file);
232-
}
233-
234-
const filePayload = {
235-
event,
236-
file: filePath,
237-
binary,
238-
fileContents
239-
};
240-
241-
return filePayload;
242-
}
243167
}
244168
$injector.register("previewAppLiveSyncService", PreviewAppLiveSyncService);

lib/services/livesync/playground/preview-sdk-service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export class PreviewSdkService extends EventEmitter implements IPreviewSdkServic
7575
onDevicesPresence: (devices: Device[]) => this.$previewDevicesService.updateConnectedDevices(devices),
7676
onSendingChange: (sending: boolean) => ({ }),
7777
onBiggerFilesUpload: async (filesContent, callback) => {
78+
console.log("ON BIGGER FILES UPLOAD!!!!!!!!!!!!");
7879
const gzippedContent = Buffer.from(pako.gzip(filesContent));
7980
const byteLength = filesContent.length;
8081

0 commit comments

Comments
 (0)