mirror of https://github.com/status-im/metro.git
Add `bundle` command
Summary: This adds the machinery necessary to create a bundling function, and adds different reusable parts around generating code and maps for bundles. Used for the new integration with Buck Reviewed By: cpojer Differential Revision: D4299272 fbshipit-source-id: 59ebe39a454ebf56c2159717c2881088d6d3308a
This commit is contained in:
parent
d556e5824a
commit
4843500e9e
|
@ -0,0 +1,102 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2016-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
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const defaults = require('../../../defaults');
|
||||||
|
const nullthrows = require('fbjs/lib/nullthrows');
|
||||||
|
const parallel = require('async/parallel');
|
||||||
|
const seq = require('async/seq');
|
||||||
|
|
||||||
|
const {virtualModule} = require('./output/util');
|
||||||
|
|
||||||
|
import type {
|
||||||
|
Callback,
|
||||||
|
GraphFn,
|
||||||
|
GraphResult,
|
||||||
|
Module,
|
||||||
|
} from './types.flow';
|
||||||
|
|
||||||
|
type BuildFn = (
|
||||||
|
entryPoints: Iterable<string>,
|
||||||
|
options: BuildOptions,
|
||||||
|
callback: Callback<{modules: Iterable<Module>, entryModules: Iterable<Module>}>,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
type BuildOptions = {|
|
||||||
|
optimize?: boolean,
|
||||||
|
platform?: string,
|
||||||
|
|};
|
||||||
|
|
||||||
|
exports.createBuildSetup = (
|
||||||
|
graph: GraphFn,
|
||||||
|
translateDefaultsPath: string => string = x => x,
|
||||||
|
): BuildFn =>
|
||||||
|
(entryPoints, options, callback) => {
|
||||||
|
const {
|
||||||
|
optimize = false,
|
||||||
|
platform = defaults.platforms[0],
|
||||||
|
} = options;
|
||||||
|
const graphOptions = {optimize};
|
||||||
|
|
||||||
|
const graphWithOptions =
|
||||||
|
(entry, cb) => graph(entry, platform, graphOptions, cb);
|
||||||
|
const graphOnlyModules = seq(graphWithOptions, getModules);
|
||||||
|
|
||||||
|
parallel({
|
||||||
|
graph: cb => graphWithOptions(
|
||||||
|
concat(defaults.runBeforeMainModule, entryPoints),
|
||||||
|
cb,
|
||||||
|
),
|
||||||
|
moduleSystem: cb => graphOnlyModules(
|
||||||
|
[translateDefaultsPath(defaults.moduleSystem)],
|
||||||
|
cb,
|
||||||
|
),
|
||||||
|
polyfills: cb => graphOnlyModules(
|
||||||
|
defaults.polyfills.map(translateDefaultsPath),
|
||||||
|
cb,
|
||||||
|
),
|
||||||
|
}, (
|
||||||
|
error: ?Error,
|
||||||
|
result?: {graph: GraphResult, moduleSystem: Array<Module>, polyfills: Array<Module>},
|
||||||
|
) => {
|
||||||
|
if (error) {
|
||||||
|
callback(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const {
|
||||||
|
graph: {modules, entryModules},
|
||||||
|
moduleSystem,
|
||||||
|
polyfills,
|
||||||
|
} = nullthrows(result);
|
||||||
|
|
||||||
|
callback(null, {
|
||||||
|
entryModules,
|
||||||
|
modules: concat([prelude(optimize)], moduleSystem, polyfills, modules),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getModules = (x, cb) => cb(null, x.modules);
|
||||||
|
|
||||||
|
function* concat<T>(...iterables: Array<Iterable<T>>): Iterable<T> {
|
||||||
|
for (const it of iterables) {
|
||||||
|
yield* it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prelude(optimize) {
|
||||||
|
return virtualModule(
|
||||||
|
`var __DEV__= ${String(!optimize)
|
||||||
|
}, __BUNDLE_START_TIME__ = Date.now();`
|
||||||
|
);
|
||||||
|
}
|
|
@ -13,14 +13,10 @@
|
||||||
const {createIndexMap} = require('./source-map');
|
const {createIndexMap} = require('./source-map');
|
||||||
const {addModuleIdsToModuleWrapper} = require('./util');
|
const {addModuleIdsToModuleWrapper} = require('./util');
|
||||||
|
|
||||||
import type {Module} from '../types.flow';
|
import type {OutputFn} from '../types.flow';
|
||||||
import type {SourceMap} from './source-map';
|
|
||||||
|
|
||||||
module.exports = (
|
module.exports = (
|
||||||
modules: Iterable<Module>,
|
(modules, filename, idForPath) => {
|
||||||
filename?: string,
|
|
||||||
idForPath: {path: string} => number,
|
|
||||||
): {code: string, map: SourceMap} => {
|
|
||||||
let code = '';
|
let code = '';
|
||||||
let line = 0;
|
let line = 0;
|
||||||
const sections = [];
|
const sections = [];
|
||||||
|
@ -42,7 +38,7 @@ module.exports = (
|
||||||
}
|
}
|
||||||
|
|
||||||
return {code, map: createIndexMap({file: filename, sections})};
|
return {code, map: createIndexMap({file: filename, sections})};
|
||||||
};
|
}: OutputFn);
|
||||||
|
|
||||||
const reLine = /^/gm;
|
const reLine = /^/gm;
|
||||||
function countLines(string: string): number {
|
function countLines(string: string): number {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import type {Module} from '../types.flow';
|
import type {IdForPathFn, Module} from '../types.flow';
|
||||||
|
|
||||||
// Transformed modules have the form
|
// Transformed modules have the form
|
||||||
// __d(function(require, module, global, exports, dependencyMap) {
|
// __d(function(require, module, global, exports, dependencyMap) {
|
||||||
|
@ -59,11 +59,27 @@ exports.createIdForPathFn = (): ({path: string} => number) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.virtualModule = (code: string): Module => ({
|
// creates a series of virtual modules with require calls to the passed-in
|
||||||
|
// modules.
|
||||||
|
exports.requireCallsTo = function* (
|
||||||
|
modules: Iterable<Module>,
|
||||||
|
idForPath: IdForPathFn,
|
||||||
|
): Iterable<Module> {
|
||||||
|
for (const module of modules) {
|
||||||
|
yield virtualModule(`require(${idForPath(module.file)});`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// creates a virtual module (i.e. not corresponding to a file on disk)
|
||||||
|
// with the given source code.
|
||||||
|
exports.virtualModule = virtualModule;
|
||||||
|
function virtualModule(code: string) {
|
||||||
|
return {
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
file: {
|
file: {
|
||||||
code,
|
code,
|
||||||
path: '',
|
path: '',
|
||||||
type: 'script',
|
type: 'script',
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
{"main": "ModuleGraph.js"}
|
|
@ -10,29 +10,13 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import type {SourceMap} from './output/source-map';
|
||||||
import type {Console} from 'console';
|
import type {Console} from 'console';
|
||||||
|
|
||||||
export type Callback<A = void, B = void>
|
export type Callback<A = void, B = void>
|
||||||
= (Error => mixed)
|
= (Error => mixed)
|
||||||
& ((null | void, A, B) => mixed);
|
& ((null | void, A, B) => mixed);
|
||||||
|
|
||||||
type ResolveOptions = {
|
|
||||||
log?: Console,
|
|
||||||
};
|
|
||||||
|
|
||||||
type LoadOptions = {|
|
|
||||||
log?: Console,
|
|
||||||
optimize?: boolean,
|
|
||||||
platform?: string,
|
|
||||||
|};
|
|
||||||
|
|
||||||
type GraphOptions = {|
|
|
||||||
cwd?: string,
|
|
||||||
log?: Console,
|
|
||||||
optimize?: boolean,
|
|
||||||
skip?: Set<string>,
|
|
||||||
|};
|
|
||||||
|
|
||||||
type Dependency = {|
|
type Dependency = {|
|
||||||
id: string,
|
id: string,
|
||||||
path: string,
|
path: string,
|
||||||
|
@ -47,11 +31,6 @@ export type File = {|
|
||||||
|
|
||||||
type FileTypes = 'module' | 'script';
|
type FileTypes = 'module' | 'script';
|
||||||
|
|
||||||
export type Module = {|
|
|
||||||
dependencies: Array<Dependency>,
|
|
||||||
file: File,
|
|
||||||
|};
|
|
||||||
|
|
||||||
export type GraphFn = (
|
export type GraphFn = (
|
||||||
entryPoints: Iterable<string>,
|
entryPoints: Iterable<string>,
|
||||||
platform: string,
|
platform: string,
|
||||||
|
@ -59,11 +38,55 @@ export type GraphFn = (
|
||||||
callback?: Callback<GraphResult>,
|
callback?: Callback<GraphResult>,
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
|
type GraphOptions = {|
|
||||||
|
cwd?: string,
|
||||||
|
log?: Console,
|
||||||
|
optimize?: boolean,
|
||||||
|
skip?: Set<string>,
|
||||||
|
|};
|
||||||
|
|
||||||
export type GraphResult = {
|
export type GraphResult = {
|
||||||
entryModules: Array<Module>,
|
entryModules: Array<Module>,
|
||||||
modules: Array<Module>,
|
modules: Array<Module>,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type IdForPathFn = {path: string} => number;
|
||||||
|
|
||||||
|
export type LoadFn = (
|
||||||
|
file: string,
|
||||||
|
options: LoadOptions,
|
||||||
|
callback: Callback<File, Array<string>>,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
type LoadOptions = {|
|
||||||
|
log?: Console,
|
||||||
|
optimize?: boolean,
|
||||||
|
platform?: string,
|
||||||
|
|};
|
||||||
|
|
||||||
|
export type Module = {|
|
||||||
|
dependencies: Array<Dependency>,
|
||||||
|
file: File,
|
||||||
|
|};
|
||||||
|
|
||||||
|
export type OutputFn = (
|
||||||
|
modules: Iterable<Module>,
|
||||||
|
filename?: string,
|
||||||
|
idForPath: IdForPathFn,
|
||||||
|
) => OutputResult;
|
||||||
|
|
||||||
|
type OutputResult = {
|
||||||
|
code: string,
|
||||||
|
map: SourceMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PackageData = {|
|
||||||
|
browser?: Object | string,
|
||||||
|
main?: string,
|
||||||
|
name?: string,
|
||||||
|
'react-native'?: Object | string,
|
||||||
|
|};
|
||||||
|
|
||||||
export type ResolveFn = (
|
export type ResolveFn = (
|
||||||
id: string,
|
id: string,
|
||||||
source: string,
|
source: string,
|
||||||
|
@ -72,12 +95,25 @@ export type ResolveFn = (
|
||||||
callback: Callback<string>,
|
callback: Callback<string>,
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
export type LoadFn = (
|
type ResolveOptions = {
|
||||||
file: string,
|
log?: Console,
|
||||||
options: LoadOptions,
|
};
|
||||||
callback: Callback<File, Array<string>>,
|
|
||||||
|
export type TransformFn = (
|
||||||
|
data: {|
|
||||||
|
filename: string,
|
||||||
|
options?: Object,
|
||||||
|
plugins?: Array<string | Object | [string | Object, any]>,
|
||||||
|
sourceCode: string,
|
||||||
|
|},
|
||||||
|
callback: Callback<TransformFnResult>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
|
|
||||||
|
export type TransformFnResult = {
|
||||||
|
ast: Object,
|
||||||
|
};
|
||||||
|
|
||||||
export type TransformResult = {|
|
export type TransformResult = {|
|
||||||
code: string,
|
code: string,
|
||||||
dependencies: Array<string>,
|
dependencies: Array<string>,
|
||||||
|
@ -93,24 +129,3 @@ export type TransformedFile = {
|
||||||
transformed: {[variant: string]: TransformResult},
|
transformed: {[variant: string]: TransformResult},
|
||||||
type: FileTypes,
|
type: FileTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PackageData = {|
|
|
||||||
browser?: Object | string,
|
|
||||||
main?: string,
|
|
||||||
name?: string,
|
|
||||||
'react-native'?: Object | string,
|
|
||||||
|};
|
|
||||||
|
|
||||||
export type TransformFnResult = {
|
|
||||||
ast: Object,
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TransformFn = (
|
|
||||||
data: {|
|
|
||||||
filename: string,
|
|
||||||
options?: Object,
|
|
||||||
plugins?: Array<string | Object | [string | Object, any]>,
|
|
||||||
sourceCode: string,
|
|
||||||
|},
|
|
||||||
callback: Callback<TransformFnResult>
|
|
||||||
) => void;
|
|
||||||
|
|
Loading…
Reference in New Issue