mirror of https://github.com/status-im/metro.git
Refactor production serializers to use directly the graph information
Reviewed By: mjesun Differential Revision: D7158632 fbshipit-source-id: 91fad2e3ca617ea5f3b283e335c0d70edbb6ff3b
This commit is contained in:
parent
3ac0bb47d9
commit
6be6b0805d
|
@ -34,7 +34,7 @@ function withSourceMap(
|
|||
|
||||
function minify(inputCode: string, inputMap: ?BabelSourceMap) {
|
||||
const result = uglify.minify(inputCode, {
|
||||
mangle: {toplevel: true},
|
||||
mangle: {toplevel: false},
|
||||
output: {
|
||||
ascii_only: true,
|
||||
quote_style: 3,
|
||||
|
@ -44,7 +44,7 @@ function minify(inputCode: string, inputMap: ?BabelSourceMap) {
|
|||
content: inputMap,
|
||||
includeSources: false,
|
||||
},
|
||||
toplevel: true,
|
||||
toplevel: false,
|
||||
compress: {
|
||||
// reduce_funcs inlines single-use function, which cause perf regressions.
|
||||
reduce_funcs: false,
|
||||
|
|
|
@ -444,7 +444,7 @@ class DeltaTransformer extends EventEmitter {
|
|||
const name = this._dependencyGraph.getHasteName(edge.path);
|
||||
|
||||
const wrappedCode = wrapModule(edge, {
|
||||
createModuleIdFn: this._getModuleId,
|
||||
createModuleId: this._getModuleId,
|
||||
dev: transformOptions.dev,
|
||||
});
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ it('should serialize a very simple bundle', () => {
|
|||
entryPoints: ['foo'],
|
||||
},
|
||||
{
|
||||
createModuleIdFn: path => path,
|
||||
createModuleId: path => path,
|
||||
dev: true,
|
||||
runBeforeMainModule: [],
|
||||
runModule: true,
|
||||
|
@ -70,7 +70,7 @@ it('should add runBeforeMainModule statements if found in the graph', () => {
|
|||
entryPoints: ['foo'],
|
||||
},
|
||||
{
|
||||
createModuleIdFn: path => path,
|
||||
createModuleId: path => path,
|
||||
dev: true,
|
||||
runBeforeMainModule: ['bar', 'non-existant'],
|
||||
runModule: true,
|
||||
|
@ -99,7 +99,7 @@ it('should handle numeric module ids', () => {
|
|||
entryPoints: ['foo'],
|
||||
},
|
||||
{
|
||||
createModuleIdFn: createModuleIdFactory(),
|
||||
createModuleId: createModuleIdFactory(),
|
||||
dev: true,
|
||||
runBeforeMainModule: ['bar', 'non-existant'],
|
||||
runModule: true,
|
||||
|
|
|
@ -35,7 +35,7 @@ describe('wrapModule()', () => {
|
|||
it('Should wrap a module in nondev mode', () => {
|
||||
expect(
|
||||
wrapModule(myModule, {
|
||||
createModuleIdFn: createModuleIdFactory(),
|
||||
createModuleId: createModuleIdFactory(),
|
||||
dev: false,
|
||||
}),
|
||||
).toEqual('__d(function() { console.log("foo") },0,[1,2]);');
|
||||
|
@ -44,7 +44,7 @@ describe('wrapModule()', () => {
|
|||
it('Should wrap a module in dev mode', () => {
|
||||
expect(
|
||||
wrapModule(myModule, {
|
||||
createModuleIdFn: createModuleIdFactory(),
|
||||
createModuleId: createModuleIdFactory(),
|
||||
dev: true,
|
||||
}),
|
||||
).toEqual('__d(function() { console.log("foo") },0,[1,2],"foo.js");');
|
||||
|
@ -55,17 +55,17 @@ describe('wrapModule()', () => {
|
|||
|
||||
expect(
|
||||
wrapModule(myModule, {
|
||||
createModuleIdFn: createModuleIdFactory(),
|
||||
createModuleId: createModuleIdFactory(),
|
||||
dev: true,
|
||||
}),
|
||||
).toEqual(myModule.output.code);
|
||||
});
|
||||
|
||||
it('should use custom createModuleIdFn param', () => {
|
||||
// Just use a createModuleIdFn that returns the same path.
|
||||
it('should use custom createModuleId param', () => {
|
||||
// Just use a createModuleId that returns the same path.
|
||||
expect(
|
||||
wrapModule(myModule, {
|
||||
createModuleIdFn: path => path,
|
||||
createModuleId: path => path,
|
||||
dev: false,
|
||||
}),
|
||||
).toEqual(
|
||||
|
|
|
@ -16,7 +16,7 @@ const path = require('path');
|
|||
import type {DependencyEdge} from '../../traverseDependencies';
|
||||
|
||||
export type Options = {
|
||||
+createModuleIdFn: string => number | string,
|
||||
+createModuleId: string => number | string,
|
||||
+dev: boolean,
|
||||
};
|
||||
|
||||
|
@ -25,10 +25,10 @@ function wrapModule(module: DependencyEdge, options: Options) {
|
|||
return module.output.code;
|
||||
}
|
||||
|
||||
const moduleId = options.createModuleIdFn(module.path);
|
||||
const moduleId = options.createModuleId(module.path);
|
||||
const params = [
|
||||
moduleId,
|
||||
Array.from(module.dependencies.values()).map(options.createModuleIdFn),
|
||||
Array.from(module.dependencies.values()).map(options.createModuleId),
|
||||
];
|
||||
|
||||
// Add the module name as the last parameter (to make it easier to do
|
||||
|
|
|
@ -10,13 +10,15 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const getAppendScripts = require('../../lib/getAppendScripts');
|
||||
|
||||
const {wrapModule} = require('./helpers/js');
|
||||
|
||||
import type {Graph} from '../DeltaCalculator';
|
||||
import type {DependencyEdge} from '../traverseDependencies';
|
||||
|
||||
type Options = {|
|
||||
createModuleIdFn: string => number | string,
|
||||
createModuleId: string => number | string,
|
||||
+dev: boolean,
|
||||
+runBeforeMainModule: $ReadOnlyArray<string>,
|
||||
+runModule: boolean,
|
||||
|
@ -29,35 +31,17 @@ function plainJSBundle(
|
|||
graph: Graph,
|
||||
options: Options,
|
||||
): string {
|
||||
const output = [];
|
||||
|
||||
for (const module of pre) {
|
||||
output.push(wrapModule(module, options));
|
||||
}
|
||||
|
||||
for (const module of graph.dependencies.values()) {
|
||||
output.push(wrapModule(module, options));
|
||||
options.createModuleId(module.path);
|
||||
}
|
||||
|
||||
for (const path of options.runBeforeMainModule) {
|
||||
if (graph.dependencies.has(path)) {
|
||||
output.push(
|
||||
`require(${JSON.stringify(options.createModuleIdFn(path))});`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.runModule && graph.dependencies.has(entryPoint)) {
|
||||
output.push(
|
||||
`require(${JSON.stringify(options.createModuleIdFn(entryPoint))});`,
|
||||
);
|
||||
}
|
||||
|
||||
if (options.sourceMapUrl) {
|
||||
output.push(`//# sourceMappingURL=${options.sourceMapUrl}`);
|
||||
}
|
||||
|
||||
return output.join('\n');
|
||||
return [
|
||||
...pre,
|
||||
...graph.dependencies.values(),
|
||||
...getAppendScripts(entryPoint, graph, options),
|
||||
]
|
||||
.map(module => wrapModule(module, options))
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
module.exports = plainJSBundle;
|
||||
|
|
|
@ -10,10 +10,16 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const DeltaCalculator = require('./DeltaCalculator');
|
||||
const DeltaTransformer = require('./DeltaTransformer');
|
||||
|
||||
import type Bundler from '../Bundler';
|
||||
import type {BundleOptions} from '../shared/types.flow';
|
||||
import type {
|
||||
DeltaResult,
|
||||
Graph as CalculatorGraph,
|
||||
Options,
|
||||
} from './DeltaCalculator';
|
||||
import type {DeltaEntry} from './DeltaTransformer';
|
||||
|
||||
export type PostProcessModules = (
|
||||
|
@ -27,6 +33,9 @@ export type MainOptions = {|
|
|||
postProcessModules?: PostProcessModules,
|
||||
|};
|
||||
|
||||
export type Delta = DeltaResult;
|
||||
export type Graph = CalculatorGraph;
|
||||
|
||||
/**
|
||||
* `DeltaBundler` uses the `DeltaTransformer` to build bundle deltas. This
|
||||
* module handles all the transformer instances so it can support multiple
|
||||
|
@ -38,6 +47,7 @@ class DeltaBundler {
|
|||
_options: MainOptions;
|
||||
_deltaTransformers: Map<string, DeltaTransformer> = new Map();
|
||||
_currentId: number = 0;
|
||||
_deltaCalculators: Map<Graph, DeltaCalculator> = new Map();
|
||||
|
||||
constructor(bundler: Bundler, options: MainOptions) {
|
||||
this._bundler = bundler;
|
||||
|
@ -47,6 +57,9 @@ class DeltaBundler {
|
|||
end() {
|
||||
this._deltaTransformers.forEach(DeltaTransformer => DeltaTransformer.end());
|
||||
this._deltaTransformers = new Map();
|
||||
|
||||
this._deltaCalculators.forEach(deltaCalculator => deltaCalculator.end());
|
||||
this._deltaCalculators = new Map();
|
||||
}
|
||||
|
||||
endTransformer(clientId: string) {
|
||||
|
@ -78,6 +91,55 @@ class DeltaBundler {
|
|||
return deltaTransformer;
|
||||
}
|
||||
|
||||
async buildGraph(options: Options): Promise<Graph> {
|
||||
const depGraph = await this._bundler.getDependencyGraph();
|
||||
|
||||
const deltaCalculator = new DeltaCalculator(
|
||||
this._bundler,
|
||||
depGraph,
|
||||
options,
|
||||
);
|
||||
|
||||
await deltaCalculator.getDelta({reset: true});
|
||||
const graph = deltaCalculator.getGraph();
|
||||
|
||||
this._deltaCalculators.set(graph, deltaCalculator);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
async getDelta(graph: Graph, {reset}: {reset: boolean}): Promise<Delta> {
|
||||
const deltaCalculator = this._deltaCalculators.get(graph);
|
||||
|
||||
if (!deltaCalculator) {
|
||||
throw new Error('Graph not found');
|
||||
}
|
||||
|
||||
return await deltaCalculator.getDelta({reset});
|
||||
}
|
||||
|
||||
listen(graph: Graph, callback: () => mixed) {
|
||||
const deltaCalculator = this._deltaCalculators.get(graph);
|
||||
|
||||
if (!deltaCalculator) {
|
||||
throw new Error('Graph not found');
|
||||
}
|
||||
|
||||
deltaCalculator.on('change', callback);
|
||||
}
|
||||
|
||||
endGraph(graph: Graph) {
|
||||
const deltaCalculator = this._deltaCalculators.get(graph);
|
||||
|
||||
if (!deltaCalculator) {
|
||||
throw new Error('Graph not found');
|
||||
}
|
||||
|
||||
deltaCalculator.end();
|
||||
|
||||
this._deltaCalculators.delete(graph);
|
||||
}
|
||||
|
||||
getPostProcessModulesFn(
|
||||
entryPoint: string,
|
||||
): (modules: $ReadOnlyArray<DeltaEntry>) => $ReadOnlyArray<DeltaEntry> {
|
||||
|
|
|
@ -19,6 +19,7 @@ jest
|
|||
}))
|
||||
.mock('../../Bundler')
|
||||
.mock('../../Assets')
|
||||
.mock('../../lib/getPrependedScripts')
|
||||
.mock('../../node-haste/DependencyGraph')
|
||||
.mock('metro-core/src/Logger')
|
||||
.mock('../../lib/getAbsolutePath')
|
||||
|
@ -29,6 +30,7 @@ describe('processRequest', () => {
|
|||
let Bundler;
|
||||
let Server;
|
||||
let getAsset;
|
||||
let getPrependedScripts;
|
||||
let symbolicate;
|
||||
let Serializers;
|
||||
let DeltaBundler;
|
||||
|
@ -40,6 +42,7 @@ describe('processRequest', () => {
|
|||
Bundler = require('../../Bundler');
|
||||
Server = require('../');
|
||||
getAsset = require('../../Assets').getAsset;
|
||||
getPrependedScripts = require('../../lib/getPrependedScripts');
|
||||
symbolicate = require('../symbolicate/symbolicate');
|
||||
Serializers = require('../../DeltaBundler/Serializers/Serializers');
|
||||
DeltaBundler = require('../../DeltaBundler');
|
||||
|
@ -85,6 +88,15 @@ describe('processRequest', () => {
|
|||
let requestHandler;
|
||||
|
||||
beforeEach(() => {
|
||||
DeltaBundler.prototype.buildGraph = jest.fn().mockReturnValue(
|
||||
Promise.resolve({
|
||||
entryPoints: [''],
|
||||
dependencies: new Map(),
|
||||
}),
|
||||
);
|
||||
|
||||
getPrependedScripts.mockReturnValue(Promise.resolve([]));
|
||||
|
||||
Serializers.fullBundle.mockReturnValue(
|
||||
Promise.resolve({
|
||||
bundle: 'this is the source',
|
||||
|
@ -445,28 +457,16 @@ describe('processRequest', () => {
|
|||
entryFile: 'foo file',
|
||||
})
|
||||
.then(() =>
|
||||
expect(Serializers.fullBundle).toBeCalledWith(
|
||||
expect.any(DeltaBundler),
|
||||
{
|
||||
expect(DeltaBundler.prototype.buildGraph).toBeCalledWith({
|
||||
assetPlugins: [],
|
||||
customTransformOptions: {},
|
||||
dev: true,
|
||||
entryFile: '/root/foo file',
|
||||
entryModuleOnly: false,
|
||||
excludeSource: false,
|
||||
entryPoints: ['/root/foo file'],
|
||||
hot: false,
|
||||
inlineSourceMap: false,
|
||||
isolateModuleIDs: false,
|
||||
minify: false,
|
||||
onProgress: null,
|
||||
platform: undefined,
|
||||
resolutionResponse: null,
|
||||
runBeforeMainModule: ['InitializeCore'],
|
||||
runModule: true,
|
||||
sourceMapUrl: null,
|
||||
unbundle: false,
|
||||
},
|
||||
),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,13 +14,19 @@ const Bundler = require('../Bundler');
|
|||
const DeltaBundler = require('../DeltaBundler');
|
||||
const MultipartResponse = require('./MultipartResponse');
|
||||
const Serializers = require('../DeltaBundler/Serializers/Serializers');
|
||||
|
||||
const defaultCreateModuleIdFactory = require('../lib/createModuleIdFactory');
|
||||
const plainJSBundle = require('../DeltaBundler/Serializers/plainJSBundle');
|
||||
const sourceMapString = require('../DeltaBundler/Serializers/sourceMapString');
|
||||
const debug = require('debug')('Metro:Server');
|
||||
const defaults = require('../defaults');
|
||||
const formatBundlingError = require('../lib/formatBundlingError');
|
||||
const getAbsolutePath = require('../lib/getAbsolutePath');
|
||||
const getMaxWorkers = require('../lib/getMaxWorkers');
|
||||
const getOrderedDependencyPaths = require('../lib/getOrderedDependencyPaths');
|
||||
const getPrependedScripts = require('../lib/getPrependedScripts');
|
||||
const mime = require('mime-types');
|
||||
const mapGraph = require('../lib/mapGraph');
|
||||
const nullthrows = require('fbjs/lib/nullthrows');
|
||||
const parseCustomTransformOptions = require('../lib/parseCustomTransformOptions');
|
||||
const parsePlatformFilePath = require('../node-haste/lib/parsePlatformFilePath');
|
||||
|
@ -32,6 +38,7 @@ const {getAsset} = require('../Assets');
|
|||
const resolveSync: ResolveSync = require('resolve').sync;
|
||||
|
||||
import type {CustomError} from '../lib/formatBundlingError';
|
||||
import type {DependencyEdge} from '../DeltaBundler/traverseDependencies';
|
||||
import type {IncomingMessage, ServerResponse} from 'http';
|
||||
import type {Reporter} from '../lib/reporting';
|
||||
import type {
|
||||
|
@ -73,7 +80,7 @@ class Server {
|
|||
blacklistRE: void | RegExp,
|
||||
cacheStores: $ReadOnlyArray<CacheStore<TransformedCode>>,
|
||||
cacheVersion: string,
|
||||
createModuleIdFactory?: () => (path: string) => number,
|
||||
createModuleId: (path: string) => number,
|
||||
enableBabelRCLookup: boolean,
|
||||
extraNodeModules: {},
|
||||
getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>,
|
||||
|
@ -119,6 +126,9 @@ class Server {
|
|||
const assetExts = options.assetExts || defaults.assetExts;
|
||||
const sourceExts = options.sourceExts || defaults.sourceExts;
|
||||
|
||||
const _createModuleId =
|
||||
options.createModuleId || defaultCreateModuleIdFactory();
|
||||
|
||||
this._opts = {
|
||||
assetExts: options.assetTransforms ? [] : assetExts,
|
||||
assetRegistryPath: options.assetRegistryPath,
|
||||
|
@ -126,7 +136,7 @@ class Server {
|
|||
cacheStores: options.cacheStores,
|
||||
cacheVersion: options.cacheVersion,
|
||||
dynamicDepsInPackages: options.dynamicDepsInPackages || 'throwAtRuntime',
|
||||
createModuleIdFactory: options.createModuleIdFactory,
|
||||
createModuleId: _createModuleId,
|
||||
enableBabelRCLookup:
|
||||
options.enableBabelRCLookup != null
|
||||
? options.enableBabelRCLookup
|
||||
|
@ -175,7 +185,7 @@ class Server {
|
|||
// This slices out options that are not part of the strict BundlerOptions
|
||||
/* eslint-disable no-unused-vars */
|
||||
const {
|
||||
createModuleIdFactory,
|
||||
createModuleId,
|
||||
getModulesRunBeforeMainModule,
|
||||
moduleFormat,
|
||||
silent,
|
||||
|
@ -230,27 +240,48 @@ class Server {
|
|||
}
|
||||
|
||||
async build(options: BundleOptions): Promise<{code: string, map: string}> {
|
||||
options = {
|
||||
...options,
|
||||
const entryPoint = getAbsolutePath(
|
||||
options.entryFile,
|
||||
this._opts.projectRoots,
|
||||
);
|
||||
|
||||
let graph = await this._deltaBundler.buildGraph({
|
||||
assetPlugins: options.assetPlugins,
|
||||
customTransformOptions: options.customTransformOptions,
|
||||
dev: options.dev,
|
||||
entryPoints: [entryPoint],
|
||||
hot: options.hot,
|
||||
minify: options.minify,
|
||||
onProgress: options.onProgress,
|
||||
platform: options.platform,
|
||||
});
|
||||
let prependScripts = await getPrependedScripts(
|
||||
this._opts,
|
||||
options,
|
||||
this._bundler,
|
||||
);
|
||||
|
||||
if (options.minify) {
|
||||
prependScripts = await Promise.all(
|
||||
prependScripts.map(script => this._minifyModule(script)),
|
||||
);
|
||||
|
||||
graph = await mapGraph(graph, module => this._minifyModule(module));
|
||||
}
|
||||
|
||||
return {
|
||||
code: plainJSBundle(entryPoint, prependScripts, graph, {
|
||||
createModuleId: this._opts.createModuleId,
|
||||
dev: options.dev,
|
||||
runBeforeMainModule: this._opts.getModulesRunBeforeMainModule(
|
||||
options.entryFile,
|
||||
),
|
||||
entryFile: getAbsolutePath(options.entryFile, this._opts.projectRoots),
|
||||
};
|
||||
|
||||
const fullBundle = await Serializers.fullBundle(
|
||||
this._deltaBundler,
|
||||
options,
|
||||
);
|
||||
|
||||
const fullMap = await Serializers.fullSourceMap(
|
||||
this._deltaBundler,
|
||||
options,
|
||||
);
|
||||
|
||||
return {
|
||||
code: fullBundle.bundle,
|
||||
map: fullMap,
|
||||
runModule: options.runModule,
|
||||
sourceMapUrl: options.sourceMapUrl,
|
||||
}),
|
||||
map: sourceMapString(prependScripts, graph, {
|
||||
excludeSource: options.excludeSource,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -299,6 +330,24 @@ class Server {
|
|||
return await getOrderedDependencyPaths(this._deltaBundler, bundleOptions);
|
||||
}
|
||||
|
||||
async _minifyModule(module: DependencyEdge): Promise<DependencyEdge> {
|
||||
const {code, map} = await this._bundler.minifyModule(
|
||||
module.path,
|
||||
module.output.code,
|
||||
module.output.map,
|
||||
);
|
||||
|
||||
// $FlowIssue #16581373 spread of an exact object should be exact
|
||||
return {
|
||||
...module,
|
||||
output: {
|
||||
...module.output,
|
||||
code,
|
||||
map,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
onFileChange(type: string, filePath: string) {
|
||||
Promise.all(
|
||||
this._fileChangeListeners.map(listener => listener(filePath)),
|
||||
|
|
|
@ -149,7 +149,7 @@ __d(function (global, _require, module, exports, _dependencyMap) {
|
|||
Foo: Foo,
|
||||
Bar: Bar
|
||||
};
|
||||
},4,[5,6]);
|
||||
},0,[1,2]);
|
||||
__d(function (global, _require, module, exports, _dependencyMap) {
|
||||
'use strict';
|
||||
|
||||
|
@ -159,7 +159,7 @@ __d(function (global, _require, module, exports, _dependencyMap) {
|
|||
type: 'bar',
|
||||
foo: Foo.type
|
||||
};
|
||||
},5,[6]);
|
||||
},1,[2]);
|
||||
__d(function (global, _require, module, exports, _dependencyMap) {
|
||||
'use strict';
|
||||
|
||||
|
@ -169,7 +169,7 @@ __d(function (global, _require, module, exports, _dependencyMap) {
|
|||
type: 'foo',
|
||||
asset: asset
|
||||
};
|
||||
},6,[7]);
|
||||
},2,[3]);
|
||||
__d(function (global, _require, module, exports, _dependencyMap) {
|
||||
module.exports = _require(_dependencyMap[0]).registerAsset({
|
||||
\\"__packager_asset\\": true,
|
||||
|
@ -181,11 +181,11 @@ __d(function (global, _require, module, exports, _dependencyMap) {
|
|||
\\"name\\": \\"test\\",
|
||||
\\"type\\": \\"png\\"
|
||||
});
|
||||
},7,[8]);
|
||||
},3,[4]);
|
||||
__d(function (global, _require, module, exports, _dependencyMap) {
|
||||
'use strict';
|
||||
},8,[]);
|
||||
require(4);"
|
||||
},4,[]);
|
||||
require(0);"
|
||||
`;
|
||||
|
||||
exports[`basic_bundle bundles package without polyfills 1`] = `
|
||||
|
@ -323,7 +323,7 @@ __d(function (global, _require, module, exports, _dependencyMap) {
|
|||
Foo: Foo,
|
||||
Bar: Bar
|
||||
};
|
||||
},2,[3,4]);
|
||||
},0,[1,2]);
|
||||
__d(function (global, _require, module, exports, _dependencyMap) {
|
||||
'use strict';
|
||||
|
||||
|
@ -333,7 +333,7 @@ __d(function (global, _require, module, exports, _dependencyMap) {
|
|||
type: 'bar',
|
||||
foo: Foo.type
|
||||
};
|
||||
},3,[4]);
|
||||
},1,[2]);
|
||||
__d(function (global, _require, module, exports, _dependencyMap) {
|
||||
'use strict';
|
||||
|
||||
|
@ -343,7 +343,7 @@ __d(function (global, _require, module, exports, _dependencyMap) {
|
|||
type: 'foo',
|
||||
asset: asset
|
||||
};
|
||||
},4,[5]);
|
||||
},2,[3]);
|
||||
__d(function (global, _require, module, exports, _dependencyMap) {
|
||||
module.exports = _require(_dependencyMap[0]).registerAsset({
|
||||
\\"__packager_asset\\": true,
|
||||
|
@ -355,9 +355,9 @@ __d(function (global, _require, module, exports, _dependencyMap) {
|
|||
\\"name\\": \\"test\\",
|
||||
\\"type\\": \\"png\\"
|
||||
});
|
||||
},5,[6]);
|
||||
},3,[4]);
|
||||
__d(function (global, _require, module, exports, _dependencyMap) {
|
||||
'use strict';
|
||||
},6,[]);
|
||||
require(2);"
|
||||
},4,[]);
|
||||
require(0);"
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* 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';
|
||||
|
||||
const mapGraph = require('../mapGraph');
|
||||
|
||||
let graph;
|
||||
|
||||
beforeEach(() => {
|
||||
graph = {
|
||||
dependencies: new Map([
|
||||
['/entryPoint', {name: 'entryPoint', id: '1'}],
|
||||
['/foo', {name: 'foo', id: '2'}],
|
||||
['/baz', {name: 'baz', id: '3'}],
|
||||
]),
|
||||
entryPoints: ['/entryPoint'],
|
||||
};
|
||||
});
|
||||
|
||||
it('should map the passed graph when a sync function is passed', async () => {
|
||||
const mapped = await mapGraph(graph, element => ({
|
||||
name: '-' + element.name + '-',
|
||||
id: parseInt(element.id, 10),
|
||||
}));
|
||||
|
||||
expect(mapped.dependencies).toEqual(
|
||||
new Map([
|
||||
['/entryPoint', {name: '-entryPoint-', id: 1}],
|
||||
['/foo', {name: '-foo-', id: 2}],
|
||||
['/baz', {name: '-baz-', id: 3}],
|
||||
]),
|
||||
);
|
||||
expect(mapped.entryPoints).toEqual(['/entryPoint']);
|
||||
});
|
||||
|
||||
it('should map the passed graph when an async function is passed', async () => {
|
||||
const mapped = await mapGraph(graph, async element => ({
|
||||
name: '-' + element.name + '-',
|
||||
id: parseInt(element.id, 10),
|
||||
}));
|
||||
|
||||
expect(mapped.dependencies).toEqual(
|
||||
new Map([
|
||||
['/entryPoint', {name: '-entryPoint-', id: 1}],
|
||||
['/foo', {name: '-foo-', id: 2}],
|
||||
['/baz', {name: '-baz-', id: 3}],
|
||||
]),
|
||||
);
|
||||
expect(mapped.entryPoints).toEqual(['/entryPoint']);
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* 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';
|
||||
|
||||
import type {Graph} from '../DeltaBundler/DeltaCalculator';
|
||||
import type {DependencyEdge} from '../DeltaBundler/traverseDependencies';
|
||||
|
||||
type Options = {
|
||||
+createModuleId: string => number | string,
|
||||
+runBeforeMainModule: $ReadOnlyArray<string>,
|
||||
+runModule: boolean,
|
||||
+sourceMapUrl: ?string,
|
||||
};
|
||||
|
||||
function getAppendScripts(
|
||||
entryPoint: string,
|
||||
graph: Graph,
|
||||
options: Options,
|
||||
): $ReadOnlyArray<DependencyEdge> {
|
||||
const output = [];
|
||||
|
||||
if (options.runModule) {
|
||||
const paths = [...options.runBeforeMainModule, entryPoint];
|
||||
|
||||
for (const path of paths) {
|
||||
if (graph.dependencies.has(path)) {
|
||||
output.push({
|
||||
path: `require-${path}`,
|
||||
dependencies: new Map(),
|
||||
inverseDependencies: new Set(),
|
||||
output: {
|
||||
code: `require(${JSON.stringify(options.createModuleId(path))});`,
|
||||
source: '',
|
||||
map: [],
|
||||
type: 'script',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.sourceMapUrl) {
|
||||
output.push({
|
||||
path: 'source-map',
|
||||
dependencies: new Map(),
|
||||
inverseDependencies: new Set(),
|
||||
output: {
|
||||
code: `//# sourceMappingURL=${options.sourceMapUrl}`,
|
||||
source: '',
|
||||
map: [],
|
||||
type: 'script',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
module.exports = getAppendScripts;
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* 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 defaults = require('../defaults');
|
||||
const getPreludeCode = require('./getPreludeCode');
|
||||
|
||||
import type Bundler from '../Bundler';
|
||||
import type {DependencyEdge} from '../DeltaBundler/traverseDependencies';
|
||||
import type Module from '../node-haste/Module';
|
||||
|
||||
type Options = {
|
||||
enableBabelRCLookup: boolean,
|
||||
getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>,
|
||||
polyfillModuleNames: Array<string>,
|
||||
projectRoots: $ReadOnlyArray<string>,
|
||||
};
|
||||
|
||||
type BundleOptions = {
|
||||
+dev: boolean,
|
||||
+hot: boolean,
|
||||
+platform: ?string,
|
||||
};
|
||||
|
||||
async function getPrependedScripts(
|
||||
options: Options,
|
||||
bundleOptions: BundleOptions,
|
||||
bundler: Bundler,
|
||||
): Promise<Array<DependencyEdge>> {
|
||||
// Get all the polyfills from the relevant option params (the
|
||||
// `getPolyfills()` method and the `polyfillModuleNames` variable).
|
||||
const polyfillModuleNames = options
|
||||
.getPolyfills({
|
||||
platform: bundleOptions.platform,
|
||||
})
|
||||
.concat(options.polyfillModuleNames);
|
||||
|
||||
const dependencyGraph = await bundler.getDependencyGraph();
|
||||
|
||||
// Build the module system dependencies (scripts that need to
|
||||
// be included at the very beginning of the bundle) + any polifyll.
|
||||
const modules = [defaults.moduleSystem]
|
||||
.concat(polyfillModuleNames)
|
||||
.map(polyfillModuleName =>
|
||||
dependencyGraph.createPolyfill({
|
||||
file: polyfillModuleName,
|
||||
}),
|
||||
);
|
||||
|
||||
const transformOptions = {
|
||||
dev: bundleOptions.dev,
|
||||
enableBabelRCLookup: options.enableBabelRCLookup,
|
||||
hot: bundleOptions.hot,
|
||||
projectRoot: options.projectRoots[0],
|
||||
};
|
||||
|
||||
const out = await Promise.all(
|
||||
modules.map(module => _createEdgeFromScript(module, transformOptions)),
|
||||
);
|
||||
|
||||
out.unshift(_getPrelude({dev: bundleOptions.dev}));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function _getPrelude({dev}: {dev: boolean}): DependencyEdge {
|
||||
const code = getPreludeCode({isDev: dev});
|
||||
const name = '__prelude__';
|
||||
|
||||
return {
|
||||
dependencies: new Map(),
|
||||
inverseDependencies: new Set(),
|
||||
path: name,
|
||||
output: {
|
||||
code,
|
||||
map: [],
|
||||
source: code,
|
||||
type: 'script',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function _createEdgeFromScript(
|
||||
module: Module,
|
||||
options: {
|
||||
dev: boolean,
|
||||
enableBabelRCLookup: boolean,
|
||||
hot: boolean,
|
||||
projectRoot: string,
|
||||
},
|
||||
): Promise<DependencyEdge> {
|
||||
const result = await module.read({
|
||||
assetDataPlugins: [],
|
||||
customTransformOptions: {},
|
||||
dev: options.dev,
|
||||
enableBabelRCLookup: options.enableBabelRCLookup,
|
||||
hot: options.hot,
|
||||
inlineRequires: false,
|
||||
minify: false,
|
||||
platform: undefined,
|
||||
projectRoot: options.projectRoot,
|
||||
});
|
||||
|
||||
return {
|
||||
dependencies: new Map(),
|
||||
inverseDependencies: new Set(),
|
||||
path: module.path,
|
||||
output: {
|
||||
code: result.code,
|
||||
map: result.map,
|
||||
source: result.source,
|
||||
type: 'script',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = getPrependedScripts;
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* 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';
|
||||
|
||||
import type {DependencyEdge} from '../DeltaBundler/traverseDependencies';
|
||||
import type {Graph} from '../DeltaBundler';
|
||||
|
||||
/**
|
||||
* Generates a new Graph object, which has all the dependencies returned by the
|
||||
* mapping function (similar to Array.prototype.map).
|
||||
**/
|
||||
async function mapGraph(
|
||||
graph: Graph,
|
||||
mappingFn: DependencyEdge => Promise<DependencyEdge>,
|
||||
): Promise<Graph> {
|
||||
const dependencies = new Map(
|
||||
await Promise.all(
|
||||
Array.from(graph.dependencies.entries()).map(async ([path, module]) => {
|
||||
const mutated = await mappingFn(module);
|
||||
|
||||
return [path, mutated];
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
dependencies,
|
||||
entryPoints: graph.entryPoints,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = mapGraph;
|
Loading…
Reference in New Issue