Skip to Main Content

DevOps, CI/CD and Automation

Announcement

For appeals, questions and feedback, please email oracle-forums_moderators_us@oracle.com

Oracle JET v15: Webpack Module Federation Not Working When Importing Component That Uses OJET Web Components.

Rachid Lamtabbet-OracleAug 22 2023 — edited Aug 22 2023

I'm working with several MFE/OJET v15 applications using Webpack Module Federation that seem to break as soon as I remote import component that uses any OJET Web Components. Working with other custom components present no problem. It's only when an OJET Web Component is added to the mix.

Let's assume “app1” is the host application and “app2” is a child mfe that exposes a single VComponent that looks like the following:

import { h } from ‘preact’;
import 'ojs/ojbutton';

const Button = (props: any) => <oj-button {...props}></oj-button>;
export default Button;

Unfortunately this does not work and throws the following error:

Uncaught error: DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "oj-surrogate" has already been used with this registry

See ref: https://github.com/oracle/oraclejet/issues/43

I understand that this might be happening due to fact that the OJET dependencies are being loaded more than once and therefor need to be shared between mfe(s).

I updated the ModuleFederationPlugin config to share the OJET dependencies as show bellow but that still didn't work.

shared: {
"@oracle/oraclejet": { eager: true, singleton: true},
"@oracle/oraclejet-core-pack": { eager: true, singleton: true},
"oracle/oraclejet-preact": { eager: true, singleton: true},
"oj-c": { eager: true, singleton: true},
"@oracle/oraclejet-core-pack/oj-c": { eager: true, singleton: true},
“ojs”: { eager: true, singleton: true},
"@oracle/oraclejet/dist/js/libs/oj/debug": { eager: true, singleton: true},
"oj-surrogate": { eager: true, singleton: true}
}

The following post helped me a little bit understand what's going on behind the curtains
https://stackoverflow.com/questions/54211849/uncaught-domexception-failed-to-execute-define-on-customelementregistry-th

And in the midst of writing this question, I ended up solving the problem, for now (finger crossed)
So I ended up writing a custom Webpack plugin that leverages the code from the previous link.

new (class CustomElementRegistryPlugin {
constructor(htmlWebpackPlugin) {
this.htmlWebpackPlugin = htmlWebpackPlugin;
}

apply(compiler) {
compiler.hooks.thisCompilation.tap(
"CustomElementRegistryPlugin",
(compilation) => {
// hook into the html-webpack-plugin processing
const hooks = this.htmlWebpackPlugin.getHooks(compilation);
// replace the customElements define method in index.html and inject it.
hooks.alterAssetTags.tap(
"CustomElementRegistryPlugin",
({ assetTags }) => {
assetTags.scripts.unshift({
tagName: "script",
innerHTML: `
function safeDecorator(fn) {
return function (...args) {
try {
return fn.apply(this, args);
} catch (error) {
if (error instanceof DOMException && error.message.includes('has already been used with this registry')) {
return false;
}
throw error;
}};
}
window.customElements.define = safeDecorator(window.customElements.define);`,
closeTag: true,
});
});
});
}})(HtmlWebpackPlugin)

All that is needed is to add the plugin into the webpack config for both mfe(s) and you're good to go.

I hope this helps someone else desperately looking for a quick fix. I'm looking forward to see if the community has a better answer.

Best.

Comments
Post Details
Added on Aug 22 2023
1 comment
359 views