mirror of https://github.com/status-im/metro.git
Use the new Graph object for generating assets
Reviewed By: mjesun Differential Revision: D7275601 fbshipit-source-id: b7c03ec35ea1994e2441da2889a44466e9e2aa0f
This commit is contained in:
parent
ce2ee5a19c
commit
0520fb254b
|
@ -14,13 +14,10 @@ const DeltaPatcher = require('../DeltaPatcher');
|
||||||
const RamBundle = require('./RamBundle');
|
const RamBundle = require('./RamBundle');
|
||||||
|
|
||||||
const stableHash = require('metro-cache/src/stableHash');
|
const stableHash = require('metro-cache/src/stableHash');
|
||||||
const toLocalPath = require('../../node-haste/lib/toLocalPath');
|
|
||||||
|
|
||||||
const {getAssetData} = require('../../Assets');
|
|
||||||
const {createRamBundleGroups} = require('../../Bundler/util');
|
const {createRamBundleGroups} = require('../../Bundler/util');
|
||||||
const {fromRawMappings} = require('metro-source-map');
|
const {fromRawMappings} = require('metro-source-map');
|
||||||
|
|
||||||
import type {AssetData} from '../../Assets';
|
|
||||||
import type {GetTransformOptions} from '../../Bundler';
|
import type {GetTransformOptions} from '../../Bundler';
|
||||||
import type {BundleOptions, ModuleTransportLike} from '../../shared/types.flow';
|
import type {BundleOptions, ModuleTransportLike} from '../../shared/types.flow';
|
||||||
import type DeltaBundler from '../';
|
import type DeltaBundler from '../';
|
||||||
|
@ -241,32 +238,6 @@ async function getRamBundleInfo(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAssets(
|
|
||||||
deltaBundler: DeltaBundler,
|
|
||||||
options: BundleOptions,
|
|
||||||
projectRoots: $ReadOnlyArray<string>,
|
|
||||||
): Promise<$ReadOnlyArray<AssetData>> {
|
|
||||||
const {modules} = await _getAllModules(deltaBundler, options);
|
|
||||||
|
|
||||||
const assets = await Promise.all(
|
|
||||||
modules.map(async module => {
|
|
||||||
if (module.type === 'asset') {
|
|
||||||
const localPath = toLocalPath(projectRoots, module.path);
|
|
||||||
|
|
||||||
return getAssetData(
|
|
||||||
module.path,
|
|
||||||
localPath,
|
|
||||||
options.assetPlugins,
|
|
||||||
options.platform,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
return assets.filter(Boolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _build(
|
async function _build(
|
||||||
deltaBundler: DeltaBundler,
|
deltaBundler: DeltaBundler,
|
||||||
clientId: string,
|
clientId: string,
|
||||||
|
@ -294,6 +265,5 @@ module.exports = {
|
||||||
fullSourceMap,
|
fullSourceMap,
|
||||||
fullSourceMapObject,
|
fullSourceMapObject,
|
||||||
getAllModules,
|
getAllModules,
|
||||||
getAssets,
|
|
||||||
getRamBundleInfo,
|
getRamBundleInfo,
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
jest.mock('../../../node-haste/lib/toLocalPath');
|
jest.mock('../../../node-haste/lib/toLocalPath');
|
||||||
jest.mock('../../../Assets');
|
jest.mock('../../../Assets');
|
||||||
|
|
||||||
const {getAssetData} = require('../../../Assets');
|
|
||||||
const toLocalPath = require('../../../node-haste/lib/toLocalPath');
|
const toLocalPath = require('../../../node-haste/lib/toLocalPath');
|
||||||
|
|
||||||
const CURRENT_TIME = 1482363367000;
|
const CURRENT_TIME = 1482363367000;
|
||||||
|
@ -61,14 +60,6 @@ describe('Serializers', () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
getAssetData.mockImplementation(
|
|
||||||
(path, localPath, assetDataPlugins, platform) => ({
|
|
||||||
path,
|
|
||||||
platform,
|
|
||||||
assetData: true,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
toLocalPath.mockImplementation((roots, path) => path.replace(roots[0], ''));
|
toLocalPath.mockImplementation((roots, path) => path.replace(roots[0], ''));
|
||||||
|
|
||||||
setCurrentTime(CURRENT_TIME);
|
setCurrentTime(CURRENT_TIME);
|
||||||
|
@ -235,35 +226,6 @@ describe('Serializers', () => {
|
||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the bundle assets', async () => {
|
|
||||||
expect(await Serializers.getAllModules(deltaBundler, {})).toMatchSnapshot();
|
|
||||||
|
|
||||||
getDelta.mockReturnValueOnce(
|
|
||||||
Promise.resolve({
|
|
||||||
delta: new Map([
|
|
||||||
[3, {code: 'modified module;'}],
|
|
||||||
[7, {code: 'code', type: 'asset', path: '/foo/path.png'}],
|
|
||||||
[8, {code: 'code', type: 'module', path: '/foo/path2.png'}],
|
|
||||||
[9, {code: 'code', type: 'asset', path: '/foo/path3.png'}],
|
|
||||||
]),
|
|
||||||
pre: new Map([[5, {code: 'more pre;'}]]),
|
|
||||||
post: new Map([[6, {code: 'bananas;'}]]),
|
|
||||||
inverseDependencies: [],
|
|
||||||
reset: true,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
await Serializers.getAssets(
|
|
||||||
deltaBundler,
|
|
||||||
{
|
|
||||||
platform: 'ios',
|
|
||||||
},
|
|
||||||
['/foo'],
|
|
||||||
),
|
|
||||||
).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should post-process the modules', async () => {
|
it('should post-process the modules', async () => {
|
||||||
postProcessModules.mockImplementation(modules => {
|
postProcessModules.mockImplementation(modules => {
|
||||||
return modules.sort(
|
return modules.sort(
|
||||||
|
|
|
@ -345,50 +345,6 @@ Object {
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Serializers should return the bundle assets 1`] = `
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"code": "pre;",
|
|
||||||
"id": 1,
|
|
||||||
"path": "/pre.js",
|
|
||||||
"type": "script",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"code": "module3;",
|
|
||||||
"id": 3,
|
|
||||||
"path": "/3.js",
|
|
||||||
"type": "module",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"code": "another;",
|
|
||||||
"id": 4,
|
|
||||||
"path": "/4.js",
|
|
||||||
"type": "module",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"code": "post;",
|
|
||||||
"id": 2,
|
|
||||||
"path": "/p",
|
|
||||||
"type": "require",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`Serializers should return the bundle assets 2`] = `
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"assetData": true,
|
|
||||||
"path": "/foo/path.png",
|
|
||||||
"platform": "ios",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"assetData": true,
|
|
||||||
"path": "/foo/path3.png",
|
|
||||||
"platform": "ios",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`Serializers should return the stringified delta bundle 1`] = `
|
exports[`Serializers should return the stringified delta bundle 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"bundle": "{\\"id\\":\\"1234\\",\\"pre\\":[[1,\\"pre;\\"]],\\"post\\":[[2,\\"post;\\"]],\\"delta\\":[[3,\\"module3;\\"],[4,\\"another;\\"]],\\"reset\\":true}",
|
"bundle": "{\\"id\\":\\"1234\\",\\"pre\\":[[1,\\"pre;\\"]],\\"post\\":[[2,\\"post;\\"]],\\"delta\\":[[3,\\"module3;\\"],[4,\\"another;\\"]],\\"reset\\":true}",
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @emails oncall+javascript_foundation
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
jest.mock('../../../Assets');
|
||||||
|
|
||||||
|
const getAssets = require('../getAssets');
|
||||||
|
|
||||||
|
const {getAssetData} = require('../../../Assets');
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
getAssetData.mockImplementation(async (path, localPath) => ({
|
||||||
|
path,
|
||||||
|
localPath,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the bundle assets', async () => {
|
||||||
|
const graph = {
|
||||||
|
dependencies: new Map([
|
||||||
|
['/tmp/1.js', {path: '/tmp/1.js', output: {type: 'module'}}],
|
||||||
|
['/tmp/2.js', {path: '/tmp/2.js', output: {type: 'module'}}],
|
||||||
|
['/tmp/3.png', {path: '/tmp/3.png', output: {type: 'asset'}}],
|
||||||
|
['/tmp/4.js', {path: '/tmp/2.js', output: {type: 'module'}}],
|
||||||
|
['/tmp/5.mov', {path: '/tmp/5.mov', output: {type: 'asset'}}],
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(await getAssets(graph, {projectRoots: ['/tmp']})).toEqual([
|
||||||
|
{path: '/tmp/3.png', localPath: '3.png'},
|
||||||
|
{path: '/tmp/5.mov', localPath: '5.mov'},
|
||||||
|
]);
|
||||||
|
});
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const toLocalPath = require('../../node-haste/lib/toLocalPath');
|
||||||
|
|
||||||
|
const {getAssetData} = require('../../Assets');
|
||||||
|
|
||||||
|
import type {AssetData} from '../../Assets';
|
||||||
|
import type {Graph} from '../DeltaCalculator';
|
||||||
|
|
||||||
|
type Options = {|
|
||||||
|
assetPlugins: $ReadOnlyArray<string>,
|
||||||
|
platform: ?string,
|
||||||
|
projectRoots: $ReadOnlyArray<string>,
|
||||||
|
|};
|
||||||
|
|
||||||
|
async function getAssets(
|
||||||
|
graph: Graph,
|
||||||
|
options: Options,
|
||||||
|
): Promise<$ReadOnlyArray<AssetData>> {
|
||||||
|
const assets = await Promise.all(
|
||||||
|
Array.from(graph.dependencies.values()).map(async module => {
|
||||||
|
if (module.output.type === 'asset') {
|
||||||
|
return getAssetData(
|
||||||
|
module.path,
|
||||||
|
toLocalPath(options.projectRoots, module.path),
|
||||||
|
options.assetPlugins,
|
||||||
|
options.platform,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return assets.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = getAssets;
|
|
@ -16,6 +16,7 @@ const MultipartResponse = require('./MultipartResponse');
|
||||||
const Serializers = require('../DeltaBundler/Serializers/Serializers');
|
const Serializers = require('../DeltaBundler/Serializers/Serializers');
|
||||||
|
|
||||||
const defaultCreateModuleIdFactory = require('../lib/createModuleIdFactory');
|
const defaultCreateModuleIdFactory = require('../lib/createModuleIdFactory');
|
||||||
|
const getAssets = require('../DeltaBundler/Serializers/getAssets');
|
||||||
const plainJSBundle = require('../DeltaBundler/Serializers/plainJSBundle');
|
const plainJSBundle = require('../DeltaBundler/Serializers/plainJSBundle');
|
||||||
const sourceMapString = require('../DeltaBundler/Serializers/sourceMapString');
|
const sourceMapString = require('../DeltaBundler/Serializers/sourceMapString');
|
||||||
const debug = require('debug')('Metro:Server');
|
const debug = require('debug')('Metro:Server');
|
||||||
|
@ -52,6 +53,7 @@ import type {
|
||||||
PostProcessBundleSourcemap,
|
PostProcessBundleSourcemap,
|
||||||
} from '../Bundler';
|
} from '../Bundler';
|
||||||
import type {CacheStore} from 'metro-cache';
|
import type {CacheStore} from 'metro-cache';
|
||||||
|
import type {Graph} from '../DeltaBundler';
|
||||||
import type {MetroSourceMap} from 'metro-source-map';
|
import type {MetroSourceMap} from 'metro-source-map';
|
||||||
import type {TransformCache} from '../lib/TransformCaching';
|
import type {TransformCache} from '../lib/TransformCaching';
|
||||||
import type {Symbolicate} from './symbolicate/symbolicate';
|
import type {Symbolicate} from './symbolicate/symbolicate';
|
||||||
|
@ -64,6 +66,11 @@ const {
|
||||||
|
|
||||||
type ResolveSync = (path: string, opts: ?{baseDir?: string}) => string;
|
type ResolveSync = (path: string, opts: ?{baseDir?: string}) => string;
|
||||||
|
|
||||||
|
type GraphInfo = {|
|
||||||
|
graph: Graph,
|
||||||
|
prepend: $ReadOnlyArray<DependencyEdge>,
|
||||||
|
|};
|
||||||
|
|
||||||
function debounceAndBatch(fn, delay) {
|
function debounceAndBatch(fn, delay) {
|
||||||
let timeout;
|
let timeout;
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -243,49 +250,22 @@ class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
async build(options: BundleOptions): Promise<{code: string, map: string}> {
|
async build(options: BundleOptions): Promise<{code: string, map: string}> {
|
||||||
|
const {prepend, graph} = await this._buildGraph(options);
|
||||||
|
|
||||||
const entryPoint = getAbsolutePath(
|
const entryPoint = getAbsolutePath(
|
||||||
options.entryFile,
|
options.entryFile,
|
||||||
this._opts.projectRoots,
|
this._opts.projectRoots,
|
||||||
);
|
);
|
||||||
|
|
||||||
const crawlingOptions = {
|
|
||||||
assetPlugins: options.assetPlugins,
|
|
||||||
customTransformOptions: options.customTransformOptions,
|
|
||||||
dev: options.dev,
|
|
||||||
entryPoints: [entryPoint],
|
|
||||||
hot: options.hot,
|
|
||||||
minify: options.minify,
|
|
||||||
onProgress: options.onProgress,
|
|
||||||
platform: options.platform,
|
|
||||||
type: 'module',
|
|
||||||
};
|
|
||||||
|
|
||||||
let graph = await this._deltaBundler.buildGraph(crawlingOptions);
|
|
||||||
let prependScripts = await getPrependedScripts(
|
|
||||||
this._opts,
|
|
||||||
crawlingOptions,
|
|
||||||
this._deltaBundler,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (options.minify) {
|
|
||||||
prependScripts = await Promise.all(
|
|
||||||
prependScripts.map(script => this._minifyModule(script)),
|
|
||||||
);
|
|
||||||
|
|
||||||
graph = await mapGraph(graph, module => this._minifyModule(module));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: plainJSBundle(entryPoint, prependScripts, graph, {
|
code: plainJSBundle(entryPoint, prepend, graph, {
|
||||||
createModuleId: this._opts.createModuleId,
|
createModuleId: this._opts.createModuleId,
|
||||||
dev: options.dev,
|
dev: options.dev,
|
||||||
runBeforeMainModule: this._opts.getModulesRunBeforeMainModule(
|
runBeforeMainModule: options.runBeforeMainModule,
|
||||||
options.entryFile,
|
|
||||||
),
|
|
||||||
runModule: options.runModule,
|
runModule: options.runModule,
|
||||||
sourceMapUrl: options.sourceMapUrl,
|
sourceMapUrl: options.sourceMapUrl,
|
||||||
}),
|
}),
|
||||||
map: sourceMapString(prependScripts, graph, {
|
map: sourceMapString(prepend, graph, {
|
||||||
excludeSource: options.excludeSource,
|
excludeSource: options.excludeSource,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -303,14 +283,16 @@ class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAssets(options: BundleOptions): Promise<$ReadOnlyArray<AssetData>> {
|
async getAssets(options: BundleOptions): Promise<$ReadOnlyArray<AssetData>> {
|
||||||
return await Serializers.getAssets(
|
const {graph} = await this._buildGraph({
|
||||||
this._deltaBundler,
|
...options,
|
||||||
{
|
minify: false, // minification does not affect the assets.
|
||||||
...options,
|
});
|
||||||
entryFile: getAbsolutePath(options.entryFile, this._opts.projectRoots),
|
|
||||||
},
|
return await getAssets(graph, {
|
||||||
this._opts.projectRoots,
|
assetPlugins: options.assetPlugins,
|
||||||
);
|
platform: options.platform,
|
||||||
|
projectRoots: this._opts.projectRoots,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOrderedDependencyPaths(options: {
|
async getOrderedDependencyPaths(options: {
|
||||||
|
@ -336,6 +318,45 @@ class Server {
|
||||||
return await getOrderedDependencyPaths(this._deltaBundler, bundleOptions);
|
return await getOrderedDependencyPaths(this._deltaBundler, bundleOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _buildGraph(options: BundleOptions): Promise<GraphInfo> {
|
||||||
|
const entryPoint = getAbsolutePath(
|
||||||
|
options.entryFile,
|
||||||
|
this._opts.projectRoots,
|
||||||
|
);
|
||||||
|
|
||||||
|
const crawlingOptions = {
|
||||||
|
assetPlugins: options.assetPlugins,
|
||||||
|
customTransformOptions: options.customTransformOptions,
|
||||||
|
dev: options.dev,
|
||||||
|
entryPoints: [entryPoint],
|
||||||
|
hot: options.hot,
|
||||||
|
minify: options.minify,
|
||||||
|
onProgress: options.onProgress,
|
||||||
|
platform: options.platform,
|
||||||
|
type: 'module',
|
||||||
|
};
|
||||||
|
|
||||||
|
let graph = await this._deltaBundler.buildGraph(crawlingOptions);
|
||||||
|
let prepend = await getPrependedScripts(
|
||||||
|
this._opts,
|
||||||
|
crawlingOptions,
|
||||||
|
this._deltaBundler,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (options.minify) {
|
||||||
|
prepend = await Promise.all(
|
||||||
|
prepend.map(script => this._minifyModule(script)),
|
||||||
|
);
|
||||||
|
|
||||||
|
graph = await mapGraph(graph, module => this._minifyModule(module));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
prepend,
|
||||||
|
graph,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async _minifyModule(module: DependencyEdge): Promise<DependencyEdge> {
|
async _minifyModule(module: DependencyEdge): Promise<DependencyEdge> {
|
||||||
const {code, map} = await this._bundler.minifyModule(
|
const {code, map} = await this._bundler.minifyModule(
|
||||||
module.path,
|
module.path,
|
||||||
|
|
Loading…
Reference in New Issue