Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom rpc templates #16

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/NodeAsyncHttpRuntime/LoadFileChunkLoadingRuntimeModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const { getInitialChunkIds } = require("webpack/lib/javascript/StartupHelpers");
const compileBooleanMatcher = require("webpack/lib/util/compileBooleanMatcher");
const { getUndoPath } = require("webpack/lib/util/identifier");

const rpcLoadTemplate = require("../templates/rpcLoad");
const rpcLoadFromBaseURITemplate = require("../templates/rpcLoadFromBaseURI");

class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
constructor(runtimeRequirements, options, context) {
Expand All @@ -26,7 +26,7 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
*/
generate() {
const { chunkGraph, chunk } = this;
const { baseURI, getBaseUri } = this.options;
const { baseURI, customRpcLoadFromBaseURITemplate, getBaseUri } = this.options;
const { webpack } = this.context;
const { runtimeTemplate } = this.compilation;
const fn = RuntimeGlobals.ensureChunkHandlers;
Expand Down Expand Up @@ -154,8 +154,8 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
)} + ${
RuntimeGlobals.getChunkScriptFilename
}(chunkId));`,
rpcLoadTemplate,
`rpcLoad(${
customRpcLoadFromBaseURITemplate || rpcLoadFromBaseURITemplate,
`rpcLoadFromBaseURI(${
getBaseUri
? `await ${getBaseUri(baseURI)}`
: `"${baseURI}"`
Expand Down Expand Up @@ -201,9 +201,9 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
`var filename = require('path').join(__dirname, ${JSON.stringify(
rootOutputDir
)} + ${RuntimeGlobals.getChunkUpdateScriptFilename}(chunkId));`,
rpcLoadTemplate,
`rpcLoad(${
promiseBaseURI ? `await ${promiseBaseURI}` : `"${baseURI}"`
customRpcLoadFromBaseURITemplate || rpcLoadFromBaseURITemplate,
`rpcLoadFromBaseURI(${
getBaseUri ? `await ${getBaseUri(baseURI)}` : `"${baseURI}"`
}, ${
RuntimeGlobals.getChunkUpdateScriptFilename
}(chunkId), function(err, content) {`,
Expand Down
1 change: 1 addition & 0 deletions src/NodeAsyncHttpRuntime/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class NodeAsyncHttpRuntime {
{
asyncChunkLoading: true,
baseURI: compiler.options.output.publicPath,
customRpcLoadFromBaseURITemplate: this.options.customRpcLoadFromBaseURITemplate,
getBaseUri: this.options.getBaseUri,
},
this.context
Expand Down
48 changes: 19 additions & 29 deletions src/NodeModuleFederation/index.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,5 @@
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 rpcPerformTemplate = require("../templates/rpcPerform");

const rpcProcessTemplate = (mfConfig) => `
function rpcProcess(remote) {
Expand All @@ -44,19 +23,21 @@ const rpcProcessTemplate = (mfConfig) => `
}
`;

function buildRemotes(mfConf, getRemoteUri) {
function buildRemotes(
mfConf,
{ customRpcLoadTemplate, customRpcPerformTemplate, getRemoteUri }
) {
const builtinsTemplate = `
${rpcPerformTemplate}
${customRpcLoadTemplate || rpcLoadTemplate}
${customRpcPerformTemplate || 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}"`
getRemoteUri ? `await ${getRemoteUri(config)}` : `"${config}"`
}).then(rpcProcess).catch((err) => { console.error(err); })
}())`,
};
Expand All @@ -71,14 +52,23 @@ class NodeModuleFederation {
}

apply(compiler) {
const { getRemoteUri, ...options } = this.options;
const {
customRpcLoadTemplate,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since you're adding new options - please document them.

customRpcPerformTemplate,
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),
remotes: buildRemotes(options, {
customRpcLoadTemplate,
customRpcPerformTemplate,
getRemoteUri,
}),
}).apply(compiler);
}
}
Expand Down
14 changes: 2 additions & 12 deletions src/templates/rpcLoad.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
/**
* rpcLoad(baseURI, fileName, cb)
* rpcLoad(scriptUrl, cb)
* rpcLoad(url, cb)
*/
module.exports = `
function rpcLoad() {
var url;
var cb = arguments[arguments.length - 1];
function rpcLoad(url, cb) {
if (typeof cb !== "function") {
throw new Error("last argument should be a function");
}
if (arguments.length === 2) {
url = arguments[0];
} else if (arguments.length === 3) {
url = new URL(arguments[1], arguments[0]).toString();
} else {
throw new Error("invalid number of arguments");
}
//TODO https support
let request = (url.startsWith('https') ? require('https') : require('http')).get(url, function(resp) {
if (resp.statusCode === 200) {
Expand Down
25 changes: 25 additions & 0 deletions src/templates/rpcLoadFromBaseURI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* rpcLoadFromBaseURI(baseURI, fileName, cb)
*/
module.exports = `
function rpcLoadFromBaseURI(baseURI, fileName, cb) {
var url = new URL(arguments[1], arguments[0]).toString();
if (typeof cb !== "function") {
throw new Error("last argument should be a function");
}
//TODO https support
let request = (url.startsWith('https') ? require('https') : require('http')).get(url, function(resp) {
if (resp.statusCode === 200) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This template should reuse rpcLoad template to avoid duplicates

let rawData = '';
resp.setEncoding('utf8');
resp.on('data', chunk => { rawData += chunk; });
resp.on('end', () => {
cb(null, rawData);
});
} else {
cb(resp);
}
});
request.on('error', error => cb(error));
}
`;
23 changes: 23 additions & 0 deletions src/templates/rpcPerform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* rpcPerform(remoteUrl)
*/
module.exports = `
function rpcPerform(remoteUrl) {
const moduleName = remoteUrl.split("@")[0];
const scriptUrl = remoteUrl.split("@")[1];
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);
}
});
});
}
`;