TYPO3: Critical CSS how to implement?

How to use the pagerenderer.html to increase loading speed and first render time. This is also known as critical rendering path

Ok, so we are trying some things to make the speed of our TYPO3 site a lot better. We can do some fun stuff with staticfilecache but this only lowers the reaction speed of the page, not the actual way the CSS and Javascript requests block the rendering of the page.

What is Critical Rendering Path / Render blocking in CSS?

Normally, one would load the CSS and JS into the header. This will make sure all the resources are loaded before the DOM is interpreted by the browser (please correct me if I am wrong, this is my personal take on this). This way the first render of the page is being delayed. I tried to visualize it in code for the readers.
html>
<head>
<!-- this css file could be big, say 100kb. The browser will wait first this file to load before even looking at your body-tag -->
<link rel="stylesheet" type="text/css" href="yourcssfile.css">
<!-- here are normally a lot more things like jquery or bootstrap js even slowing the load down more -->
<script src="yourjs.js" type="text/javascript"></script>
</head>
<body>
<h3>After loading the css and JS, then eventually the browser will load and show this</h3>
</body>
</html>
We are currently experimenting with something more like this:
<html> 
<head> 
<style>
/* Some inline css here to show everything above the fold. It does not really matter if is quite some date since no extra network requests have to be started to external resources. */
body { background: Red; }
</style>
</head> 
<body>
<h3>After loading the css and JS, then eventually the browser will load and show this</h3>
<!-- at the end of body we will load the "full" css and the javascript files -->
<link rel="stylesheet" type="text/css" href="yourcssfile.css">
<script src="yourjs.js" type="text/javascript"></script>
</body>
</html>
The problem with this setup is that we need to "calculate" the critical css path for every page or every template. So if we load bootstrap 4 css into the footer, we need to load some of bootstrap's css to render the menu and the "above the fold" part.
How to calculate critical rendering path?
I think it is possible to set something up with PhantomJS or something (I am not a javascript guy.. yet) but we prefer to use an online service for this. When we started this experiment in 2016 there was a free service to calculate the critical rendering path. This service no longer exists but we found a way to do it for only $2,- a month. They have an API to automate this process but we sadly have not found the time to implement this yet for our customers. We think they could really benefit from this. We service we use is criticalcss.com, you can simply enter the url of your page, and within a few seconds a downloadable CSS file is generated for you. We then use this file to use in the inline css part of our header. This way the first network request (the html page without the css and js in the header) already contains some of the styling to render the above-the-fold content. A short moment later (200ms or so) the "full" css has loaded in the background, sometimes this will cause a little "re-render" of the css which could be visible noticable. But consider mobile devices: If the first appearance of the page shows sooner, this will result in less bounce-rate, and faster feedback to your visitor.
How to implement this in TYPO3?
We need to locate the normal PageRenderer.html. It is located in: typo3/sysext/core/Resources/Private/Templates/PageRenderer.html
Copy this file to /fileadmin/templates/PageRenderer.html (or some other folder in your fileadmin subdir. You should know where to place it)
After creating the file, you need to use it in the main typoscript file like this:
config.pageRendererTemplateFile = fileadmin/templates/PageRenderer.html 
The file you just made in your own template folder should now look something like this:
###XMLPROLOG_DOCTYPE###
###HTMLTAG###
###HEADTAG###

###METACHARSET###
###INLINECOMMENT###

###BASEURL###
###SHORTCUT###
###TITLE###
###META###

###CSS_LIBS###
###CSS_INCLUDE###
###CSS_INLINE###

###JS_LIBS###
###JS_INCLUDE###
###JS_INLINE###

###HEADERDATA###
<!--###POSTJSMARKER###-->
</head>
###BODY###
###JS_LIBS_FOOTER###
###JS_INCLUDE_FOOTER###
###JS_INLINE_FOOTER###
###FOOTERDATA###
</body>
</html>

We will change this file by moving and removing some of the markers. This way all the css and javascript (watch out with inline js) will be moved to the bottom of the page, right before the closing body tag. This is our current working file, no guarantees here.
###XMLPROLOG_DOCTYPE###}
###HTMLTAG###
###HEADTAG###
###METACHARSET###

###BASEURL###
###SHORTCUT###
###TITLE###
###META###

###HEADERDATA###
<style type="text/css">
<!-- put your inline CSS here. This could be quite a bit of text around 10-15 kb -->
<!-- if you want to see how this works. Throttle your browser to a very low bandwidth and see how the css loads in two fases by putting body { background: red; } or something here -->
</style>

</head>
###BODY###
###CSS_LIBS###
###CSS_INCLUDE###
###CSS_INLINE###

###JS_LIBS###
###JS_INCLUDE###
###JS_INLINE###
###JS_LIBS_FOOTER###
###JS_INCLUDE_FOOTER###
###JS_INLINE_FOOTER###
###FOOTERDATA###
</body>
</html>
Again, this will move all the external requests to the bottom of the page. If you dont use critical css (inline css in the pagerendere) you will see a white page without any css for a brief moment (200ms or so) and then the css will load at the bottom of the footer (where it is not blocking the first render). Remember: The css should be cached so the second load will be much better, keep in mind we are optimizing for the first load a user ever does, so the inline css will help with this. There will be only 1 network request (the html with the inline css in the header) before rendering the page, then after that.. in the background.. the rest of the css and js is loaded (usually takes a second or two).
If you want to understand this better, have a look at the source code of this website. We have done this here as an experiment so you should look at the source code of this page and you should be able to understand. The main trick is "at what line do we request external resources, and could we move some things around to not let the browser wait for things to load, thus showing content to users sooner".
Ideas to speed up TYPO3 even more
We have used this techniques a few times to speed up sites, We won't go into them now, maybe in another post.
Combing the CSS and JS with concatenateCss, compressCss, concatenateJs and compressJs Static File Cache (like mentioned before) HTML Minifier Cloudflare or other CDN / WAF AMP?
by Daniel at 2023-03-21T20:06:34.001Z
Copyright © DanielKnows.com 2019 - 2023 - Built with NuxtJS