diff --git a/packages/metro-bundler/src/Bundler/index.js b/packages/metro-bundler/src/Bundler/index.js index 1cea4f85..83f06843 100644 --- a/packages/metro-bundler/src/Bundler/index.js +++ b/packages/metro-bundler/src/Bundler/index.js @@ -36,6 +36,7 @@ import type {Options as JSTransformerOptions} from '../JSTransformer/worker'; import type {Reporter} from '../lib/reporting'; import type {TransformCache} from '../lib/TransformCaching'; import type {GlobalTransformCache} from '../lib/GlobalTransformCache'; +import type {PostProcessModules} from '../DeltaBundler'; export type BundlingOptions = {| +preloadedModules: ?{[string]: true} | false, @@ -80,18 +81,6 @@ export type ExtendedAssetDescriptor = AssetDescriptor & { +fileSystemLocation: string, }; -export type PostProcessModulesOptions = {| - dev: boolean, - minify: boolean, - platform: string, -|}; - -export type PostProcessModules = ( - modules: Array, - entryFile: string, - options: PostProcessModulesOptions, -) => Array; - export type PostMinifyProcess = ({ code: string, map: ?MappingsMap, diff --git a/packages/metro-bundler/src/Config.js b/packages/metro-bundler/src/Config.js index 1f13ff75..34a2b431 100644 --- a/packages/metro-bundler/src/Config.js +++ b/packages/metro-bundler/src/Config.js @@ -19,9 +19,9 @@ const {providesModuleNodeModules} = require('./defaults'); import type { GetTransformOptions, PostMinifyProcess, - PostProcessModules, PostProcessBundleSourcemap, } from './Bundler'; +import type {PostProcessModules} from './DeltaBundler'; import type {PostProcessModules as PostProcessModulesForBuck} from './ModuleGraph/types.flow.js'; import type {TransformVariants} from './ModuleGraph/types.flow'; import type {HasteImpl} from './node-haste/Module'; diff --git a/packages/metro-bundler/src/DeltaBundler/DeltaPatcher.js b/packages/metro-bundler/src/DeltaBundler/DeltaPatcher.js index cd3eaf2c..066c4db1 100644 --- a/packages/metro-bundler/src/DeltaBundler/DeltaPatcher.js +++ b/packages/metro-bundler/src/DeltaBundler/DeltaPatcher.js @@ -95,10 +95,14 @@ class DeltaPatcher { return this._lastModifiedDate; } - getAllModules(): Array { + getAllModules( + modifierFn: ( + modules: $ReadOnlyArray, + ) => $ReadOnlyArray = modules => modules, + ): $ReadOnlyArray { return [].concat( Array.from(this._lastBundle.pre.values()), - Array.from(this._lastBundle.modules.values()), + modifierFn(Array.from(this._lastBundle.modules.values())), Array.from(this._lastBundle.post.values()), ); } diff --git a/packages/metro-bundler/src/DeltaBundler/DeltaTransformer.js b/packages/metro-bundler/src/DeltaBundler/DeltaTransformer.js index e5d8ce36..b11c87b3 100644 --- a/packages/metro-bundler/src/DeltaBundler/DeltaTransformer.js +++ b/packages/metro-bundler/src/DeltaBundler/DeltaTransformer.js @@ -23,7 +23,7 @@ import type {Options as JSTransformerOptions} from '../JSTransformer/worker'; import type Resolver from '../Resolver'; import type {CompactRawMappings} from '../lib/SourceMap'; import type Module from '../node-haste/Module'; -import type {Options as BundleOptions} from './'; +import type {Options as BundleOptions, MainOptions} from './'; import type {DependencyEdges} from './traverseDependencies'; export type DeltaEntryType = @@ -56,11 +56,6 @@ export type DeltaTransformResponse = {| +reset: boolean, |}; -type Options = {| - +getPolyfills: ({platform: ?string}) => $ReadOnlyArray, - +polyfillModuleNames: $ReadOnlyArray, -|}; - const globalCreateModuleId = createModuleIdFactory(); /** @@ -94,7 +89,7 @@ class DeltaTransformer extends EventEmitter { bundler: Bundler, resolver: Resolver, deltaCalculator: DeltaCalculator, - options: Options, + options: MainOptions, bundleOptions: BundleOptions, ) { super(); @@ -122,7 +117,7 @@ class DeltaTransformer extends EventEmitter { static async create( bundler: Bundler, - options: Options, + options: MainOptions, bundleOptions: BundleOptions, ): Promise { const resolver = await bundler.getResolver(); diff --git a/packages/metro-bundler/src/DeltaBundler/Serializers.js b/packages/metro-bundler/src/DeltaBundler/Serializers.js index b96fd9b9..f7217bb8 100644 --- a/packages/metro-bundler/src/DeltaBundler/Serializers.js +++ b/packages/metro-bundler/src/DeltaBundler/Serializers.js @@ -76,14 +76,12 @@ async function fullSourceMap( deltaBundler: DeltaBundler, options: Options, ): Promise { - const {id, delta} = await _build(deltaBundler, { + const {modules} = await _getAllModules(deltaBundler, { ...options, wrapModules: true, }); - const deltaPatcher = DeltaPatcher.get(id).applyDelta(delta); - - return fromRawMappings(deltaPatcher.getAllModules()).toString(undefined, { + return fromRawMappings(modules).toString(undefined, { excludeSource: options.excludeSource, }); } @@ -92,14 +90,12 @@ async function fullSourceMapObject( deltaBundler: DeltaBundler, options: Options, ): Promise { - const {id, delta} = await _build(deltaBundler, { + const {modules} = await _getAllModules(deltaBundler, { ...options, wrapModules: true, }); - const deltaPatcher = DeltaPatcher.get(id).applyDelta(delta); - - return fromRawMappings(deltaPatcher.getAllModules()).toMap(undefined, { + return fromRawMappings(modules).toMap(undefined, { excludeSource: options.excludeSource, }); } @@ -111,18 +107,17 @@ async function fullBundle( deltaBundler: DeltaBundler, options: Options, ): Promise<{bundle: string, numModifiedFiles: number, lastModified: Date}> { - const {id, delta} = await _build(deltaBundler, { - ...options, - wrapModules: true, - }); + const {modules, numModifiedFiles, lastModified} = await _getAllModules( + deltaBundler, + options, + ); - const deltaPatcher = DeltaPatcher.get(id).applyDelta(delta); - const code = deltaPatcher.getAllModules().map(m => m.code); + const code = modules.map(m => m.code); return { bundle: code.join('\n'), - lastModified: deltaPatcher.getLastModifiedDate(), - numModifiedFiles: deltaPatcher.getLastNumModifiedFiles(), + lastModified, + numModifiedFiles, }; } @@ -130,43 +125,62 @@ async function getAllModules( deltaBundler: DeltaBundler, options: Options, ): Promise<$ReadOnlyArray> { - const {id, delta} = await _build(deltaBundler, { + const {modules} = await _getAllModules(deltaBundler, { ...options, wrapModules: true, }); - return DeltaPatcher.get(id) + return modules; +} + +async function _getAllModules( + deltaBundler: DeltaBundler, + options: Options, +): Promise<{ + modules: $ReadOnlyArray, + numModifiedFiles: number, + lastModified: Date, + deltaTransformer: DeltaTransformer, +}> { + const {id, delta, deltaTransformer} = await _build(deltaBundler, { + ...options, + wrapModules: true, + }); + + const deltaPatcher = DeltaPatcher.get(id); + + const modules = deltaPatcher .applyDelta(delta) - .getAllModules(); + .getAllModules(deltaBundler.getPostProcessModulesFn(options.entryFile)); + + return { + deltaTransformer, + lastModified: deltaPatcher.getLastModifiedDate(), + modules, + numModifiedFiles: deltaPatcher.getLastNumModifiedFiles(), + }; } async function getRamBundleInfo( deltaBundler: DeltaBundler, options: Options, ): Promise { - const {id, delta, deltaTransformer} = await _build(deltaBundler, { + const {modules, deltaTransformer} = await _getAllModules(deltaBundler, { ...options, wrapModules: true, }); - const modules = DeltaPatcher.get(id) - .applyDelta(delta) - .getAllModules() - .map(module => { - const map = fromRawMappings([module]).toMap(module.path, { - excludeSource: options.excludeSource, - }); - - return { - id: module.id, - code: module.code, - map, - name: module.name, - sourcePath: module.path, - source: module.source, - type: module.type, - }; - }); + const ramModules = modules.map(module => ({ + id: module.id, + code: module.code, + map: fromRawMappings([module]).toMap(module.path, { + excludeSource: options.excludeSource, + }), + name: module.name, + sourcePath: module.path, + source: module.source, + type: module.type, + })); const { preloadedModules, @@ -178,7 +192,7 @@ async function getRamBundleInfo( const startupModules = []; const lazyModules = []; - modules.forEach(module => { + ramModules.forEach(module => { if (preloadedModules.hasOwnProperty(module.sourcePath)) { startupModules.push(module); return; @@ -226,7 +240,7 @@ async function getAssets( deltaBundler: DeltaBundler, options: Options, ): Promise<$ReadOnlyArray> { - const modules = await getAllModules(deltaBundler, options); + const {modules} = await _getAllModules(deltaBundler, options); const assets = await Promise.all( modules.map(async module => { diff --git a/packages/metro-bundler/src/DeltaBundler/__tests__/Serializers-test.js b/packages/metro-bundler/src/DeltaBundler/__tests__/Serializers-test.js index cb2edca7..9331f69b 100644 --- a/packages/metro-bundler/src/DeltaBundler/__tests__/Serializers-test.js +++ b/packages/metro-bundler/src/DeltaBundler/__tests__/Serializers-test.js @@ -21,6 +21,7 @@ describe('Serializers', () => { const getDelta = jest.fn(); const getDependenciesFn = jest.fn(); const getRamOptions = jest.fn(); + const postProcessModules = jest.fn(); let deltaBundler; const deltaResponse = { @@ -47,6 +48,7 @@ describe('Serializers', () => { ramGroups: [], }), ); + postProcessModules.mockImplementation(modules => modules); deltaBundler = { async getDeltaTransformer() { @@ -66,6 +68,9 @@ describe('Serializers', () => { }, }; }, + getPostProcessModulesFn() { + return postProcessModules; + }, }; setCurrentTime(CURRENT_TIME); @@ -253,4 +258,18 @@ describe('Serializers', () => { }), ).toMatchSnapshot(); }); + + it('should post-process the modules', async () => { + postProcessModules.mockImplementation(modules => { + return modules.sort( + (a, b) => +(a.path < b.path) || +(a.path === b.path) - 1, + ); + }); + + expect( + await Serializers.getAllModules(deltaBundler, { + deltaBundleId: 10, + }), + ).toMatchSnapshot(); + }); }); diff --git a/packages/metro-bundler/src/DeltaBundler/__tests__/__snapshots__/Serializers-test.js.snap b/packages/metro-bundler/src/DeltaBundler/__tests__/__snapshots__/Serializers-test.js.snap index b0d6d1e0..bcb7cdc5 100644 --- a/packages/metro-bundler/src/DeltaBundler/__tests__/__snapshots__/Serializers-test.js.snap +++ b/packages/metro-bundler/src/DeltaBundler/__tests__/__snapshots__/Serializers-test.js.snap @@ -28,6 +28,35 @@ exports[`Serializers should build the full Source Maps 1`] = `"{\\"version\\":3, exports[`Serializers should build the full Source Maps 2`] = `"{\\"version\\":3,\\"sources\\":[],\\"sourcesContent\\":[],\\"names\\":[],\\"mappings\\":\\"\\"}"`; +exports[`Serializers should post-process the modules 1`] = ` +Array [ + Object { + "code": "pre;", + "id": 1, + "path": "/pre.js", + "type": "script", + }, + Object { + "code": "another;", + "id": 4, + "path": "/4.js", + "type": "module", + }, + Object { + "code": "module3;", + "id": 3, + "path": "/3.js", + "type": "module", + }, + Object { + "code": "post;", + "id": 2, + "path": "/p", + "type": "require", + }, +] +`; + exports[`Serializers should return all the bundle modules 1`] = ` Array [ Object { diff --git a/packages/metro-bundler/src/DeltaBundler/index.js b/packages/metro-bundler/src/DeltaBundler/index.js index 19547471..462bf024 100644 --- a/packages/metro-bundler/src/DeltaBundler/index.js +++ b/packages/metro-bundler/src/DeltaBundler/index.js @@ -16,10 +16,17 @@ const DeltaTransformer = require('./DeltaTransformer'); import type Bundler from '../Bundler'; import type {BundleOptions} from '../Server'; +import type {DeltaEntry} from './DeltaTransformer'; -type MainOptions = {| +export type PostProcessModules = ( + modules: $ReadOnlyArray, + entryFile: string, +) => $ReadOnlyArray; + +export type MainOptions = {| getPolyfills: ({platform: ?string}) => $ReadOnlyArray, polyfillModuleNames: $ReadOnlyArray, + postProcessModules?: PostProcessModules, |}; export type Options = BundleOptions & { @@ -83,6 +90,18 @@ class DeltaBundler { id: bundleId, }; } + + getPostProcessModulesFn( + entryPoint: string, + ): (modules: $ReadOnlyArray) => $ReadOnlyArray { + const postProcessFn = this._options.postProcessModules; + + if (!postProcessFn) { + return modules => modules; + } + + return entries => postProcessFn(entries, entryPoint); + } } module.exports = DeltaBundler; diff --git a/packages/metro-bundler/src/Server/index.js b/packages/metro-bundler/src/Server/index.js index 4f73c714..d0c22018 100644 --- a/packages/metro-bundler/src/Server/index.js +++ b/packages/metro-bundler/src/Server/index.js @@ -36,7 +36,6 @@ import type {Reporter} from '../lib/reporting'; import type {Options as DeltaBundlerOptions} from '../DeltaBundler/Serializers'; import type { GetTransformOptions, - PostProcessModules, PostMinifyProcess, PostProcessBundleSourcemap, } from '../Bundler'; @@ -45,7 +44,7 @@ import type {GlobalTransformCache} from '../lib/GlobalTransformCache'; import type {SourceMap, Symbolicate} from './symbolicate'; import type {AssetData} from '../AssetServer'; import type {RamBundleInfo} from '../DeltaBundler/Serializers'; - +import type {PostProcessModules} from '../DeltaBundler'; const { createActionStartEntry, createActionEndEntry, @@ -242,6 +241,7 @@ class Server { this._deltaBundler = new DeltaBundler(this._bundler, { getPolyfills: this._opts.getPolyfills, polyfillModuleNames: this._opts.polyfillModuleNames, + postProcessModules: this._opts.postProcessModules, }); }