mirror of https://github.com/status-im/metro.git
Move the asset JS generation logic to the worker
Summary: With this, we do all the transformation and wrapping of files inside the workers, which mean faster initial builds (because parallelization and caching), and more legacy code that can be removed (see the following diff). I've done some tests locally, and while the initial builds are slightly faster, the increase is not super substantial (the big win was in the diff were I moved the wrapping of JS files, in this diff only the assets transformation has speed up). The most important thing that this diff enables is the possibility of doing the minification of modules also in the worker. This will mean that we can cache minified files and prod builds will get significantly faster - almost as fast as development builds (this will be relevant mainly for the opensource community). Reviewed By: davidaurelio Differential Revision: D6439144 fbshipit-source-id: ba2200569a668fcbe68dbfa2b3b60b3db6673326
This commit is contained in:
parent
f3ea76a0b4
commit
8c43848a1e
|
@ -29,7 +29,7 @@ const {sep: pathSeparator} = require('path');
|
|||
const VERSION = require('../../package.json').version;
|
||||
|
||||
import type AssetServer from '../AssetServer';
|
||||
import type Module, {HasteImpl} from '../node-haste/Module';
|
||||
import type {HasteImpl} from '../node-haste/Module';
|
||||
import type {MappingsMap, SourceMap} from '../lib/SourceMap';
|
||||
import type {Options as JSTransformerOptions} from '../JSTransformer/worker';
|
||||
import type {Reporter} from '../lib/reporting';
|
||||
|
@ -215,6 +215,8 @@ class Bundler {
|
|||
code,
|
||||
module.isPolyfill(),
|
||||
transformCodeOptions,
|
||||
this._opts.assetExts,
|
||||
this._opts.assetRegistryPath,
|
||||
),
|
||||
transformCache: opts.transformCache,
|
||||
watch: opts.watch,
|
||||
|
|
|
@ -441,14 +441,7 @@ class DeltaTransformer extends EventEmitter {
|
|||
nullthrows(dependencyPairs.get(dependency)),
|
||||
);
|
||||
|
||||
if (module.isAsset()) {
|
||||
wrappedCode = await this._wrapAsset({
|
||||
code: metadata.code,
|
||||
dependencyPairs,
|
||||
name,
|
||||
path: module.path,
|
||||
});
|
||||
} else if (!module.isPolyfill()) {
|
||||
if (!module.isPolyfill()) {
|
||||
wrappedCode = this._addDependencyMap({
|
||||
code: metadata.code,
|
||||
dependencies,
|
||||
|
|
|
@ -61,6 +61,8 @@ describe('Transformer', function() {
|
|||
code,
|
||||
false,
|
||||
transformOptions,
|
||||
[],
|
||||
'',
|
||||
);
|
||||
|
||||
expect(api.transform).toBeCalledWith(
|
||||
|
@ -70,6 +72,8 @@ describe('Transformer', function() {
|
|||
code,
|
||||
false,
|
||||
transformOptions,
|
||||
[],
|
||||
'',
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@ module.exports = class Transformer {
|
|||
code: string,
|
||||
isScript: boolean,
|
||||
options: Options,
|
||||
assetExts: $ReadOnlyArray<string>,
|
||||
assetRegistryPath: string,
|
||||
): Promise<TransformedCode> {
|
||||
try {
|
||||
debug('Started ransforming file', filename);
|
||||
|
@ -96,6 +98,8 @@ module.exports = class Transformer {
|
|||
code,
|
||||
isScript,
|
||||
options,
|
||||
assetExts,
|
||||
assetRegistryPath,
|
||||
);
|
||||
|
||||
debug('Done transforming file', filename);
|
||||
|
|
|
@ -31,6 +31,8 @@ describe('code transformation worker:', () => {
|
|||
dev: true,
|
||||
transform: {},
|
||||
},
|
||||
[],
|
||||
'',
|
||||
);
|
||||
|
||||
expect(result.code).toBe(
|
||||
|
@ -55,6 +57,8 @@ describe('code transformation worker:', () => {
|
|||
dev: true,
|
||||
transform: {},
|
||||
},
|
||||
[],
|
||||
'',
|
||||
);
|
||||
|
||||
expect(result.code).toBe(
|
||||
|
@ -84,6 +88,8 @@ describe('code transformation worker:', () => {
|
|||
dev: true,
|
||||
transform: {},
|
||||
},
|
||||
[],
|
||||
'',
|
||||
);
|
||||
|
||||
expect(result.code).toBe(
|
||||
|
|
|
@ -14,12 +14,15 @@
|
|||
|
||||
const JsFileWrapping = require('../../ModuleGraph/worker/JsFileWrapping');
|
||||
|
||||
const assetTransformer = require('../../assetTransformer');
|
||||
const babylon = require('babylon');
|
||||
const collectDependencies = require('../../ModuleGraph/worker/collect-dependencies');
|
||||
const constantFolding = require('./constant-folding');
|
||||
|
||||
const generate = require('babel-generator').default;
|
||||
const inline = require('./inline');
|
||||
const minify = require('./minify');
|
||||
const path = require('path');
|
||||
|
||||
const {compactMapping} = require('../../Bundler/source-map');
|
||||
|
||||
|
@ -166,6 +169,8 @@ function transformCode(
|
|||
sourceCode: string,
|
||||
isScript: boolean,
|
||||
options: Options,
|
||||
assetExts: $ReadOnlyArray<string>,
|
||||
assetRegistryPath: string,
|
||||
): Data | Promise<Data> {
|
||||
const isJson = filename.endsWith('.json');
|
||||
|
||||
|
@ -187,13 +192,18 @@ function transformCode(
|
|||
|
||||
// $FlowFixMe: impossible to type a dynamic require.
|
||||
const transformer: Transformer<*> = require(transformerPath);
|
||||
const transformResult = transformer.transform({
|
||||
|
||||
const transformerArgs = {
|
||||
filename,
|
||||
localPath,
|
||||
options,
|
||||
plugins,
|
||||
src: sourceCode,
|
||||
});
|
||||
};
|
||||
|
||||
const transformResult = isAsset(filename, assetExts)
|
||||
? assetTransformer.transform(transformerArgs, assetRegistryPath)
|
||||
: transformer.transform(transformerArgs);
|
||||
|
||||
const postTransformArgs = [
|
||||
filename,
|
||||
|
@ -204,7 +214,7 @@ function transformCode(
|
|||
transformFileStartLogEntry,
|
||||
];
|
||||
|
||||
return typeof transformResult.then === 'function'
|
||||
return transformResult instanceof Promise
|
||||
? transformResult.then(({ast}) => postTransform(...postTransformArgs, ast))
|
||||
: postTransform(...postTransformArgs, transformResult.ast);
|
||||
}
|
||||
|
@ -227,6 +237,10 @@ function minifyCode(
|
|||
}
|
||||
}
|
||||
|
||||
function isAsset(filePath: string, assetExts: $ReadOnlyArray<string>): boolean {
|
||||
return assetExts.indexOf(path.extname(filePath).slice(1)) !== -1;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
transform: transformCode,
|
||||
minify: minifyCode,
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const {getAssetData} = require('./AssetServer/util');
|
||||
const {generateAssetCodeFileAst} = require('./Bundler/util');
|
||||
|
||||
import type {TransformOptions} from './JSTransformer/worker';
|
||||
|
||||
type Params = {
|
||||
localPath: string,
|
||||
filename: string,
|
||||
options: TransformOptions,
|
||||
src: string,
|
||||
};
|
||||
|
||||
async function transform(
|
||||
{filename, localPath, options, src}: Params,
|
||||
assetRegistryPath: string,
|
||||
): Promise<{ast: Ast}> {
|
||||
options = options || {
|
||||
platform: '',
|
||||
projectRoot: '',
|
||||
inlineRequires: false,
|
||||
minify: false,
|
||||
};
|
||||
|
||||
const data = await getAssetData(filename, localPath, options.platform);
|
||||
|
||||
return {
|
||||
ast: generateAssetCodeFileAst(assetRegistryPath, data),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
transform,
|
||||
};
|
|
@ -167,8 +167,18 @@ __d(function (global, require, module, exports, _dependencyMap) {
|
|||
asset: asset
|
||||
};
|
||||
},6,[7]);
|
||||
__d(/* test.png */function(global, require, module, exports) {module.exports=require(8).registerAsset({\\"__packager_asset\\":true,\\"httpServerLocation\\":\\"/assets\\",\\"width\\":8,\\"height\\":8,\\"scales\\":[1],\\"hash\\":\\"77d45c1f7fa73c0f6c444a830dc42f67\\",\\"name\\":\\"test\\",\\"type\\":\\"png\\"}); // 8 = /AssetRegistry
|
||||
}, 7);
|
||||
__d(function (global, require, module, exports, _dependencyMap) {
|
||||
module.exports = require(_dependencyMap[0]).registerAsset({
|
||||
\\"__packager_asset\\": true,
|
||||
\\"httpServerLocation\\": \\"/assets\\",
|
||||
\\"width\\": 8,
|
||||
\\"height\\": 8,
|
||||
\\"scales\\": [1],
|
||||
\\"hash\\": \\"77d45c1f7fa73c0f6c444a830dc42f67\\",
|
||||
\\"name\\": \\"test\\",
|
||||
\\"type\\": \\"png\\"
|
||||
});
|
||||
},7,[8]);
|
||||
__d(function (global, require, module, exports, _dependencyMap) {
|
||||
'use strict';
|
||||
},8,[]);
|
||||
|
@ -328,8 +338,18 @@ __d(function (global, require, module, exports, _dependencyMap) {
|
|||
asset: asset
|
||||
};
|
||||
},4,[5]);
|
||||
__d(/* test.png */function(global, require, module, exports) {module.exports=require(6).registerAsset({\\"__packager_asset\\":true,\\"httpServerLocation\\":\\"/assets\\",\\"width\\":8,\\"height\\":8,\\"scales\\":[1],\\"hash\\":\\"77d45c1f7fa73c0f6c444a830dc42f67\\",\\"name\\":\\"test\\",\\"type\\":\\"png\\"}); // 6 = /AssetRegistry
|
||||
}, 5);
|
||||
__d(function (global, require, module, exports, _dependencyMap) {
|
||||
module.exports = require(_dependencyMap[0]).registerAsset({
|
||||
\\"__packager_asset\\": true,
|
||||
\\"httpServerLocation\\": \\"/assets\\",
|
||||
\\"width\\": 8,
|
||||
\\"height\\": 8,
|
||||
\\"scales\\": [1],
|
||||
\\"hash\\": \\"77d45c1f7fa73c0f6c444a830dc42f67\\",
|
||||
\\"name\\": \\"test\\",
|
||||
\\"type\\": \\"png\\"
|
||||
});
|
||||
},5,[6]);
|
||||
__d(function (global, require, module, exports, _dependencyMap) {
|
||||
'use strict';
|
||||
},6,[]);
|
||||
|
|
|
@ -14,16 +14,7 @@
|
|||
|
||||
const Module = require('./Module');
|
||||
|
||||
import type {CachedReadResult, ConstructorArgs, ReadResult} from './Module';
|
||||
|
||||
class AssetModule extends Module {
|
||||
_dependencies: Array<string>;
|
||||
|
||||
constructor(args: ConstructorArgs & {dependencies: Array<string>}) {
|
||||
super(args);
|
||||
this._dependencies = args.dependencies || [];
|
||||
}
|
||||
|
||||
getPackage() {
|
||||
return null;
|
||||
}
|
||||
|
@ -32,24 +23,6 @@ class AssetModule extends Module {
|
|||
return false;
|
||||
}
|
||||
|
||||
readCached(): CachedReadResult {
|
||||
return {
|
||||
/** $FlowFixMe: improper OOP design. AssetModule, being different from a
|
||||
* normal Module, shouldn't inherit it in the first place. */
|
||||
result: {dependencies: this._dependencies},
|
||||
outdatedDependencies: [],
|
||||
};
|
||||
}
|
||||
|
||||
/** $FlowFixMe: improper OOP design. */
|
||||
readFresh(): Promise<ReadResult> {
|
||||
return Promise.resolve({dependencies: this._dependencies});
|
||||
}
|
||||
|
||||
hash() {
|
||||
return `AssetModule : ${this.path}`;
|
||||
}
|
||||
|
||||
isAsset() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,6 @@ class ModuleCache {
|
|||
*/
|
||||
this._moduleCache[filePath] = new AssetModule({
|
||||
depGraphHelpers: this._depGraphHelpers,
|
||||
dependencies: this._assetDependencies,
|
||||
file: filePath,
|
||||
getTransformCacheKey: this._getTransformCacheKey,
|
||||
globalTransformCache: this._globalTransformCache,
|
||||
|
|
Loading…
Reference in New Issue