diff --git a/packages/babel-plugin/src/index.js b/packages/babel-plugin/src/index.js index 24081f419..c5b5829c6 100644 --- a/packages/babel-plugin/src/index.js +++ b/packages/babel-plugin/src/index.js @@ -20,7 +20,9 @@ const properties = [ const LOADABLE_COMMENT = '#__LOADABLE__' -const loadablePlugin = declare((api, { defaultImportSpecifier = 'loadable' }) => { +const loadablePlugin = declare((api, babelOptions) => { + const { defaultImportSpecifier = 'loadable' } = babelOptions + const { types: t } = api function collectImportCallPaths(startPath) { @@ -33,7 +35,7 @@ const loadablePlugin = declare((api, { defaultImportSpecifier = 'loadable' }) => return imports } - const propertyFactories = properties.map(init => init(api)) + const propertyFactories = properties.map(init => init(api, babelOptions)) function isValidIdentifier(path, loadableImportSpecifier, lazyImportSpecifier) { // `loadable()` diff --git a/packages/babel-plugin/src/properties/resolve.js b/packages/babel-plugin/src/properties/resolve.js index 8c952d0df..19aa5c0a8 100644 --- a/packages/babel-plugin/src/properties/resolve.js +++ b/packages/babel-plugin/src/properties/resolve.js @@ -1,13 +1,24 @@ import { getImportArg } from '../util' export default function resolveProperty({ types: t, template }) { - const buildStatements = template` - if (require.resolveWeak) { - return require.resolveWeak(ID) - } - - return eval('require.resolve')(ID) - ` + const templates = { + federated: template` + require(ID) + + if (require.resolveWeak) { + return require.resolveWeak(ID) + } + + return eval('require.resolve')(ID) + `, + standard: template` + if (require.resolveWeak) { + return require.resolveWeak(ID) + } + + return eval('require.resolve')(ID) + `, + } function getCallValue(callPath) { const importArg = getImportArg(callPath) @@ -27,11 +38,18 @@ export default function resolveProperty({ types: t, template }) { return t.stringLiteral(importArg.node.value) } - return ({ callPath, funcPath }) => - t.objectMethod( + return ({ callPath, funcPath }) => { + const targetTemplate = process.env.SERVER_SIDE_MODULE_FEDERATION + ? 'federated' + : 'standard' + + return t.objectMethod( 'method', t.identifier('resolve'), funcPath.node.params, - t.blockStatement(buildStatements({ ID: getCallValue(callPath) })), + t.blockStatement( + templates[targetTemplate]({ ID: getCallValue(callPath) }), + ), ) + } } diff --git a/packages/webpack-plugin/src/index.js b/packages/webpack-plugin/src/index.js index a8dbcbdde..3d417944e 100644 --- a/packages/webpack-plugin/src/index.js +++ b/packages/webpack-plugin/src/index.js @@ -11,8 +11,16 @@ class LoadablePlugin { writeToDisk, outputAsset = true, chunkLoadingGlobal = '__LOADABLE_LOADED_CHUNKS__', + serverSideModuleFederation = false, } = {}) { - this.opts = { filename, writeToDisk, outputAsset, path, chunkLoadingGlobal } + this.opts = { + filename, + writeToDisk, + outputAsset, + path, + chunkLoadingGlobal, + serverSideModuleFederation, + } // The Webpack compiler instance this.compiler = null @@ -101,6 +109,23 @@ class LoadablePlugin { apply(compiler) { this.compiler = compiler + if ( + this.opts.serverSideModuleFederation === true && + (compiler.options.target === 'web' || + compiler.options.target === undefined) + ) { + throw new Error( + `Enabling server-side module federation support for a client-side Webpack target (${compiler.options.target}) is unnecessary and will effectively disable all code-splitting.`, + ) + } + + if (this.opts.serverSideModuleFederation) { + Object.defineProperty(process.env, 'SERVER_SIDE_MODULE_FEDERATION', { + value: true, + writable: false, + }) + } + const version = 'jsonpFunction' in compiler.options.output ? 4 : 5 // Add a custom chunk loading callback