1

We are trying to build a React application that loads inside a lightning:container. Since there is an issue where sometimes you might hit a 403 Forbidden error if the page setup has more than 1 application using lightning:container (I believe there is race condition with the _CONFIRMATIONTOKEN where sometimes it uses the same one for multiple loads of the html of these containers). So, when that happens, sadly the html doesn't even load and we are stuck with a blank page.

<aura:component ...>
  <aura:if isTrue="{!v.iframeNotFailedToLoad}">
    <lightning:container
      aura:id="containerId"
      onmessage="{!c.handleInnerMessage}"
      src="{!$Resource.resource_name + '/index.html'}"
      onerror="{!c.handleIframeError}"
    />
  </aura:if> 
</aura:component>

Brief description of what we have so far:

To address that we tried to look for the load javascript event of the iframe that is created on runtime inside the lightning:container and then using that event to search if the React application sent a message or not the Aura Component. In case there wasn't any message we can guarantee that the iframe finished loading and that something went wrong to load the html (assuming in this case we hit the 403 error). In that case, we change the value of the isTrue attribute in the aura:if to trigger and destroy and then recreate the lightning:container, allowing us to use a different _CONFIRMATIONTOKEN and therefore loading the app correctly.

The issue we are having:

This is the way we are trying to hear for the load event:

  const iframeContainer = cmp.find("containerId");
    if (iframeContainer && iframeContainer.isValid()) {
      const internalDiv = iframeContainer.getElement();
      if (internalDiv) {
        const iframe = internalDiv.firstChild;
        if (iframe) {
          iframe.addEventListener("load", () => {
            this.iframeLoadEvent(cmp, iframe);
          });
        }
      }
    }

Although this worked well when doing dev testing, once we created the package and installed it on an organization it seems that the LockerService is preventing us from doing iframeContainer.getElement(). Therefore, this whole thing just fails.

So, going to to the question: is there a way to identify correctly if we are hitting the 403 issue or knowing if the iframe finished loading but failed to load the HTML so that we can restart it AND also something that works well with the LockerService?

Thanks in advance!

2
  • Doesn't onerror give you what you need?
    – sfdcfox
    Commented Nov 9, 2023 at 13:01
  • @sfdcfox no, it doesn't. When it fails with the 403 error to load the html onerror does not execute Commented Nov 9, 2023 at 16:27

2 Answers 2

0

To resolve this, you can switch from LockerService to LWS. Go to Session Settings in setup and enable Lightning Web Security. LWS is far more lenient in certain aspects, most importantly allows you to access iframe contents.

0

It is not a recent question and a simple workaround is to use the messages and a iife.

If you have a container, you have also an entry point like "index.js". https://webpack.js.org/concepts/entry-points/

index.js in the bundle as entry point for the bundler just contains an iife (immediately invoked function expression) which sends a first message:

(function() {
  // Function to send a message using lightning-container
  function sendMessage() {
    const message = 'bundle loaded';
    // Send the message using the postMessage API
    LCC.sendMessage(message);
    console.log(`Message sent: ${message}`);
  }
  // Execute the sendMessage function immediately
  sendMessage();
})();

and you just handle this message:

handleInnerMessage: function (component, event, helper) {
    var message = event.getParams();
    if (message.payload.toString('utf8') === "bundle loaded") {
       console.log("bundle loaded!");       
    }
},

Given that the source of the entry point is into the bundle itself, the execution means that the bundle is loaded (prerequisite). There is the technique of bundle splitting but most of the time, you have just one file, the bundle.js containing the code of index.js at least.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .