Próbuję wyeliminować 2 pliki CSS, które blokują renderowanie w mojej witrynie - pojawiają się one w Google Page Speed Insights. Stosowałem różne metody, z których żadna nie okazała się sukcesem. Ale ostatnio znalazłem post o Thinking Async i kiedy zastosowałem ten kod: <script async src="https://third-party.com/resource.js"></script>
wyeliminował problem.
Jednak po opublikowaniu strona straciła stylistykę. Nie jestem pewien, co się dzieje, ponieważ kod działa, ale to stylizacja po przesłaniu nie działa. Byłbym wdzięczny za twoją pomoc. Dzięki
html
css
asynchronous
Paulina994
źródło
źródło
Odpowiedzi:
Sztuczka wyzwalania asynchronicznego pobierania arkusza stylów polega na użyciu
<link>
elementu i ustawieniu nieprawidłowej wartości dla atrybutu media (używam media = "none", ale każda wartość wystarczy). Gdy zapytanie o media ma wartość false, przeglądarka nadal pobierze arkusz stylów, ale nie będzie czekać, aż zawartość będzie dostępna przed renderowaniem strony.<link rel="stylesheet" href="css.css" media="none">
Po zakończeniu pobierania arkusza stylów atrybut media musi być ustawiony na prawidłową wartość, aby reguły stylu zostały zastosowane do dokumentu. Zdarzenie onload służy do przełączania właściwości media na all:
<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">
Ta metoda ładowania CSS zapewni odwiedzającym użyteczne treści znacznie szybciej niż standardowe podejście. Krytyczny CSS może być nadal obsługiwany przy użyciu zwykłego podejścia blokującego (lub można go wbudować w celu uzyskania najwyższej wydajności), a style niekrytyczne można stopniowo pobierać i stosować później w procesie analizowania / renderowania.
Ta technika wykorzystuje JavaScript, ale możesz obsługiwać przeglądarki inne niż JavaScript, opakowując równoważne
<link>
elementy blokujące w<noscript>
element:<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'"><noscript><link rel="stylesheet" href="css.css"></noscript>
Operację można zobaczyć na stronie www.itcha.edu.sv
Źródło w http://keithclark.co.uk/
źródło
preload
Firefoksa i starszych przeglądarek - zobacz link w pierwszym komentarzu do tej odpowiedzi].Aktualizacja 2020
Prosta odpowiedź (pełna obsługa przeglądarki):
<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">
Udokumentowana odpowiedź (z opcjonalnym ładowaniem wstępnym i funkcją awaryjną z wyłączoną obsługą skryptów):
<!-- Optional, if we want the stylesheet to get preloaded. Note that this line causes stylesheet to get downloaded, but not applied to the page. Use strategically — while preloading will push this resource up the priority list, it may cause more important resources to be pushed down the priority list. This may not be the desired effect for non-critical CSS, depending on other resources your app needs. --> <link rel="preload" href="style.css" as="style"> <!-- Media type (print) doesn't match the current environment, so browser decides it's not that important and loads the stylesheet asynchronously (without delaying page rendering). On load, we change media type so that the stylesheet gets applied to screens. --> <link rel="stylesheet" href="style.css" media="print" onload="this.media='all'"> <!-- Fallback that only gets inserted when JavaScript is disabled, in which case we can't load CSS asynchronously. --> <noscript><link rel="stylesheet" href="style.css"></noscript>
Łączone ładowanie wstępne i asynchroniczne:
Jeśli potrzebujesz wstępnie załadowanego i asynchronicznego CSS, to rozwiązanie po prostu łączy dwie linie z udokumentowanej odpowiedzi powyżej, czyniąc ją nieco bardziej przejrzystą. Ale to nie zadziała w Firefoksie, dopóki nie obsługują słowa kluczowego preload . I znowu, jak szczegółowo opisano w udokumentowanej odpowiedzi powyżej, wstępne ładowanie może w rzeczywistości nie być korzystne.
<link href="style.css" rel="preload" as="style" onload="this.rel='stylesheet'"> <noscript><link rel="stylesheet" href="style.css"></noscript>
Dodatkowe uwagi:
Zauważ, że generalnie, jeśli zamierzasz ładować CSS asynchronicznie, ogólnie zaleca się wbudowanie krytycznego CSS , ponieważ CSS jest zasobem blokującym renderowanie z jakiegoś powodu .
Podziękowania dla grupy filamentów za wiele asynchronicznych rozwiązań CSS.
źródło
onload="this.rel='stylesheet'; this.onload = null"
. Najwyraźniej konieczne jest ustawienie opcji,this.onload
abynull
uniknąć podwójnego wywoływania tego w niektórych przeglądarkach.Korzystanie
media="print"
ionload
Grupa filamentów niedawno (lipiec 2019 r.) Opublikowała artykuł zawierający najnowsze zalecenia dotyczące asynchronicznego ładowania CSS. Mimo że są twórcami popularnej biblioteki JavaScript loadCSS , w rzeczywistości polecają to rozwiązanie, które nie wymaga biblioteki Javascript:
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'; this.onload = null" >
Użycie
media="print"
wskaże przeglądarce, aby nie używać tego arkusza stylów na ekranach, ale na wydruku. Przeglądarki faktycznie pobierają te arkusze stylów drukowania, ale asynchronicznie, a tego właśnie chcemy. Chcemy również, aby arkusz stylów był używany po pobraniu i do tego ustawiliśmyonload="this.media='all'; this.onload = null"
. (Niektóre przeglądarki zadzwoniąonload
dwa razy, aby obejść ten problem, musimy ustawićthis.onload = null
). Jeśli chcesz, możesz dodać<noscript>
rezerwę dla rzadkich użytkowników, którzy nie mają włączonego Javascript.Oryginalny artykuł warto przeczytać, jak to jest w sposób bardziej szczegółowy niż jestem tutaj. Warto przeczytać również ten artykuł na csswizardry.com .
źródło
możesz spróbować go zdobyć na wiele sposobów:
1. używanie
media="bogus"
i<link>
na stopie<head> <!-- unimportant nonsense --> <link rel="stylesheet" href="style.css" media="bogus"> </head> <body> <!-- other unimportant nonsense, such as content --> <link rel="stylesheet" href="style.css"> </body>
2.Wstawianie DOM w stary sposób
<script type="text/javascript"> (function(){ var bsa = document.createElement('script'); bsa.type = 'text/javascript'; bsa.async = true; bsa.src = 'https://s3.buysellads.com/ac/bsa.js'; (document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(bsa); })(); </script>
3. jeśli możesz wypróbować wtyczki, możesz spróbować loadCSS
<script> // include loadCSS here... function loadCSS( href, before, media ){ ... } // load a file loadCSS( "path/to/mystylesheet.css" ); </script>
źródło
<script>
na<style rel=stylesheet>
? (Po prostu ciekawy. Zamierzam użyćloadCSS
(tj. Twojego przykładu 3) zamiast tego, jeśli będę musiał załadować CSS później.)Poniższa funkcja utworzy i doda do dokumentu wszystkie arkusze stylów, które chcesz ładować asynchronicznie. (Ale dzięki
Event Listener
, zrobi to dopiero po załadowaniu wszystkich innych zasobów okna).Zobacz następujące:
function loadAsyncStyleSheets() { var asyncStyleSheets = [ '/stylesheets/async-stylesheet-1.css', '/stylesheets/async-stylesheet-2.css' ]; for (var i = 0; i < asyncStyleSheets.length; i++) { var link = document.createElement('link'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('href', asyncStyleSheets[i]); document.head.appendChild(link); } } window.addEventListener('load', loadAsyncStyleSheets, false);
źródło
var newStyle = document.createElement("link"); newStyle.rel = "stylesheet"; newStyle.href = "stylesheet.css"; document.getElementsByTagName("head")[0].appendChild(newStyle);
wewnątrz<script>
tagu w treści strony działa doskonale - nawet w starszych przeglądarkach, takich jak MSIE8.window.load
zdarzenie. Tak więc pobieranie rozpoczyna się, gdy wszystko zostanie pobrane. Nie ma szczęścia. Aby rozpocząć, potrzebujesz szybkiego ładowania bez blokowania.Asynchroniczne metody ładowania CSS
istnieje kilka sposobów, aby przeglądarka ładowała CSS asynchronicznie, ale żaden z nich nie jest tak prosty, jak można by się spodziewać.
<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">
źródło
Jeśli potrzebujesz programowo i asynchronicznie załadować link CSS:
// https://www.filamentgroup.com/lab/load-css-simpler/ function loadCSS(href, position) { const link = document.createElement('link'); link.media = 'print'; link.rel = 'stylesheet'; link.href = href; link.onload = () => { link.media = 'all'; }; position.parentNode.insertBefore(link, position); }
źródło
Jeśli masz ścisłą politykę bezpieczeństwa treści, które nie pozwala @ Vladimir-Salguero „s odpowiedź , można użyć tego (zanotuj skryptu
nonce
):<script nonce="(your nonce)" async> $(document).ready(function() { $('link[media="none"]').each(function(a, t) { var n = $(this).attr("data-async"), i = $(this); void 0 !== n && !1 !== n && ("true" == n || n) && i.attr("media", "all") }) }); </script>
Wystarczy dodać następujące odniesienia arkusza stylów:
media="none" data-async="true"
. Oto przykład:<link rel="stylesheet" href="../path/script.js" media="none" data-async="true" />
Przykład dla jQuery:
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" type="text/css" media="none" data-async="true" crossorigin="anonymous" /><noscript><link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" type="text/css" /></noscript>
źródło
async
atrybut jest ignorowany, ponieważ tag skryptu nie musisrc
ładować się asynchronicznie ... czy jest to naprawdę przydatne tutaj? Czy możesz również wyjaśnić nieco więcej, której wartości użyć jakononce
?Zaktualizuj odpowiedź, ponieważ wszystkie powyższe nie są teraz imponujące w statystykach Google Pagespeed.
Według Google w ten sposób należy zaimplementować ładowanie asynchroniczne Css
< noscript id="deferred-styles" > < link rel="stylesheet" type="text/css" href="small.css"/ > < /noscript > <script> var loadDeferredStyles = function() { var addStylesNode = document.getElementById("deferred-styles"); var replacement = document.createElement("div"); replacement.innerHTML = addStylesNode.textContent; document.body.appendChild(replacement) addStylesNode.parentElement.removeChild(addStylesNode); }; var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); }); else window.addEventListener('load', loadDeferredStyles); </script>
źródło
Spróbowałem użyć:
<link rel="preload stylesheet" href="mystyles.css" as="style">
Działa dobrze, ale podnosi również skumulowane przesunięcie układu, ponieważ kiedy używamy rel = "preload", po prostu pobiera css, a nie stosuje natychmiast.
Na przykład, gdy DOM ładuje listę zawierającą znaczniki ul, li, domyślnie przed znacznikami li znajduje się punktor, a następnie zastosowano CSS, aby usunąć te punktory z niestandardowych stylów do wyświetlenia. A więc skumulowana zmiana układu ma miejsce tutaj.
Czy jest na to jakieś rozwiązanie?
źródło
Użyj,
rel="preload"
aby pobrać go niezależnie, a następnie użyj,onload="this.rel='stylesheet'"
aby zastosować go do arkusza stylów (as="style"
konieczne jest zastosowanie go do arkusza stylów, w przeciwnym razieonload
nie zadziała)<link rel="preload" as="style" type="text/css" href="mystyles.css" onload="this.rel='stylesheet'">
źródło