mirror of https://github.com/status-im/metro.git
Move preloaded modules to startup code section
Summary:We found that moving the preloaded modules to the startup section of the RAM Bundle improves TTI quite a bit by saving lots of through the bridge calls and injecting multiple modules at once on JSC. However, doing this on a non hacky way required a lot of work. The main changes this diff does are: - Add to `BundleBase` additional bundling options. This options are fetched based on the entry file we're building by invoking a module that exports a function (`getBundleOptionsModulePath`). - Implement `BundleOptions` module to include the `numPreloadedModules` attribute as a bundle additional option. This value is computed by getting the dependencies the entry file has and looking for the first module that exports a module we don't want to preload. The `numPreloadedModules` attribute is then used to decide where to splice the array of modules. - Additional kung fu to make sure sourcemaps work for both preloaded and non preloaded modules. Reviewed By: davidaurelio Differential Revision: D3046534 fb-gh-sync-id: 80b676222ca3bb8b9eecc912a7963be94d3dee1a shipit-source-id: 80b676222ca3bb8b9eecc912a7963be94d3dee1a
This commit is contained in:
parent
18612273be
commit
c0f446d7e2
|
@ -25,6 +25,8 @@ class Bundle extends BundleBase {
|
|||
this._numPrependedModules = 0;
|
||||
this._numRequireCalls = 0;
|
||||
this._minify = minify;
|
||||
|
||||
this._ramBundle = null; // cached RAM Bundle
|
||||
}
|
||||
|
||||
addModule(resolver, resolutionResponse, module, moduleTransport) {
|
||||
|
@ -73,6 +75,7 @@ class Bundle extends BundleBase {
|
|||
virtual: true,
|
||||
sourceCode: code,
|
||||
sourcePath: name + '.js',
|
||||
meta: {preloaded: true},
|
||||
}));
|
||||
this._numRequireCalls += 1;
|
||||
}
|
||||
|
@ -103,7 +106,46 @@ class Bundle extends BundleBase {
|
|||
return source;
|
||||
}
|
||||
|
||||
getUnbundle() {
|
||||
getUnbundle(type) {
|
||||
if (this._ramBundle) {
|
||||
return this._ramBundle;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'INDEX':
|
||||
this._ramBundle = this._getAsIndexedFileUnbundle();
|
||||
break;
|
||||
case 'ASSETS':
|
||||
this._ramBundle = this._getAsAssetsUnbundle();
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unkown RAM Bundle type:', type);
|
||||
}
|
||||
|
||||
return this._ramBundle;
|
||||
}
|
||||
|
||||
_getAsIndexedFileUnbundle() {
|
||||
const modules = this.getModules();
|
||||
|
||||
// separate modules we need to preload from the ones we don't
|
||||
const shouldPreload = (module) => module.meta && module.meta.preloaded;
|
||||
const preloaded = modules.filter(module => shouldPreload(module));
|
||||
const notPreloaded = modules.filter(module => !shouldPreload(module));
|
||||
|
||||
// code that will be executed on bridge start up
|
||||
const startupCode = preloaded.map(({code}) => code).join('\n');
|
||||
|
||||
return {
|
||||
// include copy of all modules on the order they're writen on the bundle:
|
||||
// polyfills, preloaded, additional requires, non preloaded
|
||||
allModules: preloaded.concat(notPreloaded),
|
||||
startupCode, // no entries on the index for these modules, only the code
|
||||
modules: notPreloaded, // we include both the code and entries on the index
|
||||
};
|
||||
}
|
||||
|
||||
_getAsAssetsUnbundle() {
|
||||
const allModules = this.getModules().slice();
|
||||
const prependedModules = this._numPrependedModules;
|
||||
const requireCalls = this._numRequireCalls;
|
||||
|
|
|
@ -60,9 +60,8 @@ class BundleBase {
|
|||
|
||||
finalize(options) {
|
||||
Object.freeze(this._modules);
|
||||
Object.seal(this._modules);
|
||||
Object.freeze(this._assets);
|
||||
Object.seal(this._assets);
|
||||
|
||||
this._finalized = true;
|
||||
}
|
||||
|
||||
|
@ -97,9 +96,8 @@ class BundleBase {
|
|||
bundle.setMainModuleId(json.mainModuleId);
|
||||
|
||||
Object.freeze(bundle._modules);
|
||||
Object.seal(bundle._modules);
|
||||
Object.freeze(bundle._assets);
|
||||
Object.seal(bundle._assets);
|
||||
|
||||
bundle._finalized = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -356,13 +356,13 @@ class Bundler {
|
|||
const modulesByName = Object.create(null);
|
||||
|
||||
if (!resolutionResponse) {
|
||||
let onProgess = noop;
|
||||
let onProgress = noop;
|
||||
if (process.stdout.isTTY && !this._opts.silent) {
|
||||
const bar = new ProgressBar(
|
||||
'transformed :current/:total (:percent)',
|
||||
{complete: '=', incomplete: ' ', width: 40, total: 1},
|
||||
);
|
||||
onProgess = (_, total) => {
|
||||
onProgress = (_, total) => {
|
||||
bar.total = total;
|
||||
bar.tick();
|
||||
};
|
||||
|
@ -373,7 +373,7 @@ class Bundler {
|
|||
dev,
|
||||
platform,
|
||||
hot,
|
||||
onProgess,
|
||||
onProgress,
|
||||
minify,
|
||||
generateSourceMaps: unbundle,
|
||||
});
|
||||
|
@ -383,10 +383,22 @@ class Bundler {
|
|||
Activity.endEvent(findEventId);
|
||||
onResolutionResponse(response);
|
||||
|
||||
// get entry file complete path (`entryFile` is relative to roots)
|
||||
let entryFilePath;
|
||||
if (response.dependencies.length > 0) {
|
||||
const numModuleSystemDependencies =
|
||||
this._resolver.getModuleSystemDependencies({dev, unbundle}).length;
|
||||
entryFilePath = response.dependencies[
|
||||
response.numPrependedDependencies +
|
||||
numModuleSystemDependencies
|
||||
].path;
|
||||
}
|
||||
|
||||
const toModuleTransport = module =>
|
||||
this._toModuleTransport({
|
||||
module,
|
||||
bundle,
|
||||
entryFilePath,
|
||||
transformOptions: response.transformOptions,
|
||||
}).then(transformed => {
|
||||
modulesByName[transformed.name] = module;
|
||||
|
@ -432,7 +444,7 @@ class Bundler {
|
|||
hot = false,
|
||||
recursive = true,
|
||||
generateSourceMaps = false,
|
||||
onProgess,
|
||||
onProgress,
|
||||
}) {
|
||||
return this.getTransformOptions(
|
||||
entryFile,
|
||||
|
@ -450,11 +462,12 @@ class Bundler {
|
|||
platform,
|
||||
transform: transformSpecificOptions,
|
||||
};
|
||||
|
||||
return this._resolver.getDependencies(
|
||||
entryFile,
|
||||
{dev, platform, recursive},
|
||||
transformOptions,
|
||||
onProgess,
|
||||
onProgress,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -491,7 +504,7 @@ class Bundler {
|
|||
);
|
||||
}
|
||||
|
||||
_toModuleTransport({module, bundle, transformOptions}) {
|
||||
_toModuleTransport({module, bundle, entryFilePath, transformOptions}) {
|
||||
let moduleTransport;
|
||||
if (module.isAsset_DEPRECATED()) {
|
||||
moduleTransport = this._generateAssetModule_DEPRECATED(bundle, module);
|
||||
|
@ -509,15 +522,24 @@ class Bundler {
|
|||
module.read(transformOptions),
|
||||
]).then((
|
||||
[name, {code, dependencies, dependencyOffsets, map, source}]
|
||||
) => new ModuleTransport({
|
||||
name,
|
||||
id: this._getModuleId(module),
|
||||
code,
|
||||
map,
|
||||
meta: {dependencies, dependencyOffsets},
|
||||
sourceCode: source,
|
||||
sourcePath: module.path
|
||||
}));
|
||||
) => {
|
||||
const preloaded =
|
||||
module.path === entryFilePath ||
|
||||
module.isPolyfill() || (
|
||||
transformOptions.transform.preloadedModules &&
|
||||
transformOptions.transform.preloadedModules.hasOwnProperty(module.path)
|
||||
);
|
||||
|
||||
return new ModuleTransport({
|
||||
name,
|
||||
id: this._getModuleId(module),
|
||||
code,
|
||||
map,
|
||||
meta: {dependencies, dependencyOffsets, preloaded},
|
||||
sourceCode: source,
|
||||
sourcePath: module.path
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
getGraphDebugInfo() {
|
||||
|
|
|
@ -136,7 +136,11 @@ class SocketServer {
|
|||
_reply(sock, id, type, data) {
|
||||
debug('request finished', type);
|
||||
|
||||
data = toJSON(data);
|
||||
try {
|
||||
data = toJSON(data);
|
||||
} catch (e) {
|
||||
console.error('SocketServer exception:', e);
|
||||
}
|
||||
|
||||
sock.write(bser.dumpToBuffer({
|
||||
id,
|
||||
|
|
Loading…
Reference in New Issue