I recently heard about the rel="noopener"
attribute value that can be added to anchor tags so that the new window runs in a separate process. That got me wondering: Is it possible to create an iframe that runs in a separate process so that, for example, an infinite loop in the iframe won't cause the parent window's main thread to be blocked?
Here's some example code to observe the main-thread freeze:
<progress></progress>
<iframe srcdoc="<script>function loop() { i=0; while(i<700000000){i++}; setTimeout(loop, 2000) }; loop();</script>"></iframe>
,output
Edit: Note that you can prevent the freezing by adding the sandbox
attribute to the iframe, which seems to "force" the browser (Chrome, at least) to put the iframe in a separate thread, but I can't do this in my case. I am however serving the code for the iframe under a separate subdomain so I'd have thought that since it's a separate origin Chrome would put it in a separate process as it appears to do if the iframe's src
is a different top-level domain.
I recently heard about the rel="noopener"
attribute value that can be added to anchor tags so that the new window runs in a separate process. That got me wondering: Is it possible to create an iframe that runs in a separate process so that, for example, an infinite loop in the iframe won't cause the parent window's main thread to be blocked?
Here's some example code to observe the main-thread freeze:
<progress></progress>
<iframe srcdoc="<script>function loop() { i=0; while(i<700000000){i++}; setTimeout(loop, 2000) }; loop();</script>"></iframe>
https://jsbin./zabecoviwi/1/edit?html,output
Edit: Note that you can prevent the freezing by adding the sandbox
attribute to the iframe, which seems to "force" the browser (Chrome, at least) to put the iframe in a separate thread, but I can't do this in my case. I am however serving the code for the iframe under a separate subdomain so I'd have thought that since it's a separate origin Chrome would put it in a separate process as it appears to do if the iframe's src
is a different top-level domain.
2 Answers
Reset to default 4As of early 2021, there is now the Origin-Agent-Cluster
header which allows you to request dedicated resources for an iframe. It is currently supported on Chrome (88+) with positive reception from Mozilla and Safari.
Origin-Agent-Cluster is a new HTTP response header that instructs the browser to prevent synchronous scripting access between same-site cross-origin pages. Browsers may also use Origin-Agent-Cluster as a hint that your origin should get its own, separate resources, such as a dedicated process.
[...] For example, if
https://customerservicewidget.example.
expects to use lots of resources for video chat, and will be embedded on various origins throughouthttps://*.example.
, the team maintaining that widget could use the Origin-Agent-Cluster header to try to decrease their performance impact on embedders.
To use the Origin-Agent-Cluster header, configure your web server to send the following HTTP response header:
Origin-Agent-Cluster: ?1
The value of?1
is the structured header syntax for a boolean true value.
More details here: https://web.dev/origin-agent-cluster/
In some browsers, including Chrome, cross-origin iframes already run in a separate process. For example, running the following snippet in Chrome will not prevent you from scrolling in the parent Stack Overflow window:
while (true) {
}
For browsers which don't do this already, or for same origin iframes, you can make the process explicit by running the expensive tasks in a web worker in the iframe:
const workerFn = () => {
// something expensive
while (true) {
}
};
const workerFnStr = `(${workerFn})();`;
const blob = new Blob([workerFnStr], { type: 'text/javascript' });
const worker = new Worker(window.URL.createObjectURL(blob));
// The worker has been created, and will continuously consume resources,
// but will not block the iframe window or the iframe's parent
body {
height: 1000px;
}