问题
I have a critcal CSS process in place that prevents a flash-of-unstyled-content (FOUC) on above-the-fold content of a page.
I'm stuck on 'defer unused CSS' point that's being highlighted by Google PageSpeed insights (lighthouse) and/or Chrome's Performance Audit.
I've gone through other articles but they do not work.
To summarize I've tried so far.
- loadCSS()
- A script that uses requestAnimationFrame
Ref: CSS delivery optimization: How to defer css loading?
If I delay loading the script via setTimeout
by a fixed time of 3 seconds the 'defer unused CSS' issue goes away.
3 seconds is what's needed for Google PageSpeed Insights test (mobile) as they are slower devices but 3 seconds is a lot for desktops which generally has more processing power (note, not always true, hence excluding user-agent based logic).
So the question boils down to how do I delay loading the CSS by the least amount of time irrespective of the device type or specs.
Feel free to throw any rough ideas, I'll try them out and report back, if your idea works, we'll update the code and mark your answer has the chosen one.
Next on my list to try is requestAnimationFrame
+ small fixed delay.
回答1:
Keep in mind that Lighthouse is an advisory tool; it gives recommendations, not requirements. It's up to you to decide if those recommendations make sense in the context of your business requirements. These include weighing the time and effort determining and implementing a solution against the impact of the issue.
Google has advice on resolving Lighthouse's "defer unused CSS" recommendations: Defer unused CSS. To summarize: CSS required immediately by the page should be inlined rather than loaded from a separate file.
回答2:
Manually loading a CSS based on two triggers, whichever occurs first.
- [setTimeout of 2500ms]
- [Scroll event]
<script>
var raf = requestAnimationFrame || mozRequestAnimationFrame ||
webkitRequestAnimationFrame || msRequestAnimationFrame;
var app_css_loaded = false;
/* console.log(performance.now() + ' - ' + '1. async css script init'); */
var loadAppCss = function(){
if(!app_css_loaded) {
app_css_loaded = true;
var l = document.createElement('link'); l.rel = 'stylesheet';
l.href = 'YOUR_COMBINED_AND_MINIFIED_CSS_HERE.css';
var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h);
/* console.log(performance.now() + ' - ' + '5. script injected'); */
}
};
var cb = function() {
/* console.log(performance.now() + ' - ' + '3. cb called'); */
setTimeout(function(){
/* console.log(performance.now() + ' - ' + '4. timeout start'); */
loadAppCss();
/* console.log(performance.now() + ' - ' + '6. timeout end'); */
}, 3000);
};
window.addEventListener('load', function(){
/* console.log(performance.now() + ' - ' + '2. triggering cb directly'); */
if(raf) { raf(cb); } else { cb(); };
});
var loadAppCssOnScroll = function(){
/* console.log(performance.now() + ' - ' + '### triggering cb on scroll'); */
window.removeEventListener('scroll', loadAppCssOnScroll);
if(raf) { raf(loadAppCss); } else { loadAppCss() };
};
window.addEventListener('scroll', loadAppCssOnScroll);
</script>
This makes the PageSpeed insights recommendation regarding defer unused CSS go away.
requestAnimationFrame, if available, will stall the CSS file from loading if the tab has opened in the background in most browsers. You could remove it from the above code if it does not meet your requirements. Ref
console.log() is not available in all browsers. Do not use it in production. Ref
来源:https://stackoverflow.com/questions/54500814/defer-unused-css