4

On my server I am rendering pages that all have the exact same script/ style tags (from the templating on the back end).

And any time I want to create a popup on the site, I create a modal with an iFrame inside of it with the src set.

This causes all of the script tags to be loaded to the client a second time, with the performance impact expected.

My goal is to have the scripts files for the main DOM to be accessible from within the iFrame without reloading them.

Ideally what I'd be able to do is pass a parameter to the server that tells it not to include the script tags in the rendered HTML, and then "push" those scripts and styles from the client directly into the iFrame.

Is something like this possible to where I can maintain the functionality of document.ready and other API's while not having to reload all of the scripts and styles from the server?

Bigbob556677
  • 1,805
  • 1
  • 13
  • 38
  • 1
    I don't know whether It works or not, but I don't think it's a good idea to pass scripts and styles. you can make use of `postMessage` to communicate between your page and iFrame, but that needs additional scripting on both pages. Is there a specific reason to put model popup in iFrame? – Pavan Kumar Jorrigala Apr 07 '20 at 16:44
  • @PavanKumarJorrigala each pop up is a different page. So rather than switching pages, I use the pop ups. It makes development quite a bit easier and it also keeps the pages contained within themselves. Basically the pop up is just a url that is loaded. Eg. Quick edit Customer info in a pop up. – Bigbob556677 Apr 07 '20 at 16:57
  • Generally, Iframes are used to load third-party sites in your page(so that your CSS and script shouldn't affect each other layout and content), Technically, you shouldn't be putting the modal pop-up in iFrame, instead, you can get the pop-up content through Ajax and put it in Div tag with proper CSS styling. – Pavan Kumar Jorrigala Apr 07 '20 at 18:36
  • 1
    I wonder if you can benefit from enforcing [HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching) on your scripts...my theory here is if your iframes come from the same origin, browser might be smart enough to not reload identical documents – timur Apr 08 '20 at 01:37
  • "with the performance impact expected" - if all your scripts and styles are inlined, the main page also has this performance impact every time it's visited. Consider serving your scripts and styles as separate HTTP resources with expiry date headers. Even if your javascript contains dynamically generated segments, usually it can be rewritten as static code that receives dynamic JSON data. – Alexey Lebedev Apr 09 '20 at 07:04
  • @AlexeyLebedev they’re not inlined. They’re being severed as a separate resource. Thanks though – Bigbob556677 Apr 09 '20 at 07:06
  • If they're served as a separate resource, then where would the performance gain come from? If the resources are not cached, injecting `` into the iframe would fetch it from the server just like if it was included in rendered HTML. And if they are cached, including it in the rendered HTML wouldn't cause another request to the server. – Alexey Lebedev Apr 09 '20 at 09:15
  • Did you try achieving this using `window.postMessage()` https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage The window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it. – Jay Apr 09 '20 at 18:12

1 Answers1

3

My goal is to have the scripts files for the main DOM to be accessible from within the iFrame without reloading them.

Kindly note that it is not recommended due to security reasons. It is better to reload the contents or make use of AJAX (which, of course loads the content) as @Pavan said. But, to answer the question, here is my approach

Once you've loaded your DOM (having inline scripts and styles), you can do

window.onload = function() {
    let styleTags = [ ...document.getElementsByTagName('style') ];
    styleText = styleTags.map(eachStyle => eachStyle.outerHTML).join('');
    // mapping each style tag to simple html text

    let scriptTags = [ ...document.getElementsByTagName('script') ];
    scriptText = scriptTags.map(eachScript => eachScript.outerHTML).join('');

    let myIFrame = document.getElementById("myIFrame");
    let doc = myiFrame.contentDocument;
    doc.body.innerHTML += styleText + scriptText;
}

This is only applicable as far as your DOM and iFrame has same domain. I expect you've the same domain for them, by default. Also, external scripts can't be accessed using this approach, they've to be loaded each time.

Community
  • 1
  • 1
vrintle
  • 5,501
  • 2
  • 16
  • 46
  • This code looks great for getting the value of inline scripts/ styles but will it also be able to get the contents of scripts/ styles loaded as resources? – Bigbob556677 Apr 09 '20 at 13:36
  • @Bigbob556677: [Sadly no](https://stackoverflow.com/questions/43818689/get-content-of-a-external-script-included-on-page). Currently, javascript/php can't access external script contents without loading them. The best (but never recommended) you could do is, copy and append all those common styles/scripts in the main file to make them inline (if they're not humongous). But, it will be painful if you're working on some serious projects. So, it's over to you now! – vrintle Apr 09 '20 at 17:36