Krótki wpis o tym jak Google niszczy konkurencję
Żyję sobie spokojnie jak gdyby nigdy nic i nagle cerrato z 4programmers.net pisze do mnie, że moja strona mi się rozjechała i podsyła screena. Patrzę i faktycznie plik CSS się w ogóle nie wczytał. Sprawdzam w Chromium, Chromie, Operze i Edge i wszędzie działa. Pytam się cerrato co za niszową przeglądarkę używa.
Firefox, a wszystkie przeglądarki w których testowałem są oparte na silniku z Chromium. Chyba już tylko Firefox ma niespokrewniony silnik.
Analiza
Często analizuję swoją statyczną stronę generowaną przez Jekylla w PageSpeed Insights. Ostatnio Google stwierdził, że źle robię wczytując blokująco swoje CSSy i dał mi poradę z preload.
W rezultacie moje ładowanie pliku CSS przed uruchomieniem jekylla wygląda następująco:
<link rel="preload" href="{{ site.baseurl }}/assets/css/style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript>
<link rel="stylesheet" href="{{ site.baseurl }}/assets/css/style.css">
</noscript>
Co ostatecznie daje następujący kod html:
<link rel="preload" href="/assets/css/style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript>
<link rel="stylesheet" href="/assets/css/style.css">
</noscript>
Czyli jeśli przeglądarka ma włączony JavaScript to plik CSS jest ładowany asynchronicznie. W przeciwnym wypadku jest wykonane klasyczne ładowanie synchroniczne. Niestety Google nie powiedział, że preload nie jest wspierany przez Firefox :(
Dlaczego Firefox nie wspiera preload
? Bo preload
nie jest w standardzie, ale jest w drafcie standardu i jest duża szansa, że będzie. Moim skromnym zdaniem Firefox nie nadąża lub ogranicza zasoby na programistów.
Rozwiązanie
Rozwiązaniem na szybko jest oczywiście usunięcie preload
z kodu HTML. Nie jest to oczywiście rozwiązanie zadowalające.
Na szczęście istnieje skrypt loadCSS, który rozwiązuje wszystkie moje problemy. W rezultacie moje ładowanie pliku CSS przed uruchomieniem jekylla wygląda następująco:
<link rel="preload" href="{{ site.baseurl }}/assets/css/style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript>
<link rel="stylesheet" href="{{ site.baseurl }}/assets/css/style.css">
</noscript>
<script type="text/javascript">
{% include head/loadCss.js %}
</script>
A po uruchomieniu jekylla dostaję:
<link rel="preload" href="/assets/css/style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript>
<link rel="stylesheet" href="/assets/css/style.css">
</noscript>
<script type="text/javascript">
/* loadCSS. [c]2017 Filament Group, Inc. MIT License */
/* This file is meant as a standalone workflow for
- testing support for link[rel=preload]
- enabling async CSS loading in browsers that do not support rel=preload
- applying rel preload css once loaded, whether supported or not.
*/
(function( w ){
"use strict";
if( !w.loadCSS ){
w.loadCSS = function(){};
}
var rp = loadCSS.relpreload = {};
rp.support = (function(){
var ret;
try {
ret = w.document.createElement( "link" ).relList.supports( "preload" );
} catch (e) {
ret = false;
}
return function(){
return ret;
};
})();
rp.bindMediaToggle = function( link ){
var finalMedia = link.media || "all";
function enableStylesheet(){
if( link.addEventListener ){
link.removeEventListener( "load", enableStylesheet );
} else if( link.attachEvent ){
link.detachEvent( "onload", enableStylesheet );
}
link.setAttribute( "onload", null );
link.media = finalMedia;
}
if( link.addEventListener ){
link.addEventListener( "load", enableStylesheet );
} else if( link.attachEvent ){
link.attachEvent( "onload", enableStylesheet );
}
setTimeout(function(){
link.rel = "stylesheet";
link.media = "only x";
});
setTimeout( enableStylesheet, 3000 );
};
rp.poly = function(){
if( rp.support() ){
return;
}
var links = w.document.getElementsByTagName( "link" );
for( var i = 0; i < links.length; i++ ){
var link = links[ i ];
if( link.rel === "preload" && link.getAttribute( "as" ) === "style" && !link.getAttribute( "data-loadcss" ) ){
link.setAttribute( "data-loadcss", true );
rp.bindMediaToggle( link );
}
}
};
if( !rp.support() ){
rp.poly();
var run = w.setInterval( rp.poly, 500 );
if( w.addEventListener ){
w.addEventListener( "load", function(){
rp.poly();
w.clearInterval( run );
} );
} else if( w.attachEvent ){
w.attachEvent( "onload", function(){
rp.poly();
w.clearInterval( run );
} );
}
}
if( typeof exports !== "undefined" ){
exports.loadCSS = loadCSS;
}
else {
w.loadCSS = loadCSS;
}
console.log("Loaded CSS");
}( typeof global !== "undefined" ? global : this ) );
</script>
Podsumowanie
- Nie ufaj Googlowi, niszczą konkurencję
- Warto testować strony na Firefoxie
Zostaw komentarz