Created
December 8, 2020 05:12
-
-
Save jacob-ebey/1a6edce80519c25b4725a05cc5618ee4 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