CSS her zaman Javascript'ten önce mi gelmeli?


897

Çevrimiçi sayısız yerde JavaScript'ten önce CSS ekleme önerisini gördüm. Akıl yürütme genellikle bu biçimdedir :

CSS ve JavaScript'inizi sipariş etmek söz konusu olduğunda, CSS'nizin önce gelmesini istersiniz. Bunun nedeni, oluşturma iş parçacığının sayfayı oluşturmak için gereken tüm stil bilgilerine sahip olmasıdır. Önce JavaScript içeriyorsa, JavaScript motorunun sonraki kaynak kümesine devam etmeden önce hepsini ayrıştırması gerekir. Bu, oluşturma iş parçacığının sayfayı tam olarak gösteremeyeceği anlamına gelir, çünkü ihtiyacı olan tüm stillere sahip değildir.

Gerçek testim oldukça farklı bir şey ortaya koyuyor:

Test kayışım

Çeşitli kaynaklar için belirli gecikmeler oluşturmak için aşağıdaki Ruby komut dosyasını kullanın:

require 'rubygems'
require 'eventmachine'
require 'evma_httpserver'
require 'date'

class Handler  < EventMachine::Connection
  include EventMachine::HttpServer

  def process_http_request
    resp = EventMachine::DelegatedHttpResponse.new( self )

    return unless @http_query_string

    path = @http_path_info
    array = @http_query_string.split("&").map{|s| s.split("=")}.flatten
    parsed = Hash[*array]

    delay = parsed["delay"].to_i / 1000.0
    jsdelay = parsed["jsdelay"].to_i

    delay = 5 if (delay > 5)
    jsdelay = 5000 if (jsdelay > 5000)

    delay = 0 if (delay < 0) 
    jsdelay = 0 if (jsdelay < 0)

    # Block which fulfills the request
    operation = proc do
      sleep delay 

      if path.match(/.js$/)
        resp.status = 200
        resp.headers["Content-Type"] = "text/javascript"
        resp.content = "(function(){
            var start = new Date();
            while(new Date() - start < #{jsdelay}){}
          })();"
      end
      if path.match(/.css$/)
        resp.status = 200
        resp.headers["Content-Type"] = "text/css"
        resp.content = "body {font-size: 50px;}"
      end
    end

    # Callback block to execute once the request is fulfilled
    callback = proc do |res|
        resp.send_response
    end

    # Let the thread pool (20 Ruby threads) handle request
    EM.defer(operation, callback)
  end
end

EventMachine::run {
  EventMachine::start_server("0.0.0.0", 8081, Handler)
  puts "Listening..."
}

Yukarıdaki mini sunucu, JavaScript dosyaları (hem sunucu hem de istemci) için keyfi gecikmeler ve keyfi CSS gecikmeleri ayarlamama izin veriyor. Örneğin http://10.0.0.50:8081/test.css?delay=500, CSS aktarımı için 500 ms gecikme veriyor.

Test etmek için aşağıdaki sayfayı kullanıyorum.

<!DOCTYPE html>
<html>
  <head>
      <title>test</title>
      <script type='text/javascript'>
          var startTime = new Date();
      </script>
      <link href="http://10.0.0.50:8081/test.css?delay=500" type="text/css" rel="stylesheet">
      <script type="text/javascript" src="http://10.0.0.50:8081/test2.js?delay=400&amp;jsdelay=1000"></script> 
  </head>
  <body>
    <p>
      Elapsed time is: 
      <script type='text/javascript'>
        document.write(new Date() - startTime);
      </script>
    </p>    
  </body>
</html>

Önce CSS'yi eklediğimde, sayfanın oluşturulması 1.5 saniye sürer:

Önce CSS

Önce JavaScript'i eklediğimde, sayfanın oluşturulması 1,4 saniye sürer:

Önce JavaScript

Chrome, Firefox ve Internet Explorer'da benzer sonuçlar alıyorum. Opera'da ise, sipariş vermek önemli değil.

Görünen şey, JavaScript yorumlayıcısının tüm CSS indirilene kadar başlamayı reddetmesidir. Yani, JavaScript iş parçacığı daha fazla çalışma süresi aldıkça, önce JavaScript içerme özelliğinin daha verimli olduğu görülmektedir.

Bir şey eksik mi, JavaScript içermeden önce CSS içerme önerisi doğru değil mi?

Oluşturma iş parçacığını serbest bırakmak veya JavaScript kodunu altbilgiye koymak veya bir JavaScript yükleyici kullanmak için zaman uyumsuzluk ekleyebileceğimiz veya setTimeout'u kullanabileceğimiz açıktır. Buradaki nokta, temel JavaScript bitlerinin ve CSS bitlerinin kafada sıralanmasıyla ilgilidir.


120
vs 1422 istatiksel olarak anlamlı bir fark mı? Bu yüzde 6. Dikkat çekici-ortalama-insan performans farkı için genel eşik yaklaşık yüzde 20'dir.
Jeff Atwood

15
önemli olan, yeniden sıralamanın bu keyfi gecikmeyi ortadan kaldırmasıdır, gecikmeyi istediğiniz herhangi bir şeye ayarlayabilirsiniz, bu sadece sorunun bir demosudur.
Sam Saffron

3
gecikme 100 ms mıydı? ekran görüntülerinizdeki fark 89 ms'dir. URL'nizde 100ms veya 89ms'ye yakın olan delay=400&amp;jsdelay=1000ve delay=500hiçbir yerde olmayan. Sanırım hangi sayıları kastettiğinizden emin değilim.
Jeff Atwood

4
"Javascript ilk önce geliyorsa, Javascript motoru bir sonraki kaynak kümesine devam etmeden önce hepsini ayrıştırmalıdır. Bu, oluşturma iş parçacığının sayfayı tam olarak gösteremeyeceği anlamına gelir. ." - JS içerme kafasındaysa, JS, CSS içerme işleminden önce veya sonra olsun, sayfa oluşturulmadan önce yürütülür.
nnnnnn

162
Bunu düşündüğünüzden emin değilsiniz, ancak yükleme süresi algısı da önemlidir. Bu nedenle, örneğin, CSS'nin yüklenmesi önce size yalnızca sayfa arka plan rengini / dokusunu bile veriyorsa, daha hızlı görünecektir. Mutlak yükleme süreleri bunun göstergesi olmayabilir.
Rakesh Pai

Yanıtlar:


712

Bu çok ilginç bir soru. CSS'leri her zaman JS'lerimin <link href="...">önüne koydum <script src="...">çünkü "Bir kez daha iyi okudum." Yani haklısın; gerçek araştırma yapmanın tam zamanı!

Düğümde kendi test kayışımı kurdum (aşağıdaki kod). Temel olarak, ben:

  • HTTP önbelleklemesi olmadığından emin olun, böylece her sayfa yüklendiğinde tarayıcının tam indirme yapması gerekir.
  • Gerçekliği simüle etmek için jQuery ve H5BP CSS'yi dahil ettim (bu yüzden ayrıştırılacak iyi miktarda script / CSS var)
  • İki sayfa oluşturun - biri komut dosyasından önce CSS, diğeri koddan sonra CSS ile.
  • Harici komut dosyasının <head>yürütülmesinin ne kadar sürdüğü kaydedildi
  • Satır içi komut dosyasının <body>çalıştırılmasının ne kadar sürdüğünü kaydetti, buna benzer DOMReady.
  • CSS ve / veya komut dosyasını tarayıcıya 500 ms geciktirme.
  • Testi 3 ana tarayıcıda 20 kez çalıştırdı.

Sonuçlar

İlk olarak, CSS dosyası 500 ms gecikmeli olarak:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 583ms  36ms  | 559ms  42ms  | 565ms 49ms
St Dev      | 15ms   12ms  | 9ms    7ms   | 13ms  6ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 584ms  521ms | 559ms  513ms | 565ms 519ms
St Dev      | 15ms   9ms   | 9ms    5ms   | 13ms  7ms

Ardından, jQuery'yi CSS yerine 500ms geciktirecek şekilde ayarladım:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 597ms  556ms | 562ms  559ms | 564ms 564ms
St Dev      | 14ms   12ms  | 11ms   7ms   | 8ms   8ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 598ms  557ms | 563ms  560ms | 564ms 565ms
St Dev      | 14ms   12ms  | 10ms   7ms   | 8ms   8ms

Son olarak, set her iki 500ms tarafından erteleme jQuery ve CSS:

     Browser: Chrome 18    | IE 9         | Firefox 9
         CSS: first  last  | first  last  | first last
=======================================================
Header Exec |              |              |
Average     | 620ms  560ms | 577ms  577ms | 571ms 567ms
St Dev      | 16ms   11ms  | 19ms   9ms   | 9ms   10ms
------------|--------------|--------------|------------
Body Exec   |              |              |
Average     | 623ms  561ms | 578ms  580ms | 571ms 568ms
St Dev      | 18ms   11ms  | 19ms   9ms   | 9ms   10ms

Sonuçlar

İlk olarak, <head>belgenizin içinde (sonuna kadar <body>) komut dosyaları bulunduğunu varsayıyorum . <head>Belgenizin sonuna karşı neden betiklerinizle bağlantı kurabileceğinize dair çeşitli argümanlar var , ancak bu bu cevabın kapsamı dışında. Bu kesinlikle <script>s'nin s'den önce gelip gitmeyeceği <link>ile ilgilidir <head>.

Modern DESKTOP tarayıcılarda, önce CSS'ye bağlanmak asla bir performans kazancı sağlamaz gibi görünüyor . Komut dosyasından sonra CSS koymak, hem CSS hem de komut dosyası geciktiğinde size önemli miktarda kazanç sağlar, ancak CSS geciktiğinde size büyük kazançlar sağlar. ( lastİlk sonuç kümesindeki sütunlar tarafından gösterilir .)

CSS bağlantı geçen zarar performansa görünmüyor ama göz önüne alındığında olabilir belirli koşullar altında kazanç sağlamak harici stil yönlendirmelidir sonra dış komut bağlantısı olan yalnızca masaüstü tarayıcılarda eski tarayıcıların performans bir endişe değilse. Mobil durum için okumaya devam edin.

Neden?

Geçmişte, bir tarayıcı <script>harici bir kaynağa işaret eden bir etiketle karşılaştığında , tarayıcı HTML'yi ayrıştırmayı durdurur , komut dosyasını alır, yürütür ve ardından HTML'yi ayrıştırmaya devam eder. Bunun aksine, tarayıcı <link>harici bir stil sayfası için a ile karşılaşırsa , CSS dosyasını alırken HTML'yi ayrıştırmaya devam eder (paralel olarak).

Bu nedenle, stil sayfalarını ilk önce koymak için yaygın olarak tekrarlanan tavsiyeler - önce indirirler ve indirilecek ilk komut dosyası paralel olarak yüklenebilir.

Bununla birlikte, modern tarayıcılar (yukarıda test ettiğim tüm tarayıcılar dahil) , tarayıcının HTML'de "ileriye baktığı" ve komut dosyaları indirilip yürütülmeden önce kaynakları indirmeye başladığı spekülatif ayrıştırma uyguladı .

Spekülatif ayrıştırma yapılmayan eski tarayıcılarda, komut dosyalarını önce koymak, paralel olarak indirilmeyecekleri için performansı etkileyecektir.

Tarayıcı Desteği

Spekülatif ayrıştırma ilk olarak şu ülkelerde uygulandı: (Ocak 2012 itibariyle bu sürümü kullanan veya daha yüksek bir sürüm olan masaüstü masaüstü kullanıcılarının yüzdesi ile birlikte)

  • Chrome 1 (WebKit 525) (% 100)
  • IE 8 (% 75)
  • Firefox 3.5 (% 96)
  • Safari 4 (% 99)
  • Opera 11.60 (% 85)

Toplamda, günümüzde kullanılan masaüstü tarayıcılarının yaklaşık% 85'i spekülatif yüklemeyi desteklemektedir. Komut dosyalarını CSS'den önce koymak, küresel olarak kullanıcıların% 15'inde performans cezasına sahip olacaktır ; YMMV, sitenizin belirli kitlesini temel alır. (Ve bu sayının küçüldüğünü unutmayın.)

Mobil tarayıcılarda, sadece mobil tarayıcı ve işletim sistemi manzarasının heterojen olması nedeniyle kesin sayıları almak biraz daha zordur. Spekülatif oluşturma WebKit 525'te (Mart 2008'de piyasaya sürüldü) uygulandığından ve hemen hemen her değerli mobil tarayıcı WebKit'e dayandığından, "çoğu" mobil tarayıcının bunu desteklemesi gerektiği sonucuna varabiliriz . Quirksmode'a göre , iOS 2.2 / Android 1.0 WebKit 525 kullanıyor. Windows Phone'un neye benzediğine dair hiçbir fikrim yok.

Ancak, testi Android 4 cihazımda çalıştırdım ve masaüstü sonuçlarına benzer sayılar gördüğümde, Android için Chrome'daki fantastik yeni uzaktan hata ayıklayıcıya bağladım ve Ağ sekmesi tarayıcının gerçekten indirmeyi beklediğini gösterdi JavaScripts tamamen yükleninceye kadar CSS - diğer bir deyişle, Android için WebKit'in en yeni sürümü bile spekülatif ayrıştırmayı desteklemiyor gibi görünüyor. Mobil cihazlarda bulunan CPU, bellek ve / veya ağ kısıtlamaları nedeniyle kapalı olabileceğinden şüpheleniyorum.

kod

Özensizliği affet - bu soru cevaptı.

app.js

var express = require('express')
, app = express.createServer()
, fs = require('fs');

app.listen(90);

var file={};
fs.readdirSync('.').forEach(function(f) {
    console.log(f)
    file[f] = fs.readFileSync(f);
    if (f != 'jquery.js' && f != 'style.css') app.get('/' + f, function(req,res) {
        res.contentType(f);
        res.send(file[f]);
    });
});


app.get('/jquery.js', function(req,res) {
    setTimeout(function() {
        res.contentType('text/javascript');
        res.send(file['jquery.js']);
    }, 500);
});

app.get('/style.css', function(req,res) {
    setTimeout(function() {
        res.contentType('text/css');
        res.send(file['style.css']);
    }, 500);
});


var headresults={
    css: [],
    js: []
}, bodyresults={
    css: [],
    js: []
}
app.post('/result/:type/:time/:exec', function(req,res) {
    headresults[req.params.type].push(parseInt(req.params.time, 10));
    bodyresults[req.params.type].push(parseInt(req.params.exec, 10));
    res.end();
});

app.get('/result/:type', function(req,res) {
    var o = '';
    headresults[req.params.type].forEach(function(i) {
        o+='\n' + i;
    });
    o+='\n';
    bodyresults[req.params.type].forEach(function(i) {
        o+='\n' + i;
    });
    res.send(o);
});

css.html

<!DOCTYPE html>
<html>
    <head>
        <title>CSS first</title>
        <script>var start = Date.now();</script>
        <link rel="stylesheet" href="style.css">
        <script src="jquery.js"></script>
        <script src="test.js"></script>
    </head>
    <body>
        <script>document.write(jsload - start);bodyexec=Date.now()</script>
    </body>
</html>

js.html

<!DOCTYPE html>
<html>
    <head>
        <title>CSS first</title>
        <script>var start = Date.now();</script>
        <script src="jquery.js"></script>
        <script src="test.js"></script>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <script>document.write(jsload - start);bodyexec=Date.now()</script>
    </body>
</html>

test.js

var jsload = Date.now();


$(function() {
    $.post('/result' + location.pathname.replace('.html','') + '/' + (jsload - start) + '/' + (bodyexec - start));
});

jquery.js, jquery-1.7.1.min.js idi.


137
Bu harika bir cevap, bilimi kullandığınız için teşekkürler ! Sonuç olarak "modern tarayıcılarda, CSS'ye bağlanmak hiç bir zaman bir performans kazancı sağlamıyor gibi görünüyor" , soru başlığının cevabının evet olduğunu düşünüyorum, CSS'nin eski tavsiyesi açıkça geçersiz.
Jeff Atwood

@ Josh3736'nın mobil cihazlardaki tersi hakkındaki güncellemesine gelince ... bu, bu önemli değişiklikte silahı atlamamaya işaret eden bir durumdur. Mobil cihazlardaki performans genellikle daha önemli olduğu için diğer mobil tarayıcıların (webkit, gecko, presto, trident vb.) Nasıl davrandığını merak ediyorum.
scunliffe

1
Yavaş bir sunucunun hızlarını simüle etmek için css / js'yi yazdırmak için biraz yavaşlık eklemeyi de denemelisiniz.
kirb

1
"İlk olarak, <head>belgenizin içinde (sonuna kadar <body>) komut dosyaları bulunduğunu varsayıyorum . Cevabın üst kısmında olduğu gibi bunu daha erken vurgulayacağım . Bir dahil scriptiçinde heado harici dosya hemen her perspektiften (kesinlikle bir performans bir) kadar neredeyse hiç doğru ifade eder. Bunu gerçek hayatta yapmak zorunda olduğumu hatırlamıyorum. Garip hat veya iki satır içi hepsi belki senaryo ama. Varsayılan, çok iyi aksine nedenler olmadan , vücudun sonu olmalıdır.
TJ Crowder

1
Aşağı oy, jQuery JavaScript değildir ve yalnızca sayfayı daha fazla şişirir, bu nedenle onu kullanan sonuçlar objektif değildir.
John

303

CSS'yi JavaScript'ten önce koymanın iki ana nedeni vardır.

  1. Eski tarayıcılar (Internet Explorer 6-7, Firefox 2 vb.) Bir komut dosyasını indirmeye başladıklarında sonraki tüm indirmeleri engeller. Eğer a.jsizlediyseniz b.csssırayla indirilir: önce a sonra b. Bunu b.cssizlediyseniz a.js, paralel olarak indirilirler, böylece sayfa daha hızlı yüklenir.

  2. Tüm stil sayfaları indirilene kadar hiçbir şey oluşturulmaz - bu tüm tarayıcılarda geçerlidir. Komut dosyaları farklıdır - sayfadaki komut dosyası etiketinin altındaki tüm DOM öğelerinin oluşturulmasını engellerler . Komut dosyalarınızı HEAD'e koyarsanız, tüm stil sayfaları ve tüm komut dosyaları indirilene kadar tüm sayfanın oluşturulması engellenir. Stil sayfaları için tüm oluşturmayı engellemek mantıklı olsa da (böylece ilk kez doğru stili elde edersiniz ve stilsiz içerik FOUC'un flaşından kaçınırsınız), komut dosyası için tüm sayfanın oluşturulmasını engellemek mantıklı değildir. Genellikle komut dosyaları DOM öğelerini veya DOM öğelerinin yalnızca bir bölümünü etkilemez. Komut dosyalarını sayfada olabildiğince düşük yüklemek, hatta eşzamansız olarak daha iyi yüklemek en iyisidir.

Cuzillion ile örnek oluşturmak eğlencelidir . Örneğin, bu sayfanın HEAD'de bir komut dosyası vardır , bu yüzden indirme işlemi bitene kadar tüm sayfa boş kalır. Ancak, komut dosyasını BODY bloğunun sonuna taşırsak, bu DOM öğelerinin SCRIPT etiketinin üzerinde göründüğünden, bu sayfada gördüğünüz gibi sayfa üstbilgisi oluşturur .


10
Şerefli Steve cevap için beni dövdü, ama bahsettikleri şeyle ilgili bir makale ekleyeceğim: stevesouders.com/blog/2009/04/27/…
Juan Pablo Buritica

4
hangi tarayıcıların bu asyncözelliği desteklediğini görün, Steve'in "onları eşzamansız olarak daha iyi yükle" dediğinde burada önerdiğini görün - stackoverflow.com/questions/1834077/…
Jeff Atwood

Hey, neden herkesin CSS dosyalarını @importdirektiflere bağlayacağını söyleyebilir misiniz ?
Josh Stodola

6
2'nin kaynağı nedir) ve doğruysa, bir sayfanın neden zaman zaman içeriği yüklemeyi bitireceğini açıklayabilir misiniz, o zaman CSS bir veya iki saniye sonra uygulanır? (Bu, nadiren, CSS'nin <head> etiketlerinde bulunduğu kendi sayfalarımda oldu)
Izkata

2
Sayfanın sonuna jQuery+ jQuery UI+ koymalı mıyız $(document).ready(function () { });? Her zaman beklendiği gibi çalışır mı?
Olivier Pons

42

Elde ettiğiniz sonuçlara çok fazla vurgu yapmam, öznel olduğuna inanıyorum, ancak js'den önce CSS'ye koymanın daha iyi olduğunu açıklamak için bir nedenim var.

Web sitenizin yüklenmesi sırasında görebileceğiniz iki senaryo vardır:

DURUM 1: beyaz ekran> stilsiz web sitesi> tarz web sitesi> etkileşim> tarz ve etkileşimli web sitesi

DURUM 2: beyaz ekran> stilsiz web sitesi> etkileşim> tarz web sitesi> tarz ve interaktif web sitesi


Dürüst olmak gerekirse kimse Durum 2'yi seçemiyorum hayal edemiyorum. Yavaş internet bağlantıları kullanan ziyaretçilerin, Javascript kullanarak etkileşime girmelerine izin veren (zaten yüklü olduğu için) bir web sitesi ile karşı karşıya kalacağı. Ayrıca, stilsiz bir web sitesine bakmak için harcanan süre de bu şekilde maksimuma çıkarılacaktır. Neden kimse bunu istesin ki?

Ayrıca jQuery durumları olarak daha iyi çalışır

"CSS stil özelliklerinin değerine dayanan komut dosyaları kullanırken, komut dosyalarına başvurmadan önce harici stil sayfalarına veya gömme stil öğelerine başvurmak önemlidir".

Dosyalar yanlış sırada yüklendiğinde (önce JS, sonra CSS), CSS dosyalarında ayarlanan özelliklere (örneğin bir divin genişliği veya yüksekliği) dayanan herhangi bir Javascript kodu doğru şekilde yüklenmez. Yanlış yükleme sırası ile doğru özelliklerin Javascript tarafından 'bazen' bilindiği anlaşılıyor (belki de bu bir yarış koşulundan kaynaklanıyor mu?). Bu efekt, kullanılan tarayıcıya bağlı olarak daha büyük veya daha küçük görünür.


2
Javascript yürütülmeden önce tüm css'in yüklenmesini nasıl garanti edersiniz? Yapabilir misin? veya javascript'iniz, stillerin yüklenmeyebileceği durumla başa çıkacak kadar sağlam olmalıdır.
Jonnio

@Jonnio JS'nizin bir bağımlılığı varsa, o bağımlılığı açıkça belirtmelisiniz. Aksi takdirde, her zaman nadir zamanlama sorunlarınız olacaktır. ES6 modülleri bunu gerçekleştirmenin iyi bir yoludur, ancak kullanılabilecek birçok kütüphane de vardır.
kmkemp

26

Testleriniz kişisel bilgisayarınızda mı yoksa bir web sunucusunda mı gerçekleştirildi? Boş bir sayfa mı yoksa resimler, veritabanları vb. İçeren karmaşık bir çevrimiçi sistem mi? Komut dosyalarınız basit bir fareyle üzerine gelme olayı gerçekleştiriyor mu, yoksa bunlar web sitenizin kullanıcıyla oluşturma ve etkileşim kurma biçiminin temel bir bileşeni mi? Burada dikkate alınması gereken birkaç şey vardır ve bu önerilerin alaka düzeyi, yüksek kalibreli web geliştirmeye giriştiğinizde neredeyse her zaman kural haline gelir.

Kuralı "alt üst ve yazılara koymak stil" amacı bu, genel olarak, optimum elde etmenin en iyi yolu olduğu aşamalı oluşturmayı , kullanıcı deneyimi açısından çok önemlidir.

Her şey bir yana: testinizin geçerli olduğunu varsayarsak ve gerçekten popüler kurallara aykırı sonuçlar üretiyorsunuz, gerçekten sürpriz olmazdı. Her web sitesi (ve her şeyi bir kullanıcının ekranında göstermek için gereken her şey) farklıdır ve İnternet sürekli olarak gelişmektedir.


1
Cesurca belirttiğiniz noktayı takdir ediyorum, ancak OP, her ikisini de üstte, altta değilken düzeni değiştirdiğinizde neler olduğu hakkında konuşuyor .
nnnnnn

1
Böylece, "testinin geçerli olduğunu varsaymak".
skippr

21

CSS dosyalarını Javascript'ten önce farklı bir nedenden dolayı dahil ediyorum.

Javascript'imin bazı sayfa öğelerinin dinamik boyutlandırmasını yapması gerekiyorsa (CSS'nin gerçekten arkada ana olduğu köşe durumları için), JS ruslaştıktan sonra CSS'nin yüklenmesi, koşulun CSS stillerinden önce yeniden boyutlandırıldığı yarış koşullarına neden olabilir stilleri nihayet başladığında uygulanır ve böylece garip görünüyor. Eğer CSS önceden yüklerseniz şeylerin istenen sırada çalışacağını ve son düzen olmasını istediğim şey olduğunu garanti edebilirim.


2
bu bazı tarayıcılarda bir gün kırılacak. Tahmin etmiyorum.
jcolebrand

1
jcolebrand: Evet, sanırım bunu yazarken yeterince kahve içmemiştim. (Geriye dönük olarak, önemli şeyler sadece CSS'nin dinamik yüklenmesini önlemek ve dinamik boyutlandırma yapmanız gerekiyorsa JS'yi bir domReady olayının içine koymaktan kaçınmaktır)
hugomg

Komut dosyaları herhangi bir görüntüyü değiştirmemelidir. Bu CSS işi. HTML = içerik, CSS = İçerik nasıl görüntülenir, javascript içeriği dinamik olarak değiştirir. Ayrıca js sadece DOMContentLoaded bazı küçük ama çok özel durumlarla çalıştırıldıktan sonra (veya süre) harekete geçmelidir.
brunoais

@brunoais: Bazı mizanpajlar yalnızca Javascript ile oluşturulabilir. Örneğin, dinamik olarak yeniden boyutlandırılması gereken her şey Javascript ile yapılmalıdır ve bazı şeylerin (% 100 - 20px boyutunda olması gibi) eski tarayıcılarda taşınabilir olarak yapılması için Javascript gerekir.
sarılmak

@missingno Bu durumlarda, yine de DOMContentLoaded olayını kullanın. Ama ne demek istediğini anlıyorum. (Aptal IE!)
Brunoais

10

JavaScript'ten önce CSS ekleme önerisi geçersiz mi?

Sadece bir öneri olarak kabul ederseniz değil. Ama bunu sert ve hızlı bir kural olarak görüyor musunuz ?, evet, geçersiz.

Gönderen https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded

Stil sayfası blok komut dosyası yürütmesini yükler, bu nedenle <script> bir <link rel="stylesheet" ...>sayfanız varsa , sayfa ayrıştırmayı bitirmez ve stil sayfası yüklenene kadar DOMContentLoaded tetiklenmez.

Her komut dosyasının neye dayandığını bilmeniz ve komut dosyasının yürütülmesinin doğru tamamlama olayından sonrasına kadar ertelendiğinden emin olmanız gerekir. Komut dosyası yalnızca DOM'a dayanıyorsa, ondomready / domcontentloaded içinde devam edebilir, yüklenecek görüntülere veya uygulanacak stil sayfalarına dayanıyorsa, yukarıdaki referansı doğru okursam, bu kod onload olayına kadar ertelenmelidir.

Bir çorap bedeninin hepsine uyduğunu düşünmüyorum, satılma şekli bu olsa da ve bir ayakkabı bedeninin hepsine uymadığını biliyorum. Ben ilk, stilleri veya komut dosyası yüklemek için kesin bir cevap olduğunu sanmıyorum. Bu, neyin hangi sırayla yüklenmesi gerektiğine ve neyin "kritik yolda" bulunmadığına kadar ertelenebileceğine ilişkin durum kararıdır.

Kullanıcıların sayfa güzelleşene kadar etkileşim yeteneğini ertelemenin daha iyi olduğunu söyleyen gözlemci ile konuşmak. Orada birçoğunuz var ve bunun tersini hisseden muadillerinizi kızdırıyorsunuz. Bir amacı gerçekleştirmek için bir siteye geldiler ve yüklemeyi bitirmenin önemli olmadığı şeyleri beklerken bir siteyle etkileşim kurma yeteneklerini geciktirmek çok sinir bozucu. Yanlış olduğunuzu söylemiyorum, sadece varlığınızı paylaşmayan başka bir grup olduğunu bilmelisiniz.

Bu soru özellikle web sitelerine yerleştirilen tüm reklamlar için geçerlidir. Site yazarları reklam içeriği için yalnızca yer tutucu div oluşturduysa ve reklamları bir onload etkinliğinde enjekte etmeden önce sitelerinin yüklendiğinden ve etkileşimli olduğundan emin olsaydım çok isterim. O zaman bile, şişirilmiş reklamlar yüklenirken site içeriğini kaydırma yeteneğimi bile etkilediğim için, reklamların bir kerede yerine seri olarak yüklendiğini görmek istiyorum. Ama bu sadece bir kişinin bakış açısı.

  • Kullanıcılarınızı ve neye değer verdiğini öğrenin.
  • Kullanıcılarınızı ve hangi tarama ortamını kullandıklarını öğrenin.
  • Her dosyanın ne yaptığını ve ön koşullarının ne olduğunu bilin. Her şeyin işe yaraması hem hız hem de güzelden daha öncelikli olacaktır.
  • Geliştirirken ağ zaman çizgisini gösteren araçları kullanın.
  • Kullanıcılarınızın kullandığı ortamların her birinde test edin. Dinamik olarak (sayfa oluşturulurken sunucu tarafı) yükleme sırasını kullanıcı ortamına göre değiştirmek gerekebilir.
  • Şüphe duyduğunuzda, siparişi değiştirin ve tekrar ölçün.
  • Stilleri ve komut dosyalarını yükleme sırasında birbirine karıştırmak en uygun seçenek olabilir; hepsi değil sonra diğerleri.
  • Sadece dosyaları hangi sırayla yükleyeceğinizi değil, nereye yükleyeceğinizi de deneyin. Kafa mı? Vücutta? Vücut Sonrası? DOM Hazır / Yüklendi mi? Yüklendi?
  • Kullanıcının sayfa ile etkileşime girmeden önce karşılaşacağı net gecikmeyi azaltmak için uygun olduğunda zaman uyumsuzluğu ve erteleme seçeneklerini göz önünde bulundurun. Yardım edip etmediklerini veya incittiklerini belirlemek için test edin.
  • Optimal yük sırasını değerlendirirken daima dikkate alınması gereken değişimler olacaktır. Güzel vs Duyarlı sadece biri.

1
Bağlantılı makale artık "Stil sayfası blok komut dosyası yürütmesini yükler" iddiasında değil. Bu artık doğru değil mi?
Greg

@Greg - Hala doğru. Komut dosyalarının DOM .style özniteliklerini sorgulayabilmesi gerekir, bu nedenle stil sayfaları hala kod yürütülmesini engeller. Onlar belki senaryo engellemeyecek yükleme onlar zekiyseniz, ama script.onLoad olayları engeller.
Jimmy Breck-McKye

10

Güncelleme 2017-12-16

OP'deki testlerden emin değildim. Biraz denemeye karar verdim ve bazı efsaneleri yıktım.

Senkronize <script src...>, indirilip çalıştırılana kadar altındaki kaynakların indirilmesini engeller

Bu artık doğru değil . Chrome 63 tarafından oluşturulan şelaleye bir göz atın:

<head>
<script src="//alias-0.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=1"></script>
<script src="//alias-1.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=2"></script>
<script src="//alias-2.redacted.com/payload.php?type=js&amp;delay=333&amp;rand=3"></script>
</head>

Krom ağ müfettişi -> şelale

<link rel=stylesheet> altındaki komut dosyalarının indirilmesini ve yürütülmesini engellemez

Bu yanlış . Stil indir bloke olmaz ama olacak (script yürütülmesini engellemek burada küçük bir açıklama ). Chrome 63 tarafından oluşturulan performans çizelgesine göz atın:

<link href="//alias-0.redacted.com/payload.php?type=css&amp;delay=666" rel="stylesheet">
<script src="//alias-1.redacted.com/payload.php?type=js&amp;delay=333&amp;block=1000"></script>

Chrome geliştirme araçları -> performans


Yukarıdakileri akılda tutarak, OP'deki sonuçlar aşağıdaki gibi açıklanabilir:

Önce CSS:

CSS Download  500ms:<------------------------------------------------>
JS Download   400ms:<-------------------------------------->
JS Execution 1000ms:                                                  <-------------------------------------------------------------------------------------------------->
DOM Ready   @1500ms:                                                                                                                                                      

Önce JS:

JS Download   400ms:<-------------------------------------->
CSS Download  500ms:<------------------------------------------------>
JS Execution 1000ms:                                        <-------------------------------------------------------------------------------------------------->
DOM Ready   @1400ms:                                                                                                                                            

Bu yüzden document.write (), HTMLDOM için şimdiye kadar yapılmış en kötü fikirlerden biridir.
brunoais

1
The reason is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above. Naturally, it has to wait for styles to load. javascript.info/… Önce JS olması durumunda aynı varsayım neden geçerli değildir? Bana pek mantıklı gelmiyor, infaz edilen JS'nin emri onun amacı hakkında hiçbir şey söylemiyor.
Thorsten Schöning

4

Java script kullanarak test 'render' tam olarak nasıl emin değilim. Ancak bunu düşünün

Sitenizdeki bir sayfa 50k'dir ve bu mantıksız değildir. Sunucunuz batıdayken kullanıcı doğu kıyısındadır. MTU kesinlikle 10k değil, bu yüzden birkaç geziler ileri geri olacak. Sayfanızı ve stil sayfalarınızı almanız 1/2 saniye sürebilir. Genellikle (benim için) javascript (jquery eklentisi ve benzeri) CSS'den çok daha fazladır. Ayrıca internet bağlantınız sayfanın ortasında boğulur ama bunu görmezden geldiğinde ne olur (ara sıra bana ve css render inanıyorum ama% 100 emin değilim).

Css kafasında olduğundan, onu almak için ek bağlantılar olabilir, bu da sayfa yapmadan önce potansiyel olarak bitirilebileceği anlamına gelir. Her neyse, sayfanın geri kalanının yazdığı türdeki ve javascript dosyaları (çok daha fazla bayt olan) sırasında sayfa, sitenin / bağlantının yavaş görünmesini sağlayan düzensizdir.

BÜYÜK JS yorumlayıcı, özellikle sunucudan uzak siteyi güzel görünmesini sağlayacak yapacak css zaman keserken, CSS bitene kadar javascript kodunu indirmek için geçen süre başlamayı reddediyor.

Onun küçük bir optimizasyon ama bunun nedeni.


1
sunucu doğu kıyısında, fwiw olduğunu. Ayrıca, görünüşe göre, şimdi bir CDN kullandıklarının farkında değilsiniz.
jcolebrand

3

İşte yukarıdaki (veya belki aşağıda daha sonra) tüm önemli cevapların bir ÖZETI :

Modern tarayıcılar için, istediğiniz yere css koyun. Html dosyanızı analiz ederler ( spekülatif ayrıştırma diyorlar) ) ve html ayrıştırma ile paralel olarak css indirmeye başlarlar.

Eski tarayıcılar için css'i en üste koymaya devam edin (önce çıplak ama etkileşimli bir sayfa göstermek istemiyorsanız).

Tüm tarayıcılar için, javascript'i olabildiğince uzağa yerleştirin, çünkü html'nizin ayrıştırılmasını durduracaktır. Tercihen, eşzamansız olarak indirin (yani, ajax çağrısı)

Ayrıca, javascript'i ilk sıraya koymanın (CSS'yi ilk sıraya koymanın geleneksel bilgeliğinin aksine) daha iyi performans verdiğini iddia eden belirli bir vaka için bazı deneysel sonuçlar vardır, ancak bunun için mantıklı bir gerekçe yoktur ve yaygın uygulanabilirlikle ilgili doğrulamadan yoksundur, böylece şimdilik görmezden gel.

Yani, soruyu cevaplamak için: Evet. JS'den önce CSS'yi dahil etme önerisi modern tarayıcılar için geçersizdir. CSS'yi istediğiniz yere koyun ve JS'yi mümkün olduğunca sonuna kadar yerleştirin.


1

Steve Souders zaten kesin bir cevap verdi ama ...

Hem Sam'in orijinal testinde hem de Josh'un tekrarında bir sorun olup olmadığını merak ediyorum.

Her iki testin de, TCP bağlantısı kurmanın önemsiz bir maliyete yol açacağı düşük gecikmeli bağlantılarda gerçekleştirildiği görülmektedir.

Bu test sonucunu nasıl etkiler Emin değilim ve 'normal' gecikme bağlantısı üzerinden testler için şelalelere bakmak istiyorum ama ...

İndirilen ilk dosya html sayfası için kullanılan bağlantıyı almalı ve indirilen ikinci dosya yeni bağlantıyı alacaktır. (Erken yıkamak bu dinamiği değiştirir, ancak burada yapılmaz)

Daha yeni tarayıcılarda ikinci TCP bağlantısı spekülatif olarak açılır, böylece bağlantı ek yükü azalır / gider, eski tarayıcılarda bu doğru değildir ve ikinci bağlantının ek yükü açılır.

Bu testlerin sonucunu nasıl / ne şekilde etkilerse emin değilim.


takip etmiyor, inanılmaz derecede nadir olan boru hattınız yoksa, bağlantı kurulumunu azaltmanız pek olası değildir ... testin düşük gecikme süresinde tekrarlanması gerektiğini kabul edin
Sam Saffron

Bu şelale bakarsanız bunu gerekli olmadan Krom Speculatively ikinci bağlantı açılıyor nerede görebilirsiniz webpagetest.org/result/... (IE9 aynısını yapar) ... Doğrusu düşük daha TCP amaçlı Normal gecikme düşünüyordum - ne tür testin yapıldığı ortam nedir?
Andy Davies

2
Re: "Steve Souders zaten kesin bir cevap verdi ama ..." Web evrimi ile ilgili olan şey kesin bir cevap olmaması. :) Komut dosyalarını yüklemek için 3-4 yol vardır ve işler değişir. Gerçek doğru semantik aslında Steve için "Eşzamanlı JavaScript önce CSS koy"
demiş olmalıydı

Evet, ancak çoğu kişi komut dosyalarını eşzamanlı olarak içerir, bu nedenle Steve'in tavsiyesi deneyimsizler için iyidir.
Andy Davies

1

Bunun tüm durumlar için geçerli olmayacağını düşünüyorum. Çünkü css paralel indirecek ama js cant. Aynı durumu düşünün,

Tek bir css yerine 2 veya 3 css dosyası alıp bu yolları deneyin,

1) css..css..js 2) css..js..css 3) js..css..css

Eminim css..css..js diğerlerinden daha iyi sonuç verecektir.


0

Yeni tarayıcıların Javascript motorlarında, ayrıştırıcılarında vb. Çalıştıklarını, genel kod ve biçimlendirme sorunlarını <= IE8 gibi eski tarayıcılarda karşılaşılan sorunların artık sadece işaretleme açısından değil, aynı zamanda JavaScript değişkenleri, eleman seçiciler vb. ile ilgili olarak.


Performans her zaman bir konudur. Spesifikasyonu takip etmeyen tarayıcıların var olduğunu neredeyse görmezden geliyorum. Ben sadece kod takip olanlar tam hızda çalışır ve diğerleri sadece ben öyle çalışır yapmak ki benim kod hazırlamak. Yani, örneğin, sadece IE8'de çalışıyorsa, hepsi tamam.
brunoais

-5

Şahsen ben böyle bir “halk bilgeliği” ne fazla önem vermem. Geçmişte doğru olan şey, şimdi doğru olmayabilir. Bir web sayfasının yorumlanması ve oluşturulmasıyla ilgili tüm işlemlerin tamamen eşzamansız olduğunu (bir şeyi "getirme" ve "buna göre hareket etme"), farklı iş parçacıkları tarafından ele alınabilecek tamamen farklı iki şey olduğunu varsayabilirim . ) ve her durumda tamamen kontrolünüzün veya endişenizin ötesinde.

CSS referanslarını, harici komut dosyalarına yapılan referanslarla birlikte belgenin "head" kısmına koyarım. (Bazı senaryolar vücuda yerleştirilmeyi talep edebilir ve eğer öyleyse onları zorunlu kılar.)

Bunun ötesinde ... "Bu, bu / o tarayıcıda bundan daha hızlı / daha yavaş görünüyor" olarak gözlemlerseniz, bu gözlemi ilginç ama alakasız bir merak olarak ele alıp tasarım kararlarınızı etkilemesine izin vermeyin. Çok fazla şey çok hızlı değişiyor. (Herkes , Firefox ekibinin ürünlerinin başka bir ara yayınıyla çıkmadan önce kaç dakika olacağına bahis oynamak ister ? Evet, ben de.)

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.