mirror of https://github.com/status-im/metro.git
Use Graph traversal logic for building polyfills
Reviewed By: mjesun Differential Revision: D7240946 fbshipit-source-id: 5af729878cdf31831b15867c296cf89025ab6f58
This commit is contained in:
parent
6be6b0805d
commit
d8eed45c37
|
@ -42,6 +42,7 @@ export type Options = {
|
|||
+minify: boolean,
|
||||
+onProgress: ?(doneCont: number, totalCount: number) => mixed,
|
||||
+platform: ?string,
|
||||
+type: 'module' | 'script',
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -199,6 +200,17 @@ class DeltaCalculator extends EventEmitter {
|
|||
projectRoot,
|
||||
};
|
||||
|
||||
// When we're processing scripts, we don't need to calculate any
|
||||
// inlineRequires information, since scripts by definition don't have
|
||||
// requires().
|
||||
if (this._options.type === 'script') {
|
||||
// $FlowIssue #23854098 - Object.assign() loses the strictness of an object in flow
|
||||
return {
|
||||
...transformOptionsForBlacklist,
|
||||
inlineRequires: false,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
inlineRequires,
|
||||
} = await this._bundler.getTransformOptionsForEntryFiles(
|
||||
|
@ -211,14 +223,14 @@ class DeltaCalculator extends EventEmitter {
|
|||
entryPoints: [path],
|
||||
},
|
||||
this._dependencyGraph,
|
||||
transformOptionsForBlacklist,
|
||||
{...transformOptionsForBlacklist, type: this._options.type},
|
||||
);
|
||||
|
||||
return Array.from(added.keys());
|
||||
},
|
||||
);
|
||||
|
||||
// $FlowFixMe flow does not recognize well Object.assign() return types.
|
||||
// $FlowIssue #23854098 - Object.assign() loses the strictness of an object in flow
|
||||
return {
|
||||
...transformOptionsForBlacklist,
|
||||
inlineRequires: inlineRequires || false,
|
||||
|
@ -267,7 +279,10 @@ class DeltaCalculator extends EventEmitter {
|
|||
modifiedFiles: Set<string>,
|
||||
deletedFiles: Set<string>,
|
||||
): Promise<DeltaResult> {
|
||||
const transformerOptions = await this.getTransformerOptions();
|
||||
const transformerOptions = {
|
||||
...(await this.getTransformerOptions()),
|
||||
type: this._options.type,
|
||||
};
|
||||
|
||||
if (!this._graph.dependencies.size) {
|
||||
const {added} = await initialTraverseDependencies(
|
||||
|
|
|
@ -126,6 +126,7 @@ class DeltaTransformer extends EventEmitter {
|
|||
const deltaCalculator = new DeltaCalculator(bundler, dependencyGraph, {
|
||||
...bundleOptions,
|
||||
entryPoints: [bundleOptions.entryFile],
|
||||
type: 'module',
|
||||
});
|
||||
|
||||
return new DeltaTransformer(
|
||||
|
|
|
@ -52,6 +52,11 @@ type Delta = {
|
|||
deleted: Set<string>,
|
||||
};
|
||||
|
||||
export type TransformOptions = {|
|
||||
...JSTransformerOptions,
|
||||
type: 'module' | 'script',
|
||||
|};
|
||||
|
||||
/**
|
||||
* Dependency Traversal logic for the Delta Bundler. This method calculates
|
||||
* the modules that should be included in the bundle by traversing the
|
||||
|
@ -69,7 +74,7 @@ type Delta = {
|
|||
async function traverseDependencies(
|
||||
paths: $ReadOnlyArray<string>,
|
||||
dependencyGraph: DependencyGraph,
|
||||
transformOptions: JSTransformerOptions,
|
||||
transformOptions: TransformOptions,
|
||||
graph: Graph,
|
||||
onProgress?: (numProcessed: number, total: number) => mixed = () => {},
|
||||
): Promise<Result> {
|
||||
|
@ -136,11 +141,17 @@ async function traverseDependencies(
|
|||
async function initialTraverseDependencies(
|
||||
graph: Graph,
|
||||
dependencyGraph: DependencyGraph,
|
||||
transformOptions: JSTransformerOptions,
|
||||
transformOptions: TransformOptions,
|
||||
onProgress?: (numProcessed: number, total: number) => mixed = () => {},
|
||||
): Promise<Result> {
|
||||
graph.entryPoints.forEach(entryPoint =>
|
||||
createEdge(dependencyGraph.getModuleForPath(entryPoint), graph),
|
||||
createEdge(
|
||||
dependencyGraph.getModuleForPath(
|
||||
entryPoint,
|
||||
transformOptions.type === 'script',
|
||||
),
|
||||
graph,
|
||||
),
|
||||
);
|
||||
|
||||
await traverseDependencies(
|
||||
|
@ -162,7 +173,7 @@ async function initialTraverseDependencies(
|
|||
async function traverseDependenciesForSingleFile(
|
||||
edge: DependencyEdge,
|
||||
dependencyGraph: DependencyGraph,
|
||||
transformOptions: JSTransformerOptions,
|
||||
transformOptions: TransformOptions,
|
||||
graph: Graph,
|
||||
delta: Delta,
|
||||
onProgress?: (numProcessed: number, total: number) => mixed = () => {},
|
||||
|
@ -194,7 +205,7 @@ async function traverseDependenciesForSingleFile(
|
|||
async function processEdge(
|
||||
edge: DependencyEdge,
|
||||
dependencyGraph: DependencyGraph,
|
||||
transformOptions: JSTransformerOptions,
|
||||
transformOptions: TransformOptions,
|
||||
graph: Graph,
|
||||
delta: Delta,
|
||||
onDependencyAdd: () => mixed,
|
||||
|
@ -202,10 +213,11 @@ async function processEdge(
|
|||
): Promise<void> {
|
||||
const previousDependencies = edge.dependencies;
|
||||
|
||||
const result = await dependencyGraph
|
||||
.getModuleForPath(edge.path)
|
||||
.read(
|
||||
removeInlineRequiresBlacklistFromOptions(edge.path, transformOptions),
|
||||
const {type, ...workerTransformOptions} = transformOptions;
|
||||
|
||||
const module = dependencyGraph.getModuleForPath(edge.path, type === 'script');
|
||||
const result = await module.read(
|
||||
removeInlineRequiresBlacklistFromOptions(edge.path, workerTransformOptions),
|
||||
);
|
||||
|
||||
// Get the absolute path of all sub-dependencies (some of them could have been
|
||||
|
@ -262,7 +274,7 @@ async function addDependency(
|
|||
parentEdge: DependencyEdge,
|
||||
path: string,
|
||||
dependencyGraph: DependencyGraph,
|
||||
transformOptions: JSTransformerOptions,
|
||||
transformOptions: TransformOptions,
|
||||
graph: Graph,
|
||||
delta: Delta,
|
||||
onDependencyAdd: () => mixed,
|
||||
|
@ -277,7 +289,10 @@ async function addDependency(
|
|||
return;
|
||||
}
|
||||
|
||||
const edge = createEdge(dependencyGraph.getModuleForPath(path), graph);
|
||||
const edge = createEdge(
|
||||
dependencyGraph.getModuleForPath(path, transformOptions.type === 'script'),
|
||||
graph,
|
||||
);
|
||||
|
||||
edge.inverseDependencies.add(parentEdge.path);
|
||||
delta.added.set(edge.path, edge);
|
||||
|
@ -365,11 +380,14 @@ function destroyEdge(edge: DependencyEdge, graph: Graph) {
|
|||
|
||||
function resolveDependencies(
|
||||
parentPath,
|
||||
dependencies: Array<string>,
|
||||
dependencies: $ReadOnlyArray<string>,
|
||||
dependencyGraph: DependencyGraph,
|
||||
transformOptions: JSTransformerOptions,
|
||||
transformOptions: TransformOptions,
|
||||
): Map<string, string> {
|
||||
const parentModule = dependencyGraph.getModuleForPath(parentPath);
|
||||
const parentModule = dependencyGraph.getModuleForPath(
|
||||
parentPath,
|
||||
transformOptions.type === 'string',
|
||||
);
|
||||
|
||||
return new Map(
|
||||
dependencies.map(relativePath => [
|
||||
|
|
|
@ -466,6 +466,7 @@ describe('processRequest', () => {
|
|||
minify: false,
|
||||
onProgress: null,
|
||||
platform: undefined,
|
||||
type: 'module',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -245,7 +245,7 @@ class Server {
|
|||
this._opts.projectRoots,
|
||||
);
|
||||
|
||||
let graph = await this._deltaBundler.buildGraph({
|
||||
const crawlingOptions = {
|
||||
assetPlugins: options.assetPlugins,
|
||||
customTransformOptions: options.customTransformOptions,
|
||||
dev: options.dev,
|
||||
|
@ -254,11 +254,14 @@ class Server {
|
|||
minify: options.minify,
|
||||
onProgress: options.onProgress,
|
||||
platform: options.platform,
|
||||
});
|
||||
type: 'module',
|
||||
};
|
||||
|
||||
let graph = await this._deltaBundler.buildGraph(crawlingOptions);
|
||||
let prependScripts = await getPrependedScripts(
|
||||
this._opts,
|
||||
options,
|
||||
this._bundler,
|
||||
crawlingOptions,
|
||||
this._deltaBundler,
|
||||
);
|
||||
|
||||
if (options.minify) {
|
||||
|
@ -973,6 +976,7 @@ class Server {
|
|||
runBeforeMainModule: [],
|
||||
runModule: true,
|
||||
sourceMapUrl: null,
|
||||
type: 'script',
|
||||
unbundle: false,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ async function getTransformOptions(): Promise<JSTransformerOptions> {
|
|||
hot: true,
|
||||
minify: false,
|
||||
platform: 'ios',
|
||||
type: 'module',
|
||||
};
|
||||
|
||||
const deltaCalculator = new DeltaCalculator(
|
||||
|
|
|
@ -13,27 +13,27 @@
|
|||
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';
|
||||
import type DeltaBundler from '../DeltaBundler';
|
||||
import type {CustomTransformOptions} from '../JSTransformer/worker';
|
||||
|
||||
type Options = {
|
||||
enableBabelRCLookup: boolean,
|
||||
getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>,
|
||||
polyfillModuleNames: Array<string>,
|
||||
projectRoots: $ReadOnlyArray<string>,
|
||||
};
|
||||
|
||||
type BundleOptions = {
|
||||
customTransformOptions: CustomTransformOptions,
|
||||
+dev: boolean,
|
||||
+hot: boolean,
|
||||
+minify: boolean,
|
||||
+platform: ?string,
|
||||
};
|
||||
|
||||
async function getPrependedScripts(
|
||||
options: Options,
|
||||
bundleOptions: BundleOptions,
|
||||
bundler: Bundler,
|
||||
deltaBundler: DeltaBundler,
|
||||
): Promise<Array<DependencyEdge>> {
|
||||
// Get all the polyfills from the relevant option params (the
|
||||
// `getPolyfills()` method and the `polyfillModuleNames` variable).
|
||||
|
@ -43,32 +43,22 @@ async function getPrependedScripts(
|
|||
})
|
||||
.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 = {
|
||||
const graph = await deltaBundler.buildGraph({
|
||||
assetPlugins: [],
|
||||
customTransformOptions: bundleOptions.customTransformOptions,
|
||||
dev: bundleOptions.dev,
|
||||
enableBabelRCLookup: options.enableBabelRCLookup,
|
||||
entryPoints: [defaults.moduleSystem, ...polyfillModuleNames],
|
||||
hot: bundleOptions.hot,
|
||||
projectRoot: options.projectRoots[0],
|
||||
};
|
||||
minify: bundleOptions.minify,
|
||||
onProgress: null,
|
||||
platform: bundleOptions.platform,
|
||||
type: 'script',
|
||||
});
|
||||
|
||||
const out = await Promise.all(
|
||||
modules.map(module => _createEdgeFromScript(module, transformOptions)),
|
||||
);
|
||||
|
||||
out.unshift(_getPrelude({dev: bundleOptions.dev}));
|
||||
|
||||
return out;
|
||||
return [
|
||||
_getPrelude({dev: bundleOptions.dev}),
|
||||
...graph.dependencies.values(),
|
||||
];
|
||||
}
|
||||
|
||||
function _getPrelude({dev}: {dev: boolean}): DependencyEdge {
|
||||
|
@ -88,38 +78,4 @@ function _getPrelude({dev}: {dev: boolean}): DependencyEdge {
|
|||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -238,7 +238,11 @@ class DependencyGraph extends EventEmitter {
|
|||
this._haste.end();
|
||||
}
|
||||
|
||||
getModuleForPath(entryFile: string) {
|
||||
getModuleForPath(entryFile: string, isPolyfill: boolean): Module {
|
||||
if (isPolyfill) {
|
||||
return this._moduleCache.getPolyfillModule(entryFile);
|
||||
}
|
||||
|
||||
if (this._helpers.isAssetFile(entryFile)) {
|
||||
return this._moduleCache.getAssetModule(entryFile);
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ class ModuleCache {
|
|||
this._roots = roots;
|
||||
}
|
||||
|
||||
getModule(filePath: string): Module {
|
||||
getModule(filePath: string) {
|
||||
if (!this._moduleCache[filePath]) {
|
||||
this._moduleCache[filePath] = new Module({
|
||||
depGraphHelpers: this._depGraphHelpers,
|
||||
|
@ -129,6 +129,14 @@ class ModuleCache {
|
|||
return this._moduleCache[filePath];
|
||||
}
|
||||
|
||||
getPolyfillModule(filePath: string) {
|
||||
if (!this._moduleCache[filePath]) {
|
||||
this._moduleCache[filePath] = this.createPolyfill({file: filePath});
|
||||
}
|
||||
|
||||
return this._moduleCache[filePath];
|
||||
}
|
||||
|
||||
getPackage(filePath: string): Package {
|
||||
if (!this._packageCache[filePath]) {
|
||||
this._packageCache[filePath] = new Package({
|
||||
|
|
|
@ -119,14 +119,6 @@ type Params = {
|
|||
};
|
||||
|
||||
function transform({filename, options, src, plugins}: Params) {
|
||||
options = options || {
|
||||
assetDataPlugins: [],
|
||||
platform: '',
|
||||
projectRoot: '',
|
||||
inlineRequires: false,
|
||||
minify: false,
|
||||
};
|
||||
|
||||
const OLD_BABEL_ENV = process.env.BABEL_ENV;
|
||||
process.env.BABEL_ENV = options.dev ? 'development' : 'production';
|
||||
|
||||
|
|
Loading…
Reference in New Issue