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:
always includes the custom CSS variables of Jupyterlab for any DOM node. See Styles: count in above snippet in both browsers.
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.
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) )
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:
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 https://github.com/niklasvh/html2canvas/blob/6020386bbeed60ad68e675fdcaa6220e292fd35a/src/dom/document-cloner.ts#L560
is significantly slower for each call in Firefox than in Chrome.
Firefox (8ms):
Chrome (2.19ms):
Upon debugging further we found out that in Jupyterlab in Firefox this line:
https://github.com/niklasvh/html2canvas/blob/6020386bbeed60ad68e675fdcaa6220e292fd35a/src/dom/document-cloner.ts#L321
always includes the custom CSS variables of Jupyterlab for any DOM node. See
Styles:
count in above snippet in both browsers.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:
While this fix is not very generic, an ideal fix could be that
html2canvas
allows us to override our owncopyCSSStyle
function, may be in options like this:and then we can provide our implementation to solve the problem. I'm happy to raise a PR.
Open for other solutions / ideas.
Specifications: