diff --git a/local-cli/server/util/attachHMRServer.js b/local-cli/server/util/attachHMRServer.js index 572d3792a..e039edef5 100644 --- a/local-cli/server/util/attachHMRServer.js +++ b/local-cli/server/util/attachHMRServer.js @@ -20,6 +20,7 @@ function attachHMRServer({httpServer, path, packagerServer}) { function disconnect() { client = null; + packagerServer.setHMRFileChangeListener(null); } // Returns a promise with the full list of dependencies and the shallow @@ -59,41 +60,6 @@ function attachHMRServer({httpServer, path, packagerServer}) { }); } - packagerServer.addFileChangeListener(filename => { - if (!client) { - return; - } - - packagerServer.getShallowDependencies(filename) - .then(deps => { - // if the file dependencies have change we need to invalidate the - // dependencies caches because the list of files we need to send to the - // client may have changed - if (arrayEquals(deps, client.shallowDependencies[filename])) { - return Promise.resolve(); - } - return getDependencies(client.platform, client.bundleEntry) - .then(({dependenciesCache, shallowDependencies}) => { - // invalidate caches - client.dependenciesCache = dependenciesCache; - client.shallowDependencies = shallowDependencies; - }); - }) - .then(() => { - // make sure the file was modified is part of the bundle - if (!client.shallowDependencies[filename]) { - return; - } - - return packagerServer.buildBundleForHMR({ - platform: client.platform, - entryFile: filename, - }) - .then(bundle => client.ws.send(bundle)); - }) - .done(); - }); - const WebSocketServer = require('ws').Server; const wss = new WebSocketServer({ server: httpServer, @@ -115,6 +81,40 @@ function attachHMRServer({httpServer, path, packagerServer}) { shallowDependencies, }; + packagerServer.setHMRFileChangeListener(filename => { + if (!client) { + return Promise.resolve(); + } + + return packagerServer.getShallowDependencies(filename) + .then(deps => { + // if the file dependencies have change we need to invalidate the + // dependencies caches because the list of files we need to send + // to the client may have changed + if (arrayEquals(deps, client.shallowDependencies[filename])) { + return Promise.resolve(); + } + return getDependencies(client.platform, client.bundleEntry) + .then(({dependenciesCache, shallowDependencies}) => { + // invalidate caches + client.dependenciesCache = dependenciesCache; + client.shallowDependencies = shallowDependencies; + }); + }) + .then(() => { + // make sure the file was modified is part of the bundle + if (!client.shallowDependencies[filename]) { + return; + } + + return packagerServer.buildBundleForHMR({ + platform: client.platform, + entryFile: filename, + }) + .then(bundle => client.ws.send(bundle)); + }); + }); + client.ws.on('error', e => { console.error('[Hot Module Replacement] Unexpected error', e); disconnect(); diff --git a/packager/react-packager/src/Server/index.js b/packager/react-packager/src/Server/index.js index a6bb6b344..717ef9e17 100644 --- a/packager/react-packager/src/Server/index.js +++ b/packager/react-packager/src/Server/index.js @@ -191,6 +191,16 @@ class Server { this._fileWatcher.on('all', this._onFileChange.bind(this)); this._debouncedFileChangeHandler = _.debounce(filePath => { + // if Hot Loading is enabled avoid rebuilding bundles and sending live + // updates. Instead, send the HMR updates right away and once that + // finishes, invoke any other file change listener. + if (this._hmrFileChangeListener) { + this._hmrFileChangeListener(filePath).then(() => { + this._fileChangeListeners.forEach(listener => listener(filePath)); + }).done(); + return; + } + this._fileChangeListeners.forEach(listener => listener(filePath)); this._rebuildBundles(filePath); this._informChangeWatchers(); @@ -208,6 +218,10 @@ class Server { this._fileChangeListeners.push(listener); } + setHMRFileChangeListener(listener) { + this._hmrFileChangeListener = listener; + } + buildBundle(options) { return Promise.resolve().then(() => { if (!options.platform) {