Forked from jacob-ebey/webpack-access-federated-containers-plugin.js
Created
December 8, 2020 05:33
-
-
Save maraisr/8f1d7bb732c188382e0a819d8d3a5a17 to your computer and use it in GitHub Desktop.
webpack-access-federated-containers-plugin.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Makes your remote containers low level API accessible via: | |
import accessFederatedContainer from "access-federated-containers"; | |
accessFederatedContainer("app2") | |
*/ | |
/** @typedef {import("webpack").Compiler} Compiler */ | |
/** @typedef {import("webpack").Compilation} Compilation */ | |
const VirtualModulesPlugin = require("webpack-virtual-modules"); | |
const PLUGIN_NAME = "AccessFederatedContainersPlugin"; | |
/** | |
* | |
* @param {import("webpack").Module[]} modules | |
*/ | |
function createAccessFederatedContainersModule(modules) { | |
const containerAccessors = modules.map((mod) => { | |
const name = mod.userRequest.replace("webpack/container/reference/", ""); | |
const chunks = mod | |
.getChunks() | |
.filter((chunk) => !!chunk.id) | |
.map((chunk) => `__webpack_require__.e(${JSON.stringify(chunk.id)})`); | |
return `${JSON.stringify(name)}: () => Promise.all([${chunks.join( | |
", " | |
)}]).then(() => __webpack_require__(${JSON.stringify(mod.id)}))`; | |
}); | |
return ` | |
const containerAccessors = { | |
${containerAccessors.join(",\n ")} | |
}; | |
async function accessFederatedContainer(containerName) { | |
const accessor = containerAccessors[containerName]; | |
if (!accessor) { | |
throw new Error(\`Can not access container "\${containerName}".\`); | |
} | |
return await accessor(); | |
} | |
export default accessFederatedContainer;`; | |
} | |
const defaultOptions = { | |
exposedAs: "access-federated-containers", | |
}; | |
class AccessFederatedContainersPlugin { | |
constructor(options = defaultOptions) { | |
this._rawRequest = options.exposedAs || defaultOptions.exposedAs; | |
this._exposedAs = `node_modules/${this._rawRequest}`; | |
} | |
/** | |
* @param {Compiler} compiler | |
*/ | |
apply(compiler) { | |
const virtualModules = new VirtualModulesPlugin({ | |
[this._exposedAs]: "", | |
}); | |
virtualModules.apply(compiler); | |
let updatedAccessContainerModule = false; | |
const addedModules = new Map(); | |
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { | |
compilation.hooks.needAdditionalPass.tap(PLUGIN_NAME, () => { | |
console.log( | |
"updatedAccessContainerModule", | |
updatedAccessContainerModule ? "true" : "false" | |
); | |
let result = updatedAccessContainerModule; | |
updatedAccessContainerModule = false; | |
return result; | |
}); | |
compilation.hooks.afterOptimizeModuleIds.tap(PLUGIN_NAME, (modules) => { | |
const filteredModules = [...modules].filter( | |
(mod) => | |
(mod.constructor.name === "ExternalModule" && | |
mod.userRequest && | |
mod.userRequest.startsWith("webpack/container/reference/")) | |
); | |
if ( | |
filteredModules.length > 0 && | |
filteredModules.some((mod) => !addedModules.has(mod.id)) | |
) { | |
updatedAccessContainerModule = true; | |
filteredModules.forEach((mod) => addedModules.set(mod.id, mod)); | |
virtualModules.writeModule( | |
this._exposedAs, | |
createAccessFederatedContainersModule([...addedModules.values()]) | |
); | |
} | |
}); | |
}); | |
} | |
} | |
module.exports = AccessFederatedContainersPlugin; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment