You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Happo has a stylesheets config option to ensure styles are applied at render time. We'd like these styles to also be injected at prerender time. This allows components such as react-autosize-textarea, which call window.getComputedStyle while rendering, to behave more realistically.
Furthermore, we've run into some execution ordering bugs in JSDOM which result in the <script> tags after a stylesheet <link> tag executing before the stylesheet is loaded. This should not happen in a real browser, since styles ought to be parser-blocking. Our solution was to inline the stylesheet contents in a <style> tag.
We were able to work around all of these problems by using the plugins API, which allows providing a custom DomProvider. We extended the JSDOMDomProvider and modified this.dom.
Implementation ideas
Prerender currently operates on a static JSDOM template:
A very basic solution would be to just inject the stylesheets param in here as a tag, the same way that the render environment works. However, this won't support the JSDOM workaround.
Another option would be to automatically inline the styles. However, users might want to link to an external stylesheet that isn't on the filesystem, which would require some work to fetch the stylesheet.
A third option would be to allow customizing the JSDOM template in addition to the existing jsdomOptions.
Lastly, we could just document the fact that DomProviders exist and can be overridden by a plugin. We could use our custom DomProvider as an example:
module.exports=functionhappoPrerenderWithStylesheetsPlugin(stylesheetAbsolutePaths,// the regular jsdomOptions from the config aren't passed to a plugin DOMProvider, maybe we can fix thisjsdomOptions,){classJSDOMProviderWithStylesheetsextendsHappoJSDOMProvider{constructor(jsdomOpts,providerOptions){super(jsdomOpts,providerOptions);// this.dom was created in the superclassconst{window: { document },}=this.dom;stylesheetAbsolutePaths.forEach((href)=>{constcssSource=fs.readFileSync(href,'utf-8');conststyle=document.createElement('style');style.textContent=cssSource;document.head.prepend(style);});}}return{DomProvider: JSDOMProviderWithStylesheets.bind(JSDOMProviderWithStylesheets,jsdomOptions),};};
The text was updated successfully, but these errors were encountered:
Hi @yepitschunked! Thank you for that detailed description, and for providing a workaround option through the DomProvider plugin option.
The alternatives you listed to solve this all seem doable and fair. I think I like the customizing JSDOM html template the most. We could allow an async function return an html string that we use as the template, and then you could fully customize it.
I'd also like to list a few alternative options that you could explore:
By setting prerender: false you'll skip the JSDOM pre-rendering phase which could resolve issues.
You can switch to using a Static bundle. It opens up for even more customization of the html template, the javascript bundle, etc.
One action item I'm recording from this is that we need to document the DomProvider option for plugins. I think I'll add a "Custom plugin" to the Plugins page.
Happo has a stylesheets config option to ensure styles are applied at render time. We'd like these styles to also be injected at prerender time. This allows components such as react-autosize-textarea, which call
window.getComputedStyle
while rendering, to behave more realistically.Furthermore, we've run into some execution ordering bugs in JSDOM which result in the
<script>
tags after a stylesheet<link>
tag executing before the stylesheet is loaded. This should not happen in a real browser, since styles ought to be parser-blocking. Our solution was to inline the stylesheet contents in a<style>
tag.We were able to work around all of these problems by using the plugins API, which allows providing a custom DomProvider. We extended the JSDOMDomProvider and modified
this.dom
.Implementation ideas
Prerender currently operates on a static JSDOM template:
happo.io/src/JSDOMDomProvider.js
Lines 42 to 52 in 2f2bf5a
stylesheets
param in here as a tag, the same way that the render environment works. However, this won't support the JSDOM workaround.The text was updated successfully, but these errors were encountered: