diff --git a/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap b/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap index a0b141e518..79af065e25 100644 --- a/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap +++ b/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap @@ -90,6 +90,7 @@ Object { "dynamicDepsInPackages": "throwAtRuntime", "enableBabelRCLookup": true, "enableBabelRuntime": true, + "experimentalImportBundleSupport": false, "getTransformOptions": [Function], "minifierConfig": Object { "compress": Object { @@ -217,6 +218,7 @@ Object { "dynamicDepsInPackages": "throwAtRuntime", "enableBabelRCLookup": true, "enableBabelRuntime": true, + "experimentalImportBundleSupport": false, "getTransformOptions": [Function], "minifierConfig": Object { "compress": Object { diff --git a/packages/metro-config/src/configTypes.flow.js b/packages/metro-config/src/configTypes.flow.js index c6385c6090..1537310d82 100644 --- a/packages/metro-config/src/configTypes.flow.js +++ b/packages/metro-config/src/configTypes.flow.js @@ -139,6 +139,7 @@ type TransformerConfigT = {| transformVariants: TransformVariants, workerPath: string, publicPath: string, + experimentalImportBundleSupport: boolean, |}; export type VisualizerConfigT = {| diff --git a/packages/metro-config/src/convertConfig.js b/packages/metro-config/src/convertConfig.js index 9aa795f886..7a6fea236f 100644 --- a/packages/metro-config/src/convertConfig.js +++ b/packages/metro-config/src/convertConfig.js @@ -134,6 +134,7 @@ async function convertOldToNew({ dynamicDepsInPackages, enableBabelRCLookup: getEnableBabelRCLookup(), enableBabelRuntime: true, + experimentalImportBundleSupport: false, getTransformOptions, minifierConfig: defaultConfig.transformer.minifierConfig, minifierPath: minifierPath || defaultConfig.transformer.minifierPath, diff --git a/packages/metro-config/src/defaults/index.js b/packages/metro-config/src/defaults/index.js index 96182d8c05..d1db6b3f13 100644 --- a/packages/metro-config/src/defaults/index.js +++ b/packages/metro-config/src/defaults/index.js @@ -72,6 +72,7 @@ const getDefaultValues = (projectRoot: ?string): ConfigT => ({ dynamicDepsInPackages: 'throwAtRuntime', enableBabelRCLookup: true, enableBabelRuntime: true, + experimentalImportBundleSupport: false, getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, diff --git a/packages/metro-visualizer/src/middleware/graph-api/testGraph.js b/packages/metro-visualizer/src/middleware/graph-api/testGraph.js index 0ded858564..aed7c1c57a 100644 --- a/packages/metro-visualizer/src/middleware/graph-api/testGraph.js +++ b/packages/metro-visualizer/src/middleware/graph-api/testGraph.js @@ -152,6 +152,7 @@ const dummyMetroGraph: Graph<> = { ], ]), entryPoints: ['foo'], + importBundleNames: new Set(), }; module.exports = dummyMetroGraph; diff --git a/packages/metro/src/DeltaBundler/DeltaCalculator.js b/packages/metro/src/DeltaBundler/DeltaCalculator.js index 9ca6f95f71..8684375240 100644 --- a/packages/metro/src/DeltaBundler/DeltaCalculator.js +++ b/packages/metro/src/DeltaBundler/DeltaCalculator.js @@ -49,6 +49,7 @@ class DeltaCalculator extends EventEmitter { this._graph = { dependencies: new Map(), entryPoints, + importBundleNames: new Set(), }; this._dependencyGraph @@ -70,6 +71,7 @@ class DeltaCalculator extends EventEmitter { this._graph = { dependencies: new Map(), entryPoints: this._graph.entryPoints, + importBundleNames: new Set(), }; this._modifiedFiles = new Set(); this._deletedFiles = new Set(); diff --git a/packages/metro/src/DeltaBundler/Serializers/__tests__/baseJSBundle-test.js b/packages/metro/src/DeltaBundler/Serializers/__tests__/baseJSBundle-test.js index f919565f53..4cdcdfc421 100644 --- a/packages/metro/src/DeltaBundler/Serializers/__tests__/baseJSBundle-test.js +++ b/packages/metro/src/DeltaBundler/Serializers/__tests__/baseJSBundle-test.js @@ -62,6 +62,7 @@ it('should generate a very simple bundle', () => { ['/root/bar', barModule], ]), entryPoints: ['foo'], + importBundleNames: new Set(), }, { processModuleFilter: () => true, @@ -75,22 +76,22 @@ it('should generate a very simple bundle', () => { }, ), ).toMatchInlineSnapshot(` -Object { - "modules": Array [ - Array [ - "foo", - "__d(function() {/* code for foo */},\\"foo\\",[\\"bar\\"],\\"foo\\");", - ], - Array [ - "bar", - "__d(function() {/* code for bar */},\\"bar\\",[],\\"bar\\");", - ], - ], - "post": "require(\\"foo\\"); -//# sourceMappingURL=http://localhost/bundle.map", - "pre": "__d(function() {/* code for polyfill */});", -} -`); + Object { + "modules": Array [ + Array [ + "foo", + "__d(function() {/* code for foo */},\\"foo\\",[\\"bar\\"],\\"foo\\");", + ], + Array [ + "bar", + "__d(function() {/* code for bar */},\\"bar\\",[],\\"bar\\");", + ], + ], + "post": "require(\\"foo\\"); + //# sourceMappingURL=http://localhost/bundle.map", + "pre": "__d(function() {/* code for polyfill */});", + } + `); }); it('should add runBeforeMainModule statements if found in the graph', () => { @@ -104,6 +105,7 @@ it('should add runBeforeMainModule statements if found in the graph', () => { ['/root/bar', barModule], ]), entryPoints: ['/root/foo'], + importBundleNames: new Set(), }, { processModuleFilter: () => true, @@ -117,10 +119,10 @@ it('should add runBeforeMainModule statements if found in the graph', () => { }, ).post, ).toMatchInlineSnapshot(` -"require(\\"bar\\"); -require(\\"foo\\"); -//# sourceMappingURL=http://localhost/bundle.map" -`); + "require(\\"bar\\"); + require(\\"foo\\"); + //# sourceMappingURL=http://localhost/bundle.map" + `); }); it('should handle numeric module ids', () => { @@ -134,6 +136,7 @@ it('should handle numeric module ids', () => { ['/root/bar', barModule], ]), entryPoints: ['/root/foo'], + importBundleNames: new Set(), }, { processModuleFilter: () => true, @@ -147,17 +150,17 @@ it('should handle numeric module ids', () => { }, ).modules, ).toMatchInlineSnapshot(` -Array [ - Array [ - 0, - "__d(function() {/* code for foo */},0,[1],\\"foo\\");", - ], - Array [ - 1, - "__d(function() {/* code for bar */},1,[],\\"bar\\");", - ], -] -`); + Array [ + Array [ + 0, + "__d(function() {/* code for foo */},0,[1],\\"foo\\");", + ], + Array [ + 1, + "__d(function() {/* code for bar */},1,[],\\"bar\\");", + ], + ] + `); }); it('outputs custom runModule statements', () => { @@ -171,6 +174,7 @@ it('outputs custom runModule statements', () => { ['/root/bar', barModule], ]), entryPoints: ['/root/foo'], + importBundleNames: new Set(), }, { processModuleFilter: () => true, @@ -184,9 +188,9 @@ it('outputs custom runModule statements', () => { }, ).post, ).toMatchInlineSnapshot(` -"export default require(\\"bar\\").default; -export default require(\\"foo\\").default;" -`); + "export default require(\\"bar\\").default; + export default require(\\"foo\\").default;" + `); }); it('should add an inline source map to a very simple bundle', () => { @@ -199,6 +203,7 @@ it('should add an inline source map to a very simple bundle', () => { ['/root/bar', barModule], ]), entryPoints: ['foo'], + importBundleNames: new Set(), }, { processModuleFilter: () => true, @@ -241,6 +246,7 @@ it('does not add polyfills when `modulesOnly` is used', () => { ['/root/bar', barModule], ]), entryPoints: ['foo'], + importBundleNames: new Set(), }, { processModuleFilter: () => true, @@ -255,20 +261,65 @@ it('does not add polyfills when `modulesOnly` is used', () => { }, ), ).toMatchInlineSnapshot(` -Object { - "modules": Array [ - Array [ - "foo", - "__d(function() {/* code for foo */},\\"foo\\",[\\"bar\\"],\\"foo\\");", - ], - Array [ - "bar", - "__d(function() {/* code for bar */},\\"bar\\",[],\\"bar\\");", - ], - ], - "post": "require(\\"foo\\"); -//# sourceMappingURL=http://localhost/bundle.map", - "pre": "", -} -`); + Object { + "modules": Array [ + Array [ + "foo", + "__d(function() {/* code for foo */},\\"foo\\",[\\"bar\\"],\\"foo\\");", + ], + Array [ + "bar", + "__d(function() {/* code for bar */},\\"bar\\",[],\\"bar\\");", + ], + ], + "post": "require(\\"foo\\"); + //# sourceMappingURL=http://localhost/bundle.map", + "pre": "", + } + `); +}); + +it('adds lazy imports at the end of a bundle', () => { + expect( + baseJSBundle( + '/root/foo', + [polyfill], + { + dependencies: new Map([ + ['/root/foo', fooModule], + ['/root/bar', barModule], + ]), + entryPoints: ['foo'], + importBundleNames: new Set(['/path/to/async/module.js']), + }, + { + asyncRequireModulePath: '/asyncRequire.js', + processModuleFilter: () => true, + createModuleId: filePath => path.basename(filePath), + dev: true, + getRunModuleStatement, + projectRoot: '/root', + runBeforeMainModule: [], + runModule: true, + sourceMapUrl: 'http://localhost/bundle.map', + }, + ), + ).toMatchInlineSnapshot(` + Object { + "modules": Array [ + Array [ + "foo", + "__d(function() {/* code for foo */},\\"foo\\",[\\"bar\\"],\\"foo\\");", + ], + Array [ + "bar", + "__d(function() {/* code for bar */},\\"bar\\",[],\\"bar\\");", + ], + ], + "post": "(function(){var $$=require(\\"asyncRequire.js\\");$$.addImportBundleNames({\\"module.js\\":\\"../path/to/async/module.bundle\\"})})(); + require(\\"foo\\"); + //# sourceMappingURL=http://localhost/bundle.map", + "pre": "__d(function() {/* code for polyfill */});", + } + `); }); diff --git a/packages/metro/src/DeltaBundler/Serializers/__tests__/deltaJSBundle-test.js b/packages/metro/src/DeltaBundler/Serializers/__tests__/deltaJSBundle-test.js index 3a85b88cb0..8c6a6a3ac3 100644 --- a/packages/metro/src/DeltaBundler/Serializers/__tests__/deltaJSBundle-test.js +++ b/packages/metro/src/DeltaBundler/Serializers/__tests__/deltaJSBundle-test.js @@ -38,6 +38,7 @@ const graph = { createModule('bar', []), ]), entryPoints: ['/root/entrypoint.js'], + importBundleNames: new Set(), }; const options = { diff --git a/packages/metro/src/DeltaBundler/Serializers/__tests__/getRamBundleInfo-test.js b/packages/metro/src/DeltaBundler/Serializers/__tests__/getRamBundleInfo-test.js index f7a0a72c0b..0006115e56 100644 --- a/packages/metro/src/DeltaBundler/Serializers/__tests__/getRamBundleInfo-test.js +++ b/packages/metro/src/DeltaBundler/Serializers/__tests__/getRamBundleInfo-test.js @@ -39,6 +39,7 @@ const graph = { createModule('bar', []), createModule('qux', []), ]), + importBundleNames: new Set(), }; const pre = [createModule('pre', [], 'js/script')[1]]; diff --git a/packages/metro/src/DeltaBundler/Serializers/baseJSBundle.js b/packages/metro/src/DeltaBundler/Serializers/baseJSBundle.js index 20491825c6..8160d07a0e 100644 --- a/packages/metro/src/DeltaBundler/Serializers/baseJSBundle.js +++ b/packages/metro/src/DeltaBundler/Serializers/baseJSBundle.js @@ -53,14 +53,21 @@ function baseJSBundle( ); const postCode = processModules( - getAppendScripts(entryPoint, [...preModules, ...modules], { - createModuleId: options.createModuleId, - getRunModuleStatement: options.getRunModuleStatement, - runBeforeMainModule: options.runBeforeMainModule, - runModule: options.runModule, - sourceMapUrl: options.sourceMapUrl, - inlineSourceMap: options.inlineSourceMap, - }), + getAppendScripts( + entryPoint, + [...preModules, ...modules], + graph.importBundleNames, + { + asyncRequireModulePath: options.asyncRequireModulePath, + createModuleId: options.createModuleId, + getRunModuleStatement: options.getRunModuleStatement, + inlineSourceMap: options.inlineSourceMap, + projectRoot: options.projectRoot, + runBeforeMainModule: options.runBeforeMainModule, + runModule: options.runModule, + sourceMapUrl: options.sourceMapUrl, + }, + ), processModulesOptions, ) .map(([_, code]) => code) diff --git a/packages/metro/src/DeltaBundler/Serializers/deltaJSBundle.js b/packages/metro/src/DeltaBundler/Serializers/deltaJSBundle.js index 4553d5fe75..14fcbcb118 100644 --- a/packages/metro/src/DeltaBundler/Serializers/deltaJSBundle.js +++ b/packages/metro/src/DeltaBundler/Serializers/deltaJSBundle.js @@ -54,6 +54,7 @@ function deltaJSBundle( const appendScripts = getAppendScripts( entryPoint, [...pre, ...modules], + graph.importBundleNames, options, ); diff --git a/packages/metro/src/DeltaBundler/Serializers/getRamBundleInfo.js b/packages/metro/src/DeltaBundler/Serializers/getRamBundleInfo.js index 244c5ac6ae..c120d37196 100644 --- a/packages/metro/src/DeltaBundler/Serializers/getRamBundleInfo.js +++ b/packages/metro/src/DeltaBundler/Serializers/getRamBundleInfo.js @@ -50,7 +50,9 @@ async function getRamBundleInfo( ...pre, ...graph.dependencies.values(), ]; - modules = modules.concat(getAppendScripts(entryPoint, modules, options)); + modules = modules.concat( + getAppendScripts(entryPoint, modules, graph.importBundleNames, options), + ); modules.forEach((module: Module<>) => options.createModuleId(module.path)); diff --git a/packages/metro/src/DeltaBundler/traverseDependencies.js b/packages/metro/src/DeltaBundler/traverseDependencies.js index 9ef24844f7..8cff933318 100644 --- a/packages/metro/src/DeltaBundler/traverseDependencies.js +++ b/packages/metro/src/DeltaBundler/traverseDependencies.js @@ -39,21 +39,24 @@ type Delta = $ReadOnly<{| |}>; type InternalOptions = $ReadOnly<{| - resolve: $PropertyType, 'resolve'>, - transform: $PropertyType, 'transform'>, + experimentalImportBundleSupport: boolean, onDependencyAdd: () => mixed, onDependencyAdded: () => mixed, + resolve: $PropertyType, 'resolve'>, + transform: $PropertyType, 'transform'>, |}>; function getInternalOptions({ transform, resolve, onProgress, + experimentalImportBundleSupport, }: Options): InternalOptions { let numProcessed = 0; let total = 0; return { + experimentalImportBundleSupport, transform, resolve, onDependencyAdd: () => onProgress && onProgress(numProcessed, ++total), @@ -229,7 +232,12 @@ async function processModule( const promises = []; for (const [relativePath, dependency] of currentDependencies) { - if (!previousDependencies.has(relativePath)) { + if ( + options.experimentalImportBundleSupport && + dependency.data.data.isAsync + ) { + graph.importBundleNames.add(dependency.absolutePath); + } else if (!previousDependencies.has(relativePath)) { promises.push( addDependency(module, dependency.absolutePath, graph, delta, options), ); @@ -369,7 +377,11 @@ function reorderDependencies( const childModule = graph.dependencies.get(path); if (!childModule) { - throw new ReferenceError('Module not registered in graph: ' + path); + if (dependency.data.data.isAsync) { + return; + } else { + throw new ReferenceError('Module not registered in graph: ' + path); + } } reorderDependencies(graph, childModule, orderedDependencies); diff --git a/packages/metro/src/DeltaBundler/types.flow.js b/packages/metro/src/DeltaBundler/types.flow.js index bc0e5d98b0..77a8343122 100644 --- a/packages/metro/src/DeltaBundler/types.flow.js +++ b/packages/metro/src/DeltaBundler/types.flow.js @@ -54,6 +54,7 @@ export type Module = {| export type Graph = {| dependencies: Map>, + importBundleNames: Set, +entryPoints: $ReadOnlyArray, |}; @@ -75,6 +76,7 @@ export type Options = {| +resolve: (from: string, to: string) => string, +transform: TransformFn, +onProgress: ?(numProcessed: number, total: number) => mixed, + +experimentalImportBundleSupport: boolean, |}; export type DeltaResult = {| @@ -85,6 +87,7 @@ export type DeltaResult = {| |}; export type SerializerOptions = {| + +asyncRequireModulePath: string, +createModuleId: string => number, +dev: boolean, +getRunModuleStatement: (number | string) => string, diff --git a/packages/metro/src/IncrementalBundler.js b/packages/metro/src/IncrementalBundler.js index dc90426055..379a112dc8 100644 --- a/packages/metro/src/IncrementalBundler.js +++ b/packages/metro/src/IncrementalBundler.js @@ -129,6 +129,8 @@ class IncrementalBundler { transformOptions, ), onProgress: otherOptions.onProgress, + experimentalImportBundleSupport: this._config.transformer + .experimentalImportBundleSupport, }); this._config.serializer.experimentalSerializerHook(graph, { diff --git a/packages/metro/src/JSTransformer/worker.js b/packages/metro/src/JSTransformer/worker.js index 380e816901..8bb32ebbc0 100644 --- a/packages/metro/src/JSTransformer/worker.js +++ b/packages/metro/src/JSTransformer/worker.js @@ -61,6 +61,7 @@ export type JsTransformerConfig = $ReadOnly<{| dynamicDepsInPackages: DynamicRequiresBehavior, enableBabelRCLookup: boolean, enableBabelRuntime: boolean, + experimentalImportBundleSupport: boolean, minifierConfig: MinifierConfig, minifierPath: string, optimizationSizeLimit: number, diff --git a/packages/metro/src/Server.js b/packages/metro/src/Server.js index 4b9be54cd3..966e0f9c0c 100644 --- a/packages/metro/src/Server.js +++ b/packages/metro/src/Server.js @@ -194,6 +194,7 @@ class Server { const entryPoint = path.resolve(this._config.projectRoot, entryFile); const bundle = baseJSBundle(entryPoint, prepend, graph, { + asyncRequireModulePath: this._config.transformer.asyncRequireModulePath, processModuleFilter: this._config.serializer.processModuleFilter, createModuleId: this._createModuleId, getRunModuleStatement: this._config.serializer.getRunModuleStatement, @@ -234,6 +235,7 @@ class Server { const entryPoint = path.resolve(this._config.projectRoot, entryFile); return await getRamBundleInfo(entryPoint, prepend, graph, { + asyncRequireModulePath: this._config.transformer.asyncRequireModulePath, processModuleFilter: this._config.serializer.processModuleFilter, createModuleId: this._createModuleId, dev: transformOptions.dev, @@ -652,6 +654,8 @@ class Server { revision.id, revision.graph, { + asyncRequireModulePath: this._config.transformer + .asyncRequireModulePath, processModuleFilter: this._config.serializer.processModuleFilter, createModuleId: this._createModuleId, dev: transformOptions.dev, @@ -731,6 +735,7 @@ class Server { ((...args) => bundleToString(baseJSBundle(...args)).code); const bundle = serializer(entryFile, revision.prepend, revision.graph, { + asyncRequireModulePath: this._config.transformer.asyncRequireModulePath, processModuleFilter: this._config.serializer.processModuleFilter, createModuleId: this._createModuleId, getRunModuleStatement: this._config.serializer.getRunModuleStatement, @@ -873,6 +878,7 @@ class Server { } const base = baseJSBundle(entryFile, revision.prepend, revision.graph, { + asyncRequireModulePath: this._config.transformer.asyncRequireModulePath, processModuleFilter: this._config.serializer.processModuleFilter, createModuleId: this._createModuleId, getRunModuleStatement: this._config.serializer.getRunModuleStatement, diff --git a/packages/metro/src/Server/__tests__/Server-test.js b/packages/metro/src/Server/__tests__/Server-test.js index e29069a9ab..96c8ad8cce 100644 --- a/packages/metro/src/Server/__tests__/Server-test.js +++ b/packages/metro/src/Server/__tests__/Server-test.js @@ -153,6 +153,7 @@ describe('processRequest', () => { const graph = { entryPoints: ['/root/mybundle.js'], dependencies, + importBundleNames: new Set(), }; currentGraphs.add(graph); @@ -392,9 +393,10 @@ describe('processRequest', () => { expect(DeltaBundler.prototype.buildGraph).toBeCalledWith( ['/root/index.js'], { + experimentalImportBundleSupport: false, + onProgress: expect.any(Function), resolve: expect.any(Function), transform: expect.any(Function), - onProgress: expect.any(Function), }, ); }); @@ -710,9 +712,10 @@ describe('processRequest', () => { expect(DeltaBundler.prototype.buildGraph).toBeCalledWith( ['/root/foo file'], { + experimentalImportBundleSupport: false, + onProgress: null, resolve: expect.any(Function), transform: expect.any(Function), - onProgress: null, }, ); }); diff --git a/packages/metro/src/lib/getAppendScripts.js b/packages/metro/src/lib/getAppendScripts.js index 6ffff05ffb..8626467076 100644 --- a/packages/metro/src/lib/getAppendScripts.js +++ b/packages/metro/src/lib/getAppendScripts.js @@ -12,26 +12,58 @@ const getInlineSourceMappingURL = require('../DeltaBundler/Serializers/helpers/getInlineSourceMappingURL'); const nullthrows = require('nullthrows'); +const path = require('path'); const sourceMapString = require('../DeltaBundler/Serializers/sourceMapString'); import type {Module} from '../DeltaBundler'; type Options = { + +asyncRequireModulePath: string, +createModuleId: string => T, +getRunModuleStatement: T => string, + +inlineSourceMap: ?boolean, + +projectRoot: string, +runBeforeMainModule: $ReadOnlyArray, +runModule: boolean, +sourceMapUrl: ?string, - +inlineSourceMap: ?boolean, }; function getAppendScripts( entryPoint: string, modules: $ReadOnlyArray>, + importBundleNames: Set, options: Options, ): $ReadOnlyArray> { const output = []; + if (importBundleNames.size) { + const importBundleNamesObject = Object.create(null); + importBundleNames.forEach(absolutePath => { + const bundlePath = path.relative(options.projectRoot, absolutePath); + importBundleNamesObject[options.createModuleId(absolutePath)] = + bundlePath.slice(0, -path.extname(bundlePath).length) + '.bundle'; + }); + output.push({ + path: '$$importBundleNames', + dependencies: new Map(), + getSource: (): Buffer => Buffer.from(''), + inverseDependencies: new Set(), + output: [ + { + type: 'js/script/virtual', + data: { + code: `(function(){var $$=${options.getRunModuleStatement( + options.createModuleId(options.asyncRequireModulePath), + )}$$.addImportBundleNames(${String( + JSON.stringify(importBundleNamesObject), + )})})();`, + map: [], + }, + }, + ], + }); + } + if (options.runModule) { const paths = [...options.runBeforeMainModule, entryPoint]; diff --git a/packages/metro/src/lib/getPrependedScripts.js b/packages/metro/src/lib/getPrependedScripts.js index 1516fa14c5..58e88949b1 100644 --- a/packages/metro/src/lib/getPrependedScripts.js +++ b/packages/metro/src/lib/getPrependedScripts.js @@ -56,6 +56,8 @@ async function getPrependedScripts( transformOptions, ), onProgress: null, + experimentalImportBundleSupport: + config.transformer.experimentalImportBundleSupport, }, ); diff --git a/packages/metro/src/lib/transformHelpers.js b/packages/metro/src/lib/transformHelpers.js index 3e75215ae4..3504053db3 100644 --- a/packages/metro/src/lib/transformHelpers.js +++ b/packages/metro/src/lib/transformHelpers.js @@ -68,6 +68,8 @@ async function calcTransformerOptions( minify: false, }), onProgress: null, + experimentalImportBundleSupport: + config.transformer.experimentalImportBundleSupport, }); return Array.from(dependencies.keys());