Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

html2canvas significantly slower in Firefox for Jupyterlab #3191

Open
nishikantparmariam opened this issue Aug 23, 2024 · 0 comments
Open

html2canvas significantly slower in Firefox for Jupyterlab #3191

nishikantparmariam opened this issue Aug 23, 2024 · 0 comments

Comments

@nishikantparmariam
Copy link

nishikantparmariam commented Aug 23, 2024

Bug report

Context

We write custom React components for Jupyterlab, one of components allows users to download the view of that component as an image that internally uses html2canvas library. But we found that this operation is significantly slower in Firefox as compared to Chrome in Jupyterlab for the same component. This affects our user-experience a lot.

Reproducer

While our setup is bit complex, we managed to create a minimal reproducer.

Go to https://jupyter.org/try-jupyter/lab/, open a new notebook, add a cell with below code and run it. This code downloads html2canvas on the page and runs it against a div of the page:

from IPython.display import Javascript

Javascript("""

function loadScript(url, callback) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url; 
    script.onload = callback;    
    document.head.appendChild(script);
}

loadScript('https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js', async () => {

    const refreshIconDiv = document.getElementsByClassName('jp-CommandToolbarButton')[5];

    console.log('Styles:', window.getComputedStyle(refreshIconDiv).length);
    
    console.time('HTMLTOCANVAS TIMING');
    await html2canvas(refreshIconDiv);
    console.timeEnd('HTMLTOCANVAS TIMING');
});
""")

If we check the timing in console then in Chrome it takes just 500-600ms but in Firefox this takes 6-7s.

Root-Cause

Upon lots of debugging, we figured out that

export const copyCSSStyles = <T extends HTMLElement | SVGElement>(style: CSSStyleDeclaration, target: T): T => {

is significantly slower for each call in Firefox than in Chrome.

Firefox (8ms):
firefox-timing

Chrome (2.19ms):
image

Upon debugging further we found out that in Jupyterlab in Firefox this line:

const style = window.getComputedStyle(node);

always includes the custom CSS variables of Jupyterlab for any DOM node. See Styles: count in above snippet in both browsers.

image

Because html2canvas clones entire document and styles of every DOM node, these custom CSS variables are getting copied in Firefox making it very slow for Jupyterlab related use-cases.

Related Chromium Issues:
https://issues.chromium.org/issues/351029427
https://issues.chromium.org/issues/41419198

Proposed Solution

While this happens only in Jupyterlab in Firefox but any webpage having custom CSS variables will get affected and html2canvas performance will be very slow.

For us, these custom variables do not matter to be copied and may be skipped, so we re-wrote the copyCSSStyle function like below that made Firefox as fast as Chrome:

var copyCSSStyles = function (style, target) {
        // Iterate from beginning
        for (var i = 0; i < style.length; i++) {
            var property = style.item(i);
            // Return early if a style like this encountered as styles are sorted
            if(property.startsWith('--')) return target;
            if (ignoredStyleProperties.indexOf(property) === -1) {
                target.style.setProperty(property, style.getPropertyValue(property));
            }
        }
        return target;
};

While this fix is not very generic, an ideal fix could be that html2canvas allows us to override our own copyCSSStyle function, may be in options like this:

html2canvas(element, {customCopyCSSStyle: // My implementation})

and then we can provide our implementation to solve the problem. I'm happy to raise a PR.

Open for other solutions / ideas.

Specifications:

  • html2canvas version tested with: 1.4.1 (Latest)
  • Browser & version: Firefox ( 129.0.1 (64-bit) ) and Chrome ( Version 127.0.6533.120 (Official Build) (64-bit) )
  • Operating system: Windows 10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant