Always use the HMR transforms when building the bundle from the metro-bundler server

Summary:
This diff enables the HMR transforms for any bundle requested through the metro-bundler HTTP server, so it ignores the `hot` parameter passed in the URL.

This allows much faster switches when enabling/disabling HMR, since metro-bundler does not need to re-compile each single file again, while not impacting substantially build times when HMR is off.

I've done some lightweight benchmarks on my machine and these are the results (all the tests have been done after running metro-bundler with a clean cache and restarting the app).

**Before**

Time to build (HMR off): 1x (baseline)
Time to build (HMR on): 1.90x

**This diff**

Time to build (HMR off): 1.009x
Time to build (HMR on): 1.036x

(The reason why now it takes double the time to load the HMR bundle than the non-HMR bundle after launching the app is because the device after a restart always asks for the non-HMR bundle and afterwards the HMR bundle, causing the server to have to build both bundles).

**Bundle size**
In terms of bundle size, adding the HMR transforms increases the size by around 3-4% (this regression is due to the wrappers added around React components, and will depend on the app).

**Next steps**

There are two improvements to do after this diff:

1. Remove the `hot=true` parameter from the clients when they request the bundle. This will reduce by half the memory used by metro-bundler when switching from non-HMR to HMR (or when opening the app with HMR enabled), since metro-bundler caches the bundles based on url.
2. After this diff, the `hot` parameter in the various options objects will not make much sense, so my suggestion is to just remove it from everywhere and instead of checking for that parameter in the transformer, check for `dev=true` there.

Reviewed By: davidaurelio

Differential Revision: D5623623

fbshipit-source-id: cb76b9182e55f442e2987fcf59eee2ba2571578e
This commit is contained in:
Rafael Oleza 2017-08-15 18:35:46 -07:00 committed by Facebook Github Bot
parent a78be6ce0a
commit 409a2ae809
3 changed files with 31 additions and 7 deletions

View File

@ -160,7 +160,7 @@ describe('processRequest', () => {
entryModuleOnly: false, entryModuleOnly: false,
excludeSource: false, excludeSource: false,
generateSourceMaps: false, generateSourceMaps: false,
hot: false, hot: true,
inlineSourceMap: false, inlineSourceMap: false,
isolateModuleIDs: false, isolateModuleIDs: false,
minify: false, minify: false,
@ -188,7 +188,7 @@ describe('processRequest', () => {
entryModuleOnly: false, entryModuleOnly: false,
excludeSource: false, excludeSource: false,
generateSourceMaps: false, generateSourceMaps: false,
hot: false, hot: true,
inlineSourceMap: false, inlineSourceMap: false,
isolateModuleIDs: false, isolateModuleIDs: false,
minify: false, minify: false,
@ -216,7 +216,7 @@ describe('processRequest', () => {
entryModuleOnly: false, entryModuleOnly: false,
excludeSource: false, excludeSource: false,
generateSourceMaps: false, generateSourceMaps: false,
hot: false, hot: true,
inlineSourceMap: false, inlineSourceMap: false,
isolateModuleIDs: false, isolateModuleIDs: false,
minify: false, minify: false,
@ -481,7 +481,7 @@ describe('processRequest', () => {
entryModuleOnly: false, entryModuleOnly: false,
excludeSource: true, excludeSource: true,
generateSourceMaps: true, generateSourceMaps: true,
hot: false, hot: true,
inlineSourceMap: false, inlineSourceMap: false,
isolateModuleIDs: false, isolateModuleIDs: false,
minify: false, minify: false,
@ -495,6 +495,31 @@ describe('processRequest', () => {
}) })
); );
}); });
it('ignores the `hot` parameter (since it is not used anymore)', () => {
return server.buildBundleFromUrl('/path/to/foo.bundle?dev=false&hot=false&runModule=false')
.then(() =>
expect(Bundler.prototype.bundle).toBeCalledWith({
assetPlugins: [],
dev: false,
entryFile: 'path/to/foo.js',
entryModuleOnly: false,
excludeSource: false,
generateSourceMaps: true,
hot: true,
inlineSourceMap: false,
isolateModuleIDs: false,
minify: false,
onProgress: null,
platform: null,
resolutionResponse: null,
runBeforeMainModule: ['InitializeCore'],
runModule: false,
sourceMapUrl: '/path/to/foo.map?dev=false&hot=false&runModule=false',
unbundle: false,
})
);
});
}); });
describe('/symbolicate endpoint', () => { describe('/symbolicate endpoint', () => {

View File

@ -1014,7 +1014,7 @@ class Server {
dev, dev,
minify, minify,
excludeSource, excludeSource,
hot: this._getBoolOptionFromQuery(urlObj.query, 'hot', false), hot: true,
runBeforeMainModule: defaults.runBeforeMainModule, runBeforeMainModule: defaults.runBeforeMainModule,
runModule: this._getBoolOptionFromQuery(urlObj.query, 'runModule', true), runModule: this._getBoolOptionFromQuery(urlObj.query, 'runModule', true),
inlineSourceMap: this._getBoolOptionFromQuery( inlineSourceMap: this._getBoolOptionFromQuery(

View File

@ -108,11 +108,10 @@ class TerminalReporter {
): string { ): string {
const localPath = path.relative('.', bundleOptions.entryFile); const localPath = path.relative('.', bundleOptions.entryFile);
return util.format( return util.format(
'Bundling `%s` [%s, %s, %s] %s%s%% (%s/%s)%s', 'Bundling `%s` [%s, %s] %s%s%% (%s/%s)%s',
localPath, localPath,
bundleOptions.dev ? 'development' : 'production', bundleOptions.dev ? 'development' : 'production',
bundleOptions.minify ? 'minified' : 'non-minified', bundleOptions.minify ? 'minified' : 'non-minified',
bundleOptions.hot ? 'hmr enabled' : 'hmr disabled',
phase === 'in_progress' ? getProgressBar(ratio, 16) + ' ' : '', phase === 'in_progress' ? getProgressBar(ratio, 16) + ' ' : '',
(100 * ratio).toFixed(1), (100 * ratio).toFixed(1),
transformedFileCount, transformedFileCount,