CSS Eşzamansız Olarak Nasıl Yüklenir


92

Sitemde engelleme oluşturan 2 CSS dosyasını ortadan kaldırmaya çalışıyorum - bunlar Google Page Speed ​​Insights'ta görünüyor. Hiçbiri başarılı olmayan farklı yöntemler izledim. Ancak son zamanlarda, Thinking Async hakkında bir gönderi buldum ve bu kodu uyguladığımda: <script async src="https://third-party.com/resource.js"></script>sorunu ortadan kaldırdı.

Ancak, yayınlandıktan sonra sayfa stilini kaybetti. Neler olup bittiğinden pek emin değilim çünkü kod çalışıyor ama işe yaramayan yüklemeden sonraki stil. Bununla ilgili yardımın için minnettar olurum. Teşekkürler


2
Stillere veya komut dosyalarına zaman uyumsuz mu uyguluyorsunuz? Stil, sayfayı yükledikten bir süre sonra mı yükleniyor yoksa hiç görünmüyor mu?
kamus

Async özelliğini stillere uyguladım ve bunları başlığa yerleştirdim.
Paulina994

2
Stillerle ilgili olan şey, onları geç yüklerseniz (örneğin gövdede) bir yeniden oluşturma tetiklenecek ve standartlarda buna izin verilmiyor (ancak tarayıcılar çok bağışlayıcı olduğu için yine de işe yarayacaktır). Sorun, üçüncü taraf bir sunucudan yavaş yanıt süreleriyse, belki de bunları sunucunuzda barındırabilirsiniz?
Josef Engelfrost

Yanıtlar:


129

Eşzamansız bir stil sayfası indirmesini tetiklemenin püf noktası, bir <link>öğe kullanmak ve media özniteliği için geçersiz bir değer ayarlamaktır (media = "none" kullanıyorum, ancak herhangi bir değer işe yarar). Bir medya sorgusu yanlış olarak değerlendirildiğinde, tarayıcı yine de stil sayfasını indirir, ancak sayfayı oluşturmadan önce içeriğin kullanılabilir olmasını beklemez.

<link rel="stylesheet" href="css.css" media="none">

Stil sayfasının indirilmesi bittiğinde, ortam niteliği geçerli bir değere ayarlanmalıdır, böylece stil kuralları belgeye uygulanacaktır. Onload olayı, media özelliğini tümü olarak değiştirmek için kullanılır:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">

Bu CSS yükleme yöntemi, standart yaklaşımdan çok daha hızlı şekilde ziyaretçilere kullanılabilir içerik sunacaktır. Kritik CSS, normal engelleme yaklaşımıyla sunulmaya devam edilebilir (veya nihai performans için satır içi yapabilirsiniz) ve kritik olmayan stiller, daha sonra ayrıştırma / oluşturma sürecinde aşamalı olarak indirilebilir ve uygulanabilir.

Bu teknik JavaScript kullanır, ancak eşdeğer engelleme <link>öğelerini bir <noscript>öğeye sararak JavaScript olmayan tarayıcıların ihtiyaçlarını karşılayabilirsiniz :

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'"><noscript><link rel="stylesheet" href="css.css"></noscript>

İşlemi www.itcha.edu.sv adresinde görebilirsiniz.

görüntü açıklamasını buraya girin

Kaynak http://keithclark.co.uk/


Tamam .. İşleyicilerdeki öğe özniteliklerine yalnızca adlarını söyleyerek başvurabileceğinizi bilmiyordum. Hep 'olay'ın tek istisna olduğunu düşünmüşümdür.
Teemoh

1
Peki, sayfanızın her şeyi yeniden oluştururken yanıp sönmesini nasıl önleyebilirsiniz? Ayrıca, Lynx'in gurur duyacağı bir şeyi oluşturmak yerine sayfanızın başlangıç ​​düzenine sahip olması için satır içi çekirdek uygulama kabuğu stillerini mi kullanıyorsunuz?
Chris Love

2
Hala benim için çalışıyor gibi görünüyor. Bunu yaptıktan sonra, bu dosya için PageSpeed ​​Insights'ta artık bir uyarı aldığımı biliyorum.
AndyWarren

3
bu benim için çalışıyor (08-temmuz-2018). Ve Pagespeed Insight'ta iyi bir puan veriyor
abilash er

1
Jabachetta'nın "önyükleme" kullanan daha yeni yanıtı olan IMHO, muhtemelen şu anda tercih edilen çözümdür. Herhangi birinin bu cevabın hala tercih edilebilir olduğunu düşünmesi için bir nedeni varsa , lütfen nedenini açıklayan bir yorum ekleyin. İdeal olarak, bu yaklaşımın neden / ne zaman hala tercih edilebilir olduğunu doğrulayan bir kaynağa bağlanmak. [Çoklu dolguyu preloadFirefox'ta ve eski tarayıcılarda desteklemek için kullandığınızı varsayarsak - bu cevabın ilk yorumundaki bağlantıya bakın].
ToolmakerSteve

109

2020 Güncellemesi


Basit cevap (tam tarayıcı desteği):

<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">

Belgelenen cevap (isteğe bağlı önyükleme ve komut dosyası devre dışı bırakılmış geri dönüş ile):

 <!-- 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>

Önceden yükleme ve eşzamansız:

Önceden yüklenmiş ve eşzamansız CSS'ye ihtiyacınız varsa, bu çözüm, yukarıda belgelenen cevaptan iki satırı birleştirerek onu biraz daha temiz hale getirir. Ancak bu , önyükleme anahtar kelimesini destekleyene kadar Firefox'ta çalışmayacaktır . Ve yine, yukarıda belgelenen cevapta detaylandırıldığı gibi, ön yükleme aslında faydalı olmayabilir.

<link href="style.css" rel="preload" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="style.css"></noscript>

Ek hususlar:

Genel olarak, CSS'yi eşzamansız olarak yükleyecekseniz, CSS'nin bir nedenden ötürü oluşturmayı engelleyen bir kaynak olması nedeniyle genellikle kritik CSS'yi satır içine almanız önerilir .

Birçok async CSS çözümleri için filament grubuna kredi .


3
LoadCSS kullanmaya gerek yok, polyfill yeterli: github.com/filamentgroup/loadCSS/blob/master/src/…
nathan

1
Önyüklemenin teknik özellik durumu nihayet [W3C Aday Önerisi] 'dir. ( W3.org/TR/preload/… ) Firefox bunu destekler, ancak varsayılan olarak yine de devre dışıdır; onu kontrol eden Firefox bayrağının "Kullanabilir miyim" açıklaması için yanıtın "yaygın olarak desteklenen" bağlantısını tıklayın.
ToolmakerSteve

1
Yanıt, ek açıklamayla birlikte tam tarayıcı desteği için çözüm sağlamak üzere güncellendi.
jabacchetta

1
@jabacchetta 2020 güncellemesi çok takdir ediliyor, teşekkür ederim. Tarayıcı desteğinin genellikle daha iyi olduğu son zamanlarda yazılmış talimatları özellikle arıyordum . Web'de 3 yılda çok fazla değişiklik!
Brandito

Görünüşe göre daha iyi onload="this.rel='stylesheet'; this.onload = null". Görünüşe göre bazı tarayıcılarda bunun iki kez çağrılmasını önlemek için ayar this.onloadyapılması nullgerekiyor.
Flimm

9

kullanılması media="print"veonload

Filament grubu kısa süre önce (Temmuz 2019) , CSS'nin eşzamansız olarak nasıl yükleneceğine dair en son önerilerini veren bir makale yayınladı . Popüler Javascript kitaplığı loadCSS'nin geliştiricileri olsalar da , aslında bir Javascript kitaplığı gerektirmeyen bu çözümü öneriyorlar:

<link
  rel="stylesheet"
  href="/path/to/my.css"
  media="print"
  onload="this.media='all'; this.onload = null"
>

Kullanılması media="print", tarayıcıya bu stil sayfasını ekranlarda değil, baskıda kullanacağını belirtecektir. Tarayıcılar aslında bu baskı stil sayfalarını indiriyorlar, ancak eşzamansız olarak, biz de bunu istiyoruz. Ayrıca stil sayfasının indirildikten sonra kullanılmasını istiyoruz ve bunun için ayarladık onload="this.media='all'; this.onload = null". (Bazı tarayıcılar onloadiki kez arayacak , bunu çözmek için ayarlamamız gerekiyor this.onload = null.) İsterseniz <noscript>, Javascript'i etkinleştirmemiş nadir kullanıcılar için bir yedek ekleyebilirsiniz .

Orijinal makale buradayım olmadığı kadar daha ayrıntılı anlatır gibi bir okuma değer. Csswizardry.com adresindeki bu makale de okunmaya değer.


5

birçok yoldan edinmeyi deneyebilirsiniz:

1. kullanarak media="bogus"ve a <link>ayak

<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. DOM'u eski yöntemle yerleştirmek

<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. Eklentileri deneyebiliyorsanız, loadCSS'yi deneyebilirsiniz

<script>
  // include loadCSS here...
  function loadCSS( href, before, media ){ ... }
  // load a file
  loadCSS( "path/to/mystylesheet.css" );
</script>

3
Örnek 2 Javascript yüklüyor, ancak soru CSS yüklemeyle ilgili. Örnek 2 CSS da çalışır eğer değiştirmek eğer, biliyor musunuz <script>için <style rel=stylesheet>? (Merak ediyorum. loadCSSCSS'yi daha sonra yüklemem gerekirse, bunun yerine (yani örneğiniz 3'ü) kullanacağım .)
KajMagnus

5

Aşağıdaki işlev, eşzamansız olarak yüklemek istediğiniz tüm stil sayfalarını oluşturacak ve belgeye ekleyecektir. (Ancak, sayesinde Event Listener, bunu ancak pencerenin diğer tüm kaynakları yüklendikten sonra yapacak.)

Aşağıdakilere bakın:

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);

1
LoadCSS yaklaşımıyla karşılaştırırsak, bu yöntemin herhangi bir sakıncası var mı? Görünüşe göre, sayfa gövdesindeki etiketin var newStyle = document.createElement("link"); newStyle.rel = "stylesheet"; newStyle.href = "stylesheet.css"; document.getElementsByTagName("head")[0].appendChild(newStyle);içindeki klasik kod , <script>MSIE8 gibi eski tarayıcılarda bile işini mükemmel bir şekilde yapıyor.
TecMan

2
@TecMan evet var. Gördüğünüz gibi, bu işlev window.loadolay üzerinde işini yapıyor . Yani indirme, her şey indirildiğinde başlar. Orada şans yok. Başlamak için mümkün olan en kısa sürede engellemesiz yüklemeye ihtiyacınız var.
Miloš Đakonović

5

Async CSS Yükleme Yaklaşımları

Bir tarayıcının CSS'yi eşzamansız olarak yüklemesinin birkaç yolu vardır, ancak hiçbiri beklediğiniz kadar basit değildir.

<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">

1

Programlı ve eşzamansız olarak bir CSS bağlantısı yüklemeniz gerekiyorsa:

// 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);
}

0

Eğer izin vermeyen bir katı içerik güvenlik politikası varsa vladimir-Salguero @ 'ın cevabı , siz (script not ediniz bunu kullanabilirsiniz 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>

Sadece stil referansına aşağıdakileri ekleyin: media="none" data-async="true". İşte bir örnek:

<link rel="stylesheet" href="../path/script.js" media="none" data-async="true" />

JQuery için örnek:

<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>

asyncBetik etiketinin srceşzamansız olarak yüklenmesi gerekmediği için özniteliğin yok sayıldığını düşünüyorum ... yoksa burada gerçekten yararlı mı? Ayrıca, hangi değerin bir değer olarak kullanılacağı konusunda biraz daha ayrıntı verebilir misiniz nonce?
Philipp

0

Yukarıdakilerin tümü google pagepeed analizlerini şimdi etkilemediği için lütfen yanıtı güncellemeye özen gösterin.

Google'a göre , Css'nin eşzamansız yüklemesini bu şekilde uygulamanız gerekir

 < 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>

1
Bahsettiğim önyükleme anahtar kelime yaklaşımını kullanıyorsanız muhtemelen yanlış pozitif (Sayfa Hızı hatası). github.com/filamentgroup/loadCSS/issues/53
jabacchetta

1
GÜNCELLEME: Google, bu soruna sahip olan PageSpeed ​​sürüm 4'ü kullanımdan kaldırmış ve ardından kapatmıştır - bu eşzamansız kodun önerildiği sürüm buydu. PageSpeed ​​5'te test etmemiş olmama rağmen : şimdi nasıl test ettiklerinin açıklaması ve "bağlantı" nın "önyükleme" etiketini destekledikleri düşünüldüğünde , jabachetta'nın cevabı muhtemelen Google için daha iyi bir cevap.
ToolmakerSteve

1
@ToolmakerSteve Evet Bu yanıtın sık sık denetlenmesi gerekiyor. Ancak bu kod yine de size Sayfa Hızı'nda 100 sağlamaya çalışır.
kaushik gandhi

0

Kullanmayı denedim:

<link rel="preload stylesheet" href="mystyles.css" as="style">

Cezalarla çalışır, ancak aynı zamanda kümülatif düzen değişimini de artırır çünkü rel = "preload" kullandığımızda, sadece css'i indirir, hemen uygulanmaz.

DOM yüklediğinde bir liste ul, li etiketleri içerdiğinde, varsayılan olarak li etiketlerinden önce bir madde işareti bulunduğunda, ardından CSS uygulanmış, bu madde işaretlerini listelemek için özel stillere kaldırdım. Böylece, kümülatif düzen değişimi burada gerçekleşiyor.

Bunun için herhangi bir çözüm var mı?


0

rel="preload"Bağımsız olarak indirmesini sağlamak için kullanın , ardından onload="this.rel='stylesheet'"stil as="style"sayfasına uygulamak için kullanın (stil sayfasına uygulamak gerekir, onloadaksi takdirde işe yaramaz)

<link rel="preload" as="style" type="text/css" href="mystyles.css" onload="this.rel='stylesheet'">
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.