简体   繁体   中英

How to load an iframe without blocking onload or waiting for onload

Suppose I have this page:

<h1>Hello, world!</h1>
<iframe src="https://example.com/test.html"></iframe>

And test.html contains this:

<img src="huge.png" />

huge.png is 100mb for some reason.

I have no control over test.html, but I must include the iframe in my page.

Is there a way to load the iframe without

  1. blocking my page's onload event OR
  2. waiting until my page's onload event to set the iframe's src attribute

I want #1 because I don't want JS on my page to have to wait for example.com's slow image.

I want #2 because I want to start loading example.com's content ASAP.

There are two similar questions.

This is why they aren't duplicates:

  1. Neither is clear what it means to "block" loading - I specify the onload event.
  2. Neither specifies that I don't have control over the iframe's contents (which the first answer on #2 assumes).
  3. Neither specifies that setting the src attribute after onload is not an option (which several answers on #1 assume).

While it's possible that answers to those questions could answer this one, neither is worded in such a way that the answer must answer this question.

You can use Window: DOMContentLoaded event as suggested by charlietfl in the comments; it does not get blocked by resources/assets loading:

The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

Here is a demo snippet that loads an external iFrame that has a 2MB JPEG image; when you run it, you'll see that DOMContentLoaded get to trigger before the iFrame fully loads and it runs custom Javascript; then when the iFrame is done loading, the load event on the iFrame is called and we update a status text.

 // On DOMContentLoaded set status text and start an ASCII animation window.addEventListener('DOMContentLoaded', (event) => { document.getElementById('js-status').textContent = 'DOM fully loaded and parsed; staring JS code'; const animation = new animascii({ src: [ ["0-----", "-----0"], ["-0----", "----0-"], ["--0---", "---0--"], ["---0--", "--0---"], ["----0-", "-0----"], ["-----0", "0-----"] ], display: document.getElementById("ascii-animation"), repeat: -1, delay: 120, font_size: 20 }, function() { alert("Done!"); }); }); // On iframe load event set status text document.getElementsByTagName('iframe')[0].addEventListener('load', function() { document.getElementById('iframe-status').textContent = 'IFrame fully loaded'; });
 iframe { width: 600px; height: 400px; } h2 span { color: blue; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/rot.js/0.6.0/rot.min.js"></script> <script src="https://www.cssscript.com/demo/ascii-animation-library-pure-javascript-animascii/animascii.js"></script> <h2>DOM/JS status: <span id="js-status">(loading...)</span></h2> <h2>IFrame status: <span id="iframe-status">(loading...)</span></h2> <h3>Demo JS to check that JS is running after DOMContentLoaded and before iFrame finish loading</h3> <div id="ascii-animation"></div> <iframe src="https://zikro.gr/dbg/so/53583045/iframe.php"></iframe>

Of course you can set the iFrame src attribute on load , but that is already covered by the questions you're linking:

 window.addEventListener('load', (event) => { document.getElementById('js-status').textContent = 'DOM fully loaded and parsed; staring JS code'; document.getElementById('iframe-status').textContent = '(loading...)'; document.getElementsByTagName('iframe')[0].setAttribute('src', 'https://zikro.gr/dbg/so/53583045/iframe.php'); }); document.getElementsByTagName('iframe')[0].addEventListener('load', (event) => { document.getElementById('iframe-status').textContent = 'IFrame fully loaded'; });
 iframe { width: 600px; height: 400px; } h2 span { color: blue; }
 <h2>DOM/JS status: <span id="js-status">(loading...)</span></h2> <h2>IFrame status: <span id="iframe-status">(not started yet)</span></h2> <iframe></iframe>

A different and somewhat-easier trick: do the load as usual, but also include

<link rel="prefetch" href="https://example.com/test.html">

in your page's <head> .

The browser will start fetching test.html (or huge.png) for you .

It doesn't even require the iframe to exist, you can put it in any page. If you want, you can have the browser start loading the external resource before it's even on the specific page that needs it.

The detailed time depends on the browser's decision, of course, but at the end of the day that's true for all async requests -- and you can put that prefetch first thing after the doctype stuff.

In modern browsers all you need to do is add loading="lazy" to your iframe.

<iframe src="test.html" loading="lazy" />

It's not supported everywhere , but maybe enough for your case?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM