Make Hot Loading faster
Summary: public Before this this when a file was changed besides sending the HMR update we rebuild every single bundle that the packager had build (to serve it faster when the user hit cmd+r). Since when hot loading is enabled we don't do cmd+r all this work was pointless (except for when you're developing multiple apps using the same packager instance at the same time, which we can assume is very uncommon). As a consequence, the HMR update was competing with the rebundling job making HMR quite slow (i.e.: on one huge internal app it took up to 6s for the HMR changes to get applied). So, this diff tweaks the file change listener so that we don't rebundle nor invoke the fileWatchers (use for live reload which is also useless when hot load is enabled) when hot loading is enabled. Also, it makes the HMR listener more high pri than the other listeners so that the HMR dev experience is as good as it can get. Reviewed By: vjeux Differential Revision: D2793827 fb-gh-sync-id: 724930db9f44974c15ad3f562910b0885e44efde
This commit is contained in:
parent
b5081abae3
commit
e75e861116
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue