diff --git a/lib/services/webpack/webpack-compiler-service.ts b/lib/services/webpack/webpack-compiler-service.ts index 2603f5a762..4f0dd015da 100644 --- a/lib/services/webpack/webpack-compiler-service.ts +++ b/lib/services/webpack/webpack-compiler-service.ts @@ -7,7 +7,7 @@ import { WEBPACK_COMPILATION_COMPLETE, WEBPACK_PLUGIN_NAME } from "../../constan export class WebpackCompilerService extends EventEmitter implements IWebpackCompilerService { private webpackProcesses: IDictionary = {}; - private expectedHash: string = null; + private expectedHashes: IStringDictionary = {}; constructor( private $errors: IErrors, @@ -42,14 +42,14 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp if (message.emittedFiles) { if (isFirstWebpackWatchCompilation) { isFirstWebpackWatchCompilation = false; - this.expectedHash = message.hash; + this.expectedHashes[platformData.platformNameLowerCase] = message.hash; return; } let result; if (prepareData.hmr) { - result = this.getUpdatedEmittedFiles(message.emittedFiles, message.chunkFiles, message.hash); + result = this.getUpdatedEmittedFiles(message.emittedFiles, message.chunkFiles, message.hash, platformData.platformNameLowerCase); } else { result = { emittedFiles: message.emittedFiles, fallbackFiles: [], hash: "" }; } @@ -248,7 +248,7 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp return args; } - public getUpdatedEmittedFiles(allEmittedFiles: string[], chunkFiles: string[], nextHash: string) { + public getUpdatedEmittedFiles(allEmittedFiles: string[], chunkFiles: string[], nextHash: string, platform: string) { const currentHash = this.getCurrentHotUpdateHash(allEmittedFiles); // This logic is needed as there are already cases when webpack doesn't emit any files physically. @@ -260,8 +260,8 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp // if files will be emitted or not. This way, the first successful compilation after fixing the compilation error generates // a hash that is not the same as the one expected in the latest emitted hot-update.json file. // As a result, the hmr chain is broken and the changes are not applied. - const isHashValid = nextHash ? this.expectedHash === currentHash : true; - this.expectedHash = nextHash; + const isHashValid = nextHash ? this.expectedHashes[platform] === currentHash : true; + this.expectedHashes[platform] = nextHash; const emittedHotUpdatesAndAssets = isHashValid ? _.difference(allEmittedFiles, chunkFiles) : allEmittedFiles; diff --git a/test/services/webpack/webpack-compiler-service.ts b/test/services/webpack/webpack-compiler-service.ts index e23a701fa4..22fb85686d 100644 --- a/test/services/webpack/webpack-compiler-service.ts +++ b/test/services/webpack/webpack-compiler-service.ts @@ -2,6 +2,8 @@ import { Yok } from "../../../lib/common/yok"; import { WebpackCompilerService } from "../../../lib/services/webpack/webpack-compiler-service"; import { assert } from "chai"; +const iOSPlatformName = "ios"; +const androidPlatformName = "android"; const chunkFiles = ["bundle.js", "runtime.js", "vendor.js"]; function getAllEmittedFiles(hash: string) { @@ -35,39 +37,54 @@ describe("WebpackCompilerService", () => { describe("getUpdatedEmittedFiles", () => { // backwards compatibility with old versions of nativescript-dev-webpack it("should return only hot updates when nextHash is not provided", async () => { - const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, null); + const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, null, iOSPlatformName); const expectedEmittedFiles = ['bundle.hash1.hot-update.js', 'hash1.hot-update.json']; assert.deepEqual(result.emittedFiles, expectedEmittedFiles); }); // 2 successful webpack compilations it("should return only hot updates when nextHash is provided", async () => { - webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2"); - const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash2"), chunkFiles, "hash3"); + webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2", iOSPlatformName); + const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash2"), chunkFiles, "hash3", iOSPlatformName); assert.deepEqual(result.emittedFiles, ['bundle.hash2.hot-update.js', 'hash2.hot-update.json']); }); // 1 successful webpack compilation, n compilations with no emitted files it("should return all files when there is a webpack compilation with no emitted files", () => { - webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2"); - const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash4"), chunkFiles, "hash5"); + webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2", iOSPlatformName); + const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash4"), chunkFiles, "hash5", iOSPlatformName); assert.deepEqual(result.emittedFiles, ['bundle.js', 'runtime.js', 'bundle.hash4.hot-update.js', 'hash4.hot-update.json']); }); // 1 successful webpack compilation, n compilations with no emitted files, 1 successful webpack compilation it("should return only hot updates after fixing the compilation error", () => { - webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2"); - webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash5"), chunkFiles, "hash6"); - const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash6"), chunkFiles, "hash7"); + webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2", iOSPlatformName); + webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash5"), chunkFiles, "hash6", iOSPlatformName); + const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash6"), chunkFiles, "hash7", iOSPlatformName); assert.deepEqual(result.emittedFiles, ['bundle.hash6.hot-update.js', 'hash6.hot-update.json']); }); // 1 webpack compilation with no emitted files it("should return all files when first compilation on livesync change is not successful", () => { - (webpackCompilerService).expectedHash = "hash1"; - const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2"); + (webpackCompilerService).expectedHashes = { + "ios": "hash1" + }; + const result = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2", iOSPlatformName); assert.deepEqual(result.emittedFiles, ["bundle.hash1.hot-update.js", "hash1.hot-update.json"]); }); + it("should return correct hashes when there are more than one platform", () => { + webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash1"), chunkFiles, "hash2", iOSPlatformName); + webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash3"), chunkFiles, "hash4", androidPlatformName); + + webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash2"), chunkFiles, "hash5", iOSPlatformName); + webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash4"), chunkFiles, "hash6", androidPlatformName); + + const iOSResult = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash5"), chunkFiles, "hash7", iOSPlatformName); + assert.deepEqual(iOSResult.emittedFiles, ["bundle.hash5.hot-update.js", "hash5.hot-update.json"]); + + const androidResult = webpackCompilerService.getUpdatedEmittedFiles(getAllEmittedFiles("hash6"), chunkFiles, "hash8", androidPlatformName); + assert.deepEqual(androidResult.emittedFiles, ["bundle.hash6.hot-update.js", "hash6.hot-update.json"]); + }); }); });