UNPKG

@telenko/node-mf

Version:

Module Federation plugin support for NodeJS

87 lines (79 loc) 2.93 kB
const rpcLoadTemplate = require("../templates/rpcLoad"); const rpcPerformTemplate = ` ${rpcLoadTemplate} function rpcPerform(remoteUrl) { const scriptUrl = remoteUrl.split("@")[1]; const moduleName = remoteUrl.split("@")[0]; return new Promise(function (resolve, reject) { rpcLoad(scriptUrl, function(error, scriptContent) { if (error) { reject(error); } //TODO using vm?? const remote = eval(scriptContent + '\\n try{' + moduleName + '}catch(e) { null; };'); if (!remote) { reject("remote library " + moduleName + " is not found at " + scriptUrl); } else if (remote instanceof Promise) { return remote; } else { resolve(remote); } }); }); } `; const rpcProcessTemplate = (mfConfig) => ` function rpcProcess(remote) { return {get:(request)=> remote.get(request),init:(arg)=>{try {return remote.init({ ...arg, ${Object.keys(mfConfig.shared || {}) .filter( (item) => mfConfig.shared[item].singleton && mfConfig.shared[item].requiredVersion ) .map(function (item) { return `"${item}": { ["${mfConfig.shared[item].requiredVersion}"]: { get: () => Promise.resolve().then(() => () => require("${item}")) } }`; }) .join(",")} })} catch(e){console.log('remote container already initialized')}}} } `; function buildRemotes(mfConf, getRemoteUri) { const builtinsTemplate = ` ${rpcPerformTemplate} ${rpcProcessTemplate(mfConf)} `; return Object.entries(mfConf.remotes || {}).reduce((acc, [name, config]) => { acc[name] = { external: `external (async function() { ${builtinsTemplate} return rpcPerform(${ getRemoteUri ? `await ${getRemoteUri(config)}` : `"${config}"` }).then(rpcProcess).catch((err) => { console.error(err); }) }())`, }; return acc; }, {}); } class NodeModuleFederation { constructor(options, context) { this.options = options || {}; this.context = context || {}; } apply(compiler) { const { getRemoteUri, ...options } = this.options; // When used with Next.js, context is needed to use Next.js webpack const { webpack } = this.context; new (webpack?.container.ModuleFederationPlugin || require("webpack/lib/container/ModuleFederationPlugin"))({ ...options, remotes: buildRemotes(options, getRemoteUri), }).apply(compiler); } } module.exports = NodeModuleFederation;