mirror of https://github.com/status-im/metro.git
Move minification to the transformation phase
Reviewed By: mjesun Differential Revision: D7670710 fbshipit-source-id: 8a55de0d3a1ee4879d21391d47fd0acd66482f44
This commit is contained in:
parent
310c096671
commit
380ad7105a
|
@ -19,11 +19,6 @@ const fs = require('fs');
|
||||||
const getTransformCacheKeyFn = require('./lib/getTransformCacheKeyFn');
|
const getTransformCacheKeyFn = require('./lib/getTransformCacheKeyFn');
|
||||||
|
|
||||||
const {Cache, stableHash} = require('metro-cache');
|
const {Cache, stableHash} = require('metro-cache');
|
||||||
const {
|
|
||||||
toSegmentTuple,
|
|
||||||
fromRawMappings,
|
|
||||||
toBabelSegments,
|
|
||||||
} = require('metro-source-map');
|
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
TransformedCode,
|
TransformedCode,
|
||||||
|
@ -37,10 +32,7 @@ import type Module from './node-haste/Module';
|
||||||
import type {BabelSourceMap} from '@babel/core';
|
import type {BabelSourceMap} from '@babel/core';
|
||||||
import type {CacheStore} from 'metro-cache';
|
import type {CacheStore} from 'metro-cache';
|
||||||
import type {CustomResolver} from 'metro-resolver';
|
import type {CustomResolver} from 'metro-resolver';
|
||||||
import type {
|
import type {MetroSourceMap} from 'metro-source-map';
|
||||||
MetroSourceMapSegmentTuple,
|
|
||||||
MetroSourceMap,
|
|
||||||
} from 'metro-source-map';
|
|
||||||
|
|
||||||
type TransformOptions = {|
|
type TransformOptions = {|
|
||||||
+inlineRequires: {+blacklist: {[string]: true}} | boolean,
|
+inlineRequires: {+blacklist: {[string]: true}} | boolean,
|
||||||
|
@ -135,7 +127,6 @@ class Bundler {
|
||||||
this._transformer = new Transformer({
|
this._transformer = new Transformer({
|
||||||
asyncRequireModulePath: opts.asyncRequireModulePath,
|
asyncRequireModulePath: opts.asyncRequireModulePath,
|
||||||
maxWorkers: opts.maxWorkers,
|
maxWorkers: opts.maxWorkers,
|
||||||
minifierPath: opts.minifierPath,
|
|
||||||
reporters: {
|
reporters: {
|
||||||
stdoutChunk: chunk =>
|
stdoutChunk: chunk =>
|
||||||
opts.reporter.update({type: 'worker_stdout_chunk', chunk}),
|
opts.reporter.update({type: 'worker_stdout_chunk', chunk}),
|
||||||
|
@ -177,6 +168,7 @@ class Bundler {
|
||||||
opts.assetExts,
|
opts.assetExts,
|
||||||
opts.assetRegistryPath,
|
opts.assetRegistryPath,
|
||||||
getTransformCacheKey,
|
getTransformCacheKey,
|
||||||
|
opts.minifierPath,
|
||||||
'experimental',
|
'experimental',
|
||||||
]).toString('binary');
|
]).toString('binary');
|
||||||
|
|
||||||
|
@ -237,25 +229,6 @@ class Bundler {
|
||||||
return this._depGraphPromise;
|
return this._depGraphPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
async minifyModule(
|
|
||||||
path: string,
|
|
||||||
code: string,
|
|
||||||
map: Array<MetroSourceMapSegmentTuple>,
|
|
||||||
): Promise<{code: string, map: Array<MetroSourceMapSegmentTuple>}> {
|
|
||||||
const sourceMap = fromRawMappings([{code, source: code, map, path}]).toMap(
|
|
||||||
undefined,
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
|
|
||||||
const minified = await this._transformer.minify(path, code, sourceMap);
|
|
||||||
const result = await this._opts.postMinifyProcess({...minified});
|
|
||||||
|
|
||||||
return {
|
|
||||||
code: result.code,
|
|
||||||
map: result.map ? toBabelSegments(result.map).map(toSegmentTuple) : [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async _cachedTransformCode(
|
async _cachedTransformCode(
|
||||||
module: Module,
|
module: Module,
|
||||||
code: ?string,
|
code: ?string,
|
||||||
|
@ -334,6 +307,7 @@ class Bundler {
|
||||||
transformCodeOptions,
|
transformCodeOptions,
|
||||||
this._opts.assetExts,
|
this._opts.assetExts,
|
||||||
this._opts.assetRegistryPath,
|
this._opts.assetRegistryPath,
|
||||||
|
this._opts.minifierPath,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
jest
|
jest
|
||||||
.setMock('jest-worker', () => ({}))
|
.setMock('jest-worker', () => ({}))
|
||||||
.setMock('metro-minify-uglify')
|
|
||||||
.mock('image-size')
|
.mock('image-size')
|
||||||
.mock('fs', () => new (require('metro-memory-fs'))())
|
.mock('fs', () => new (require('metro-memory-fs'))())
|
||||||
.mock('os')
|
.mock('os')
|
||||||
|
@ -97,28 +96,6 @@ describe('Bundler', function() {
|
||||||
expect(b._opts.platforms).toEqual(['android', 'vr']);
|
expect(b._opts.platforms).toEqual(['android', 'vr']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should minify code using the Transformer', async () => {
|
|
||||||
const code = 'arbitrary(code)';
|
|
||||||
const id = 'arbitrary.js';
|
|
||||||
|
|
||||||
const minifiedCode = 'minified(code)';
|
|
||||||
const minifiedMap = {
|
|
||||||
version: 3,
|
|
||||||
file: ['minified'],
|
|
||||||
sources: [],
|
|
||||||
mappings: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
bundler._transformer.minify = jest
|
|
||||||
.fn()
|
|
||||||
.mockReturnValue(Promise.resolve({code: minifiedCode, map: minifiedMap}));
|
|
||||||
|
|
||||||
const result = await bundler.minifyModule(id, code, []);
|
|
||||||
|
|
||||||
expect(result.code).toEqual(minifiedCode);
|
|
||||||
expect(result.map).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('uses new cache layers when transforming if requested to do so', async () => {
|
it('uses new cache layers when transforming if requested to do so', async () => {
|
||||||
const get = jest.fn();
|
const get = jest.fn();
|
||||||
const set = jest.fn();
|
const set = jest.fn();
|
||||||
|
|
|
@ -16,17 +16,13 @@ const {Logger} = require('metro-core');
|
||||||
const debug = require('debug')('Metro:JStransformer');
|
const debug = require('debug')('Metro:JStransformer');
|
||||||
const Worker = require('jest-worker').default;
|
const Worker = require('jest-worker').default;
|
||||||
|
|
||||||
import type {BabelSourceMap} from '@babel/core';
|
|
||||||
import type {Options, TransformedCode} from './JSTransformer/worker';
|
import type {Options, TransformedCode} from './JSTransformer/worker';
|
||||||
import type {LocalPath} from './node-haste/lib/toLocalPath';
|
import type {LocalPath} from './node-haste/lib/toLocalPath';
|
||||||
import type {MetroMinifier} from 'metro-minify-uglify';
|
|
||||||
import type {ResultWithMap} from 'metro-minify-uglify';
|
|
||||||
import type {DynamicRequiresBehavior} from './ModuleGraph/worker/collectDependencies';
|
import type {DynamicRequiresBehavior} from './ModuleGraph/worker/collectDependencies';
|
||||||
|
|
||||||
import typeof {transform as Transform} from './JSTransformer/worker';
|
import typeof {transform as Transform} from './JSTransformer/worker';
|
||||||
|
|
||||||
type WorkerInterface = Worker & {
|
type WorkerInterface = Worker & {
|
||||||
minify: MetroMinifier,
|
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,11 +41,9 @@ module.exports = class Transformer {
|
||||||
_transformModulePath: string;
|
_transformModulePath: string;
|
||||||
_asyncRequireModulePath: string;
|
_asyncRequireModulePath: string;
|
||||||
_dynamicDepsInPackages: DynamicRequiresBehavior;
|
_dynamicDepsInPackages: DynamicRequiresBehavior;
|
||||||
_minifierPath: string;
|
|
||||||
|
|
||||||
constructor(options: {|
|
constructor(options: {|
|
||||||
+maxWorkers: number,
|
+maxWorkers: number,
|
||||||
+minifierPath: string,
|
|
||||||
+reporters: Reporters,
|
+reporters: Reporters,
|
||||||
+transformModulePath: string,
|
+transformModulePath: string,
|
||||||
+asyncRequireModulePath: string,
|
+asyncRequireModulePath: string,
|
||||||
|
@ -59,7 +53,6 @@ module.exports = class Transformer {
|
||||||
this._transformModulePath = options.transformModulePath;
|
this._transformModulePath = options.transformModulePath;
|
||||||
this._asyncRequireModulePath = options.asyncRequireModulePath;
|
this._asyncRequireModulePath = options.asyncRequireModulePath;
|
||||||
this._dynamicDepsInPackages = options.dynamicDepsInPackages;
|
this._dynamicDepsInPackages = options.dynamicDepsInPackages;
|
||||||
this._minifierPath = options.minifierPath;
|
|
||||||
const {workerPath = require.resolve('./JSTransformer/worker')} = options;
|
const {workerPath = require.resolve('./JSTransformer/worker')} = options;
|
||||||
|
|
||||||
if (options.maxWorkers > 1) {
|
if (options.maxWorkers > 1) {
|
||||||
|
@ -90,19 +83,6 @@ module.exports = class Transformer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async minify(
|
|
||||||
filename: string,
|
|
||||||
code: string,
|
|
||||||
sourceMap: BabelSourceMap,
|
|
||||||
): Promise<ResultWithMap> {
|
|
||||||
return await this._worker.minify(
|
|
||||||
filename,
|
|
||||||
code,
|
|
||||||
sourceMap,
|
|
||||||
this._minifierPath,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async transform(
|
async transform(
|
||||||
filename: string,
|
filename: string,
|
||||||
localPath: LocalPath,
|
localPath: LocalPath,
|
||||||
|
@ -111,6 +91,7 @@ module.exports = class Transformer {
|
||||||
options: Options,
|
options: Options,
|
||||||
assetExts: $ReadOnlyArray<string>,
|
assetExts: $ReadOnlyArray<string>,
|
||||||
assetRegistryPath: string,
|
assetRegistryPath: string,
|
||||||
|
minifierPath: string,
|
||||||
): Promise<TransformerResult> {
|
): Promise<TransformerResult> {
|
||||||
try {
|
try {
|
||||||
debug('Started transforming file', filename);
|
debug('Started transforming file', filename);
|
||||||
|
@ -124,6 +105,7 @@ module.exports = class Transformer {
|
||||||
options,
|
options,
|
||||||
assetExts,
|
assetExts,
|
||||||
assetRegistryPath,
|
assetRegistryPath,
|
||||||
|
minifierPath,
|
||||||
this._asyncRequireModulePath,
|
this._asyncRequireModulePath,
|
||||||
this._dynamicDepsInPackages,
|
this._dynamicDepsInPackages,
|
||||||
);
|
);
|
||||||
|
|
|
@ -23,7 +23,6 @@ describe('Transformer', function() {
|
||||||
const opts = {
|
const opts = {
|
||||||
asyncRequireModulePath: 'asyncRequire',
|
asyncRequireModulePath: 'asyncRequire',
|
||||||
maxWorkers: 4,
|
maxWorkers: 4,
|
||||||
minifierPath: defaults.DEFAULT_METRO_MINIFIER_PATH,
|
|
||||||
reporters: {},
|
reporters: {},
|
||||||
transformModulePath,
|
transformModulePath,
|
||||||
dynamicDepsInPackages: 'reject',
|
dynamicDepsInPackages: 'reject',
|
||||||
|
@ -79,6 +78,7 @@ describe('Transformer', function() {
|
||||||
transformOptions,
|
transformOptions,
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
defaults.DEFAULT_METRO_MINIFIER_PATH,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(api.transform).toBeCalledWith(
|
expect(api.transform).toBeCalledWith(
|
||||||
|
@ -90,6 +90,7 @@ describe('Transformer', function() {
|
||||||
transformOptions,
|
transformOptions,
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
defaults.DEFAULT_METRO_MINIFIER_PATH,
|
||||||
'asyncRequire',
|
'asyncRequire',
|
||||||
'reject',
|
'reject',
|
||||||
);
|
);
|
||||||
|
|
|
@ -24,7 +24,11 @@ const path = require('path');
|
||||||
|
|
||||||
const {babylon} = require('../babel-bridge');
|
const {babylon} = require('../babel-bridge');
|
||||||
const {babelGenerate: generate} = require('../babel-bridge');
|
const {babelGenerate: generate} = require('../babel-bridge');
|
||||||
const {toSegmentTuple} = require('metro-source-map');
|
const {
|
||||||
|
fromRawMappings,
|
||||||
|
toBabelSegments,
|
||||||
|
toSegmentTuple,
|
||||||
|
} = require('metro-source-map');
|
||||||
|
|
||||||
import type {DynamicRequiresBehavior} from '../ModuleGraph/worker/collectDependencies';
|
import type {DynamicRequiresBehavior} from '../ModuleGraph/worker/collectDependencies';
|
||||||
import type {LocalPath} from '../node-haste/lib/toLocalPath';
|
import type {LocalPath} from '../node-haste/lib/toLocalPath';
|
||||||
|
@ -124,6 +128,7 @@ async function transformCode(
|
||||||
options: Options,
|
options: Options,
|
||||||
assetExts: $ReadOnlyArray<string>,
|
assetExts: $ReadOnlyArray<string>,
|
||||||
assetRegistryPath: string,
|
assetRegistryPath: string,
|
||||||
|
minifierPath: string,
|
||||||
asyncRequireModulePath: string,
|
asyncRequireModulePath: string,
|
||||||
dynamicDepsInPackages: DynamicRequiresBehavior,
|
dynamicDepsInPackages: DynamicRequiresBehavior,
|
||||||
): Promise<Data> {
|
): Promise<Data> {
|
||||||
|
@ -253,10 +258,27 @@ async function transformCode(
|
||||||
sourceCode,
|
sourceCode,
|
||||||
);
|
);
|
||||||
|
|
||||||
const map = result.rawMappings ? result.rawMappings.map(toSegmentTuple) : [];
|
let map = result.rawMappings ? result.rawMappings.map(toSegmentTuple) : [];
|
||||||
|
let code = result.code;
|
||||||
|
|
||||||
|
if (options.minify) {
|
||||||
|
const sourceMap = fromRawMappings([
|
||||||
|
{code, source: sourceCode, map, path: filename},
|
||||||
|
]).toMap(undefined, {});
|
||||||
|
|
||||||
|
const minified = await minifyCode(
|
||||||
|
filename,
|
||||||
|
result.code,
|
||||||
|
sourceMap,
|
||||||
|
minifierPath,
|
||||||
|
);
|
||||||
|
|
||||||
|
code = minified.code;
|
||||||
|
map = minified.map ? toBabelSegments(minified.map).map(toSegmentTuple) : [];
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
result: {dependencies, code: result.code, map},
|
result: {dependencies, code, map},
|
||||||
sha1,
|
sha1,
|
||||||
transformFileStartLogEntry,
|
transformFileStartLogEntry,
|
||||||
transformFileEndLogEntry,
|
transformFileEndLogEntry,
|
||||||
|
@ -316,6 +338,5 @@ class InvalidRequireCallError extends Error {
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
transform: transformCode,
|
transform: transformCode,
|
||||||
minify: minifyCode,
|
|
||||||
InvalidRequireCallError,
|
InvalidRequireCallError,
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,12 @@
|
||||||
jest
|
jest
|
||||||
.mock('../constant-folding-plugin')
|
.mock('../constant-folding-plugin')
|
||||||
.mock('../inline-plugin')
|
.mock('../inline-plugin')
|
||||||
|
.mock('../../../lib/getMinifier', () => () => ({
|
||||||
|
withSourceMap: (code, map) => ({
|
||||||
|
code: code.replace('arbitrary(code)', 'minified(code)'),
|
||||||
|
map,
|
||||||
|
}),
|
||||||
|
}))
|
||||||
.mock('metro-minify-uglify');
|
.mock('metro-minify-uglify');
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
@ -33,6 +39,7 @@ describe('code transformation worker:', () => {
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
'minifyModulePath',
|
||||||
'asyncRequire',
|
'asyncRequire',
|
||||||
'reject',
|
'reject',
|
||||||
);
|
);
|
||||||
|
@ -61,6 +68,7 @@ describe('code transformation worker:', () => {
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
'minifyModulePath',
|
||||||
'asyncRequire',
|
'asyncRequire',
|
||||||
'reject',
|
'reject',
|
||||||
);
|
);
|
||||||
|
@ -96,6 +104,7 @@ describe('code transformation worker:', () => {
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
'minifyModulePath',
|
||||||
'asyncRequire',
|
'asyncRequire',
|
||||||
'reject',
|
'reject',
|
||||||
);
|
);
|
||||||
|
@ -138,6 +147,7 @@ describe('code transformation worker:', () => {
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
'minifyModulePath',
|
||||||
'asyncRequire',
|
'asyncRequire',
|
||||||
'reject',
|
'reject',
|
||||||
);
|
);
|
||||||
|
@ -181,6 +191,7 @@ describe('code transformation worker:', () => {
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
'minifyModulePath',
|
||||||
'asyncRequire',
|
'asyncRequire',
|
||||||
'reject',
|
'reject',
|
||||||
);
|
);
|
||||||
|
@ -207,8 +218,38 @@ describe('code transformation worker:', () => {
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
'minifyModulePath',
|
||||||
'asyncRequire',
|
'asyncRequire',
|
||||||
'throwAtRuntime',
|
'throwAtRuntime',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('minifies the code correctly', async () => {
|
||||||
|
expect(
|
||||||
|
(await transformCode(
|
||||||
|
'/root/node_modules/bar/file.js',
|
||||||
|
`node_modules/bar/file.js`,
|
||||||
|
'arbitrary(code);',
|
||||||
|
path.join(__dirname, '../../../transformer.js'),
|
||||||
|
false,
|
||||||
|
{
|
||||||
|
dev: true,
|
||||||
|
minify: true,
|
||||||
|
transform: {},
|
||||||
|
enableBabelRCLookup: false,
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
'',
|
||||||
|
'minifyModulePath',
|
||||||
|
'asyncRequire',
|
||||||
|
'throwAtRuntime',
|
||||||
|
)).result.code,
|
||||||
|
).toBe(
|
||||||
|
[
|
||||||
|
'__d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {',
|
||||||
|
' minified(code);',
|
||||||
|
'});',
|
||||||
|
].join('\n'),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,6 @@ const getAbsolutePath = require('./lib/getAbsolutePath');
|
||||||
const getMaxWorkers = require('./lib/getMaxWorkers');
|
const getMaxWorkers = require('./lib/getMaxWorkers');
|
||||||
const getPrependedScripts = require('./lib/getPrependedScripts');
|
const getPrependedScripts = require('./lib/getPrependedScripts');
|
||||||
const mime = require('mime-types');
|
const mime = require('mime-types');
|
||||||
const mapGraph = require('./lib/mapGraph');
|
|
||||||
const nullthrows = require('fbjs/lib/nullthrows');
|
const nullthrows = require('fbjs/lib/nullthrows');
|
||||||
const parseCustomTransformOptions = require('./lib/parseCustomTransformOptions');
|
const parseCustomTransformOptions = require('./lib/parseCustomTransformOptions');
|
||||||
const parsePlatformFilePath = require('./node-haste/lib/parsePlatformFilePath');
|
const parsePlatformFilePath = require('./node-haste/lib/parsePlatformFilePath');
|
||||||
|
@ -263,11 +262,7 @@ class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
async build(options: BundleOptions): Promise<{code: string, map: string}> {
|
async build(options: BundleOptions): Promise<{code: string, map: string}> {
|
||||||
let graphInfo = await this._buildGraph(options);
|
const graphInfo = await this._buildGraph(options);
|
||||||
|
|
||||||
if (options.minify) {
|
|
||||||
graphInfo = await this._minifyGraph(graphInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
const entryPoint = getAbsolutePath(
|
const entryPoint = getAbsolutePath(
|
||||||
options.entryFile,
|
options.entryFile,
|
||||||
|
@ -313,11 +308,7 @@ class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRamBundleInfo(options: BundleOptions): Promise<RamBundleInfo> {
|
async getRamBundleInfo(options: BundleOptions): Promise<RamBundleInfo> {
|
||||||
let graphInfo = await this._buildGraph(options);
|
const graphInfo = await this._buildGraph(options);
|
||||||
|
|
||||||
if (options.minify) {
|
|
||||||
graphInfo = await this._minifyGraph(graphInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
const entryPoint = getAbsolutePath(
|
const entryPoint = getAbsolutePath(
|
||||||
options.entryFile,
|
options.entryFile,
|
||||||
|
@ -450,10 +441,6 @@ class Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.minify) {
|
|
||||||
graphInfo = await this._minifyGraph(graphInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {...graphInfo, numModifiedFiles};
|
return {...graphInfo, numModifiedFiles};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,56 +480,12 @@ class Server {
|
||||||
this._deltaGraphs.set(id, graphInfo);
|
this._deltaGraphs.set(id, graphInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.minify) {
|
|
||||||
// $FlowIssue #16581373 spread of an exact object should be exact
|
|
||||||
delta = {
|
|
||||||
...delta,
|
|
||||||
modified: new Map(
|
|
||||||
await Promise.all(
|
|
||||||
Array.from(delta.modified).map(async ([path, module]) => [
|
|
||||||
path,
|
|
||||||
await this._minifyModule(module),
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...graphInfo,
|
...graphInfo,
|
||||||
delta,
|
delta,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async _minifyGraph(graphInfo: GraphInfo): Promise<GraphInfo> {
|
|
||||||
const prepend = await Promise.all(
|
|
||||||
graphInfo.prepend.map(script => this._minifyModule(script)),
|
|
||||||
);
|
|
||||||
const graph = await mapGraph(graphInfo.graph, module =>
|
|
||||||
this._minifyModule(module),
|
|
||||||
);
|
|
||||||
|
|
||||||
// $FlowIssue #16581373 spread of an exact object should be exact
|
|
||||||
return {...graphInfo, prepend, graph};
|
|
||||||
}
|
|
||||||
|
|
||||||
async _minifyModule(module: Module): Promise<Module> {
|
|
||||||
const {code, map} = await this._bundler.minifyModule(
|
|
||||||
module.path,
|
|
||||||
module.output.code,
|
|
||||||
module.output.map,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...module,
|
|
||||||
output: {
|
|
||||||
...module.output,
|
|
||||||
code,
|
|
||||||
map,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileChange(type: string, filePath: string) {
|
onFileChange(type: string, filePath: string) {
|
||||||
// Make sure the file watcher event runs through the system before
|
// Make sure the file watcher event runs through the system before
|
||||||
// we rebuild the bundles.
|
// we rebuild the bundles.
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
jest
|
jest
|
||||||
.mock('jest-worker', () => ({}))
|
.mock('jest-worker', () => ({}))
|
||||||
.mock('metro-minify-uglify')
|
|
||||||
.mock('crypto')
|
.mock('crypto')
|
||||||
.mock('../symbolicate/symbolicate', () => ({
|
.mock('../symbolicate/symbolicate', () => ({
|
||||||
createWorker: jest.fn().mockReturnValue(jest.fn()),
|
createWorker: jest.fn().mockReturnValue(jest.fn()),
|
||||||
|
@ -169,13 +168,6 @@ describe('processRequest', () => {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
Bundler.prototype.minifyModule = jest.fn().mockReturnValue(
|
|
||||||
Promise.resolve({
|
|
||||||
code: '__d(function(){minified();});',
|
|
||||||
map: [],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
server = new Server(options);
|
server = new Server(options);
|
||||||
requestHandler = server.processRequest.bind(server);
|
requestHandler = server.processRequest.bind(server);
|
||||||
|
|
||||||
|
@ -307,28 +299,6 @@ describe('processRequest', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calculates an incremental minified bundle', async () => {
|
|
||||||
await makeRequest(
|
|
||||||
requestHandler,
|
|
||||||
'mybundle.bundle?runModule=true&minify=true',
|
|
||||||
);
|
|
||||||
|
|
||||||
const response = await makeRequest(
|
|
||||||
requestHandler,
|
|
||||||
'mybundle.bundle?runModule=true&minify=true',
|
|
||||||
);
|
|
||||||
expect(response.statusCode).toEqual(200);
|
|
||||||
expect(response.body).toEqual(
|
|
||||||
[
|
|
||||||
'__d(function(){minified();});',
|
|
||||||
'__d(function(){minified();},0,[1],"mybundle.js");',
|
|
||||||
'__d(function(){minified();},1,[],"foo.js");',
|
|
||||||
'require(0);',
|
|
||||||
'//# sourceMappingURL=http://localhost:8081/mybundle.map?runModule=true&minify=true',
|
|
||||||
].join('\n'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns sourcemap on request of *.map', async () => {
|
it('returns sourcemap on request of *.map', async () => {
|
||||||
const response = await makeRequest(requestHandler, 'mybundle.map');
|
const response = await makeRequest(requestHandler, 'mybundle.map');
|
||||||
|
|
||||||
|
@ -608,29 +578,6 @@ describe('processRequest', () => {
|
||||||
reset: true,
|
reset: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate a minified delta correctly', async () => {
|
|
||||||
const response = await makeRequest(
|
|
||||||
requestHandler,
|
|
||||||
'index.delta?platform=ios&minify=true',
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(JSON.parse(response.body)).toEqual({
|
|
||||||
id: 'XXXXX-0',
|
|
||||||
pre: [[-1, 'function () {require();}']],
|
|
||||||
delta: [
|
|
||||||
[0, '__d(function(){minified();},0,[1],"mybundle.js");'],
|
|
||||||
[1, '__d(function(){minified();},1,[],"foo.js");'],
|
|
||||||
],
|
|
||||||
post: [
|
|
||||||
[
|
|
||||||
2,
|
|
||||||
'//# sourceMappingURL=http://localhost:8081/index.map?platform=ios&minify=true',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
reset: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('/onchange endpoint', () => {
|
describe('/onchange endpoint', () => {
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
/**
|
|
||||||
* 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']);
|
|
||||||
});
|
|
|
@ -1,40 +0,0 @@
|
||||||
/**
|
|
||||||
* 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 {Module} 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: Module => Promise<Module>,
|
|
||||||
): 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