Komut Dosyası Etiketi - zaman uyumsuzluk ve erteleme


547

Niteliklerim asyncve sadece HTML5 tarayıcılarında çalışan etiket deferiçin birkaç sorum var <script>.

Sitelerimden birinde şu anda </body>etiketin hemen üzerinde bulunan iki harici JavaScript dosyası var ; ilk olarak google kaynaklı ve ikincisi yerel bir harici komut dosyasıdır.

Saha yük hızı açısından

  1. asyncSayfanın alt kısmındaki iki komut dosyasına eklemenin bir avantajı var mı ?

  2. asyncİki komut dosyasına seçenek ekleme ve bunları sayfanın en üstüne yerleştirme avantajı olur <head>mu?

  3. Bu, sayfa yüklenirken indirildikleri anlamına mı gelir?
  4. Bunun HTML4 tarayıcıları için gecikmelere neden olacağını, ancak HTML5 tarayıcıları için sayfa yüklenmesini hızlandıracağını varsayıyorum.

kullanma <script defer src=...

  1. Misiniz içinde iki komut yükleme <head>özelliği olan deferaynı önce komut sahip olarak etkileyecek </body>?
  2. Bir kez daha bunun HTML4 tarayıcılarını yavaşlatacağını varsayıyorum.

kullanma <script async src=...

asyncEtkinleştirilmiş iki komut dosyam varsa

  1. Aynı anda indirebilirler mi?
  2. Yoksa sayfanın geri kalanıyla birer birer mi?
  3. Komut dosyalarının sırası sorun yaratır mı? Örneğin, bir komut dosyası diğerine bağlıdır, bu yüzden biri daha hızlı indirirse, ikincisi doğru yürütülmeyebilir vb.

Son olarak, HTML5 daha yaygın bir şekilde kullanılana kadar şeyleri olduğu gibi bırakmak en iyisidir?


5
asyncyeni (ish), ancak deferIE4'ten beri IE'nin bir parçası olmuştur. deferdiğer tarayıcılara çok daha yakın zamanda eklendi, ancak bu tarayıcıların eski sürümleri çok daha az asılı kalıyor.
Alohci

3
Şimdi, HTML5 çok popüler oldu!
sept08

2
deferuzun yıllardır yaygın olan HTML'nin altına komut dosyaları yerleştirmeyle aynıdır .
vsync

1
@vsync mutlaka doğru değildir, tarayıcı komut dosyası etiketini ayrıştırdığında JS'yi erteleme etiketiyle indirir, ancak DOMContentLoaded'den hemen önce exeuction işlemini erteler. İndirme engellenmemektedir. HTML'nin altına yerleştirmek, DOM oluşturuluncaya kadar JS'nin indirilmesini ve yürütülmesini geciktirir, ancak yine de indirme işlemini bekleyerek ek bir gecikme yaşarsınız.
Brad Frost

@BradFrost - İndirme benim görüşüme göre engelliyor, yani internet bant genişliği alıyor ve yavaş bağlantıya sahip olanlar için, önce belgeyi yüklemek için zorunlu olarak görüyorum ve ancak o zaman, oluşturulduğunda, javascript dosyalarını indirmeye başlayın . Bu, içeriğin her şeyi ( SPA gibi ) oluşturmak için javascript'e sıkıca bağlı olmadığı durumlarda geçerlidir
vsync

Yanıtlar:


405

Komut dosyalarınızı daha önce saklayın </body>. Async, birkaç durumda orada bulunan komut dosyalarıyla kullanılabilir (aşağıdaki tartışmaya bakın). Defer, orada bulunan komut dosyaları için fazla bir fark yaratmayacaktır çünkü DOM ayrıştırma işi zaten zaten zaten yapılmıştır.

Asenkron ve erteleme arasındaki farkı açıklayan bir makale: http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/ .

Komut dosyalarını daha önce gövdenin sonunda tutarsanız HTML'niz eski tarayıcılarda daha hızlı görüntülenir </body>. Bu nedenle, eski tarayıcılarda yükleme hızını korumak için, bunları başka bir yere koymak istemezsiniz.

İkinci komut dosyanız ilk komut dosyasına bağlıysa (örn. İkinci komut dosyanız ilk komut dosyasında yüklü jQuery kullanır), yürütme sırasını denetlemek için ek kod olmadan bunları zaman uyumsuz hale getiremezsiniz, ancak erteleme komut dosyaları ertelendiğinden bunları erteleyebilirsiniz hala sırayla yürütülür, belge ayrıştırılıncaya kadar değil. Bu koda sahipseniz ve komut dosyalarının hemen çalıştırılması gerekmiyorsa, bunları zaman uyumsuz hale getirebilir veya erteleyebilirsiniz.

Komut dosyalarını <head>etikete koyabilir ve olarak ayarlayabilirsiniz deferve DOM ayrıştırılana kadar komut dosyalarının yüklenmesi ertelenir ve ertelemeyi destekleyen yeni tarayıcılarda hızlı sayfa görüntüleme elde edilir, ancak size hiç yardımcı olmaz. eski tarayıcılarda ve tüm komut dosyalarında </body>çalışan komut dosyalarını hemen yerleştirmekten daha hızlı değildir . Yani, onları neden daha önce koymanın en iyisi olduğunu görebilirsiniz </body>.

Async, komut dosyasının ne zaman yüklendiğini gerçekten önemsemediğinizde daha kullanışlıdır ve kullanıcıya bağlı başka hiçbir şey komut dosyasının yüklenmesine bağlı değildir. Async'i kullanmak için en sık belirtilen örnek, Google Analytics gibi beklemek istemediğiniz bir analiz komut dosyasıdır ve yakında çalıştırmak acil değildir ve tek başına durur, bu yüzden başka hiçbir şey buna bağlı değildir.

Genellikle jQuery kitaplığı zaman uyumsuzluk için iyi bir aday değildir, çünkü diğer komut dosyaları buna bağlıdır ve sayfanızın kullanıcı olaylarına yanıt vermeye başlayabilmesi için olay işleyicileri yüklemek ve başlangıç ​​durumunu oluşturmak için bazı jQuery tabanlı başlatma kodunu çalıştırmanız gerekebilir sayfası. Zaman uyumsuz olarak kullanılabilir, ancak jQuery yüklenene kadar yürütülememesi için diğer komut dosyalarının kodlanması gerekir.


8
Erteleme, onları hala sırayla çalıştırmalı, ancak dom-içerik yüklenmeden önce çalıştırmalıdır. Bu, kafasına koymanın daha hızlı olacağı anlamına gelmez, çünkü vücut html ayrıştırılmadan ÖNCE onları indirmeye başlayabilir mi?
Kevin

9
Senaryoları koymak headve onları deferkoymak daha önce koymak daha hızlı olmayacak dedin </body>, ama okudum ne yanlış. Bir düşünün - eğer komut dosyalarını yerleştirirseniz <head>, hemen indirmeye başlayacaklar, oysa hemen önce </body>ise diğer tüm öğeler önce indirilir.
Nate

12
@Nate - Belgenizin daha hızlı yüklenmesini sağlamaz. Komut dosyasının daha erken yüklenmesini iyileştirebileceğinden eminsiniz, ancak belgenin ve içeriğinin yüklenmesini yavaşlatabilir, çünkü bant genişliğinizin bir kısmını kullanıyorsunuz ve tarayıcının belirli bir sunucuya yapacağı sınırlı bağlantılardan birini kullanıyorsunuz İçeriğinizi yüklemeye çalışırken komut dosyasını yükleyin.
jfriend00

4
"Eğer ikinci betiğiniz ilk betiğe bağlıysa ... o zaman onları zaman uyumsuz ya da erteleme yapamazsınız" - bu doğru değil, sırayla yürüttükleri erteleme ile.
DisgruntledGoat

2
Bu noktada, </body> şartı, bu cevabın yayınlandığı 2012 yılından bu yana tarayıcı geliştirmelerinde gerçekten gerekli değildir.
bgcode

843

Bu resim normal komut dosyası etiketini, zaman uyumsuzluğu ve ertelemeyi açıklar

resim açıklamasını buraya girin

  • Async komut dosyaları, komut dosyası yüklenir yüklenmez yürütülür, bu nedenle yürütme sırasını garanti etmez (sonuna eklediğiniz bir komut dosyası ilk komut dosyasından önce yürütülebilir)

  • Erteleme komut dosyaları, sayfada göründükleri yürütme sırasını garanti eder.

Bu bağlantıya bakın: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html


Bence birden fazla komut dosyası içeren bir örnek onların sırasını göstermek için daha iyi olurdu
vsync

4
@writofmandamus Görünüşe göre asynckazanacak. Bkz. Stackoverflow.com/questions/13821151/…
Monsignor

İyi açıklama için teşekkürler. Ancak görüntüler ölçeklendirilmez. Yalnızca <script>etiket olması durumunda, sayfa yükünün toplam uzunluğu komut dosyasının indirilmesi için geçen süre uzar.
arni

@BhavikHirani Bu siteye göre , aynı kod etiketinde hem eşzamansız hem de ertelemeyi kullanmak, tarayıcı destekliyorsa eşzamansız kullanır veya eşzamansızlığı desteklemiyorsa, ertelemeyi destekliyorsa ertelenmeye geri döner. Davranışlar oldukça farklıdır, bu yüzden sonuç tahmin edilemez olduğundan ve hatalar için harika bir kaynak olabileceğinden, her ikisini de kullanmanızı tavsiye etmem.
Adrian Wiik

@arni Yalnızca bant genişliği tam olarak kullanılırsa, nadiren kullanılır. Ve her iki indirme de bant genişliğini paylaşır, birini engellemez. - Dahası: bu görüntüler indirmeyi değil yeşil olarak ayrışmayı gösterir.
Robert Siemer

213

HTML5: async,defer

HTML5'te tarayıcıya JavaScript kodunuzu ne zaman çalıştırmanız gerektiğini söyleyebilirsiniz. 3 olasılık vardır:

<script       src="myscript.js"></script>

<script async src="myscript.js"></script>

<script defer src="myscript.js"></script>
  1. asyncVeya olmadan defer, tarayıcı komut dizisi etiketinizin altındaki öğeleri oluşturmadan önce komut dosyanızı hemen çalıştırır.

  2. İle async(asenkron), tarayıcı HTML sayfası yükleme ve tarayıcı yükü ederken işlemek ve aynı zamanda senaryoyu yürütmek için devam edecektir.

  3. İle defer, sayfa ayrıştırmayı bitirdiğinde tarayıcı komut dosyanızı çalıştıracaktır. (tüm resim dosyalarını indirmeyi bitirmek gerekli değildir. Bu iyidir.)


blogger.com şablonu, async=""şablon değişikliklerini doğrulamak ve kaydetmek için gereklidir .
noobninja

1
Not: komut dosyalarının Async kullanılarak belirtildikleri sırayla çalışacağının garantisi yoktur. "Yani ikinci betiğiniz ilk betiğe bağlıysa Async'ten kaçının."
Faisal Naseer

2
async- Komut dosyaları , HTML dosyasındaki sıraları dikkate alınmadan indirildikleri anda yürütülür .
vsync

30

Hem asyncve deferkomut ayrıştırıcı ve her iki destek opsiyonel duraklamadan hemen indirilmeye başladığını onloadsenaryo bağlıdır başlatma gerçekleştirmek için ortak gereksinimi karşılamak için işleyici.

Komut dosyası yürütüldüğünde asyncve deferetrafındaki fark ortalanır. Her asynckomut dosyası, indirmeyi tamamladıktan sonra ve pencerenin load olayından önce ilk fırsatta yürütülür. Bu, asynckomut dosyalarının sayfada göründükleri sırayla yürütülemedikleri (ve büyük olasılıkla) anlamına gelir . Oysa deferkomut, diğer taraftan, sayfanın meydana sırayla yürütülecek garanti edilir. Bu yürütme, ayrıştırma işlemi tamamlandıktan sonra, ancak belgenin DOMContentLoadedolayından önce başlar .

Kaynak ve diğer ayrıntılar: burada .


25

Aynı tür bir sorunla karşı karşıya ve şimdi her ikisinin de nasıl çalışacağını açıkça anladım.

zaman uyumsuz

Kod etiketinize zaman uyumsuzluk özelliği eklediğinizde aşağıdakiler gerçekleşir.

<script src="myfile1.js" async></script>
<script src="myfile2.js" async></script>
  1. Dosyaları getirmek için paralel istekler yapın.
  2. Belgeyi hiç kesilmemiş gibi ayrıştırmaya devam edin.
  3. Dosyalar indirilince tek tek komut dosyalarını yürütün.

ertele

Erteleme, büyük bir farklılıkla asenkronize çok benzer. Bir tarayıcı erteleme özniteliğine sahip bir komut dosyasıyla karşılaştığında şunlar olur.

<script src="myfile1.js" defer></script>
<script src="myfile2.js" defer></script>
  1. Tek tek dosyaları almak için paralel istekler yapın.
  2. Belgeyi hiç kesilmemiş gibi ayrıştırmaya devam edin.
  3. Komut dosyası dosyaları indirilmiş olsa bile belgeyi ayrıştırmayı bitirin.
  4. Her komut dosyasını belgede karşılaştıkları sırayla yürütün.

Referans: Async ve Defer arasındaki fark


7

asyncve deferHTML ayrıştırma sırasında dosyayı indirir. Her ikisi de ayrıştırıcıyı kesmez.

  • asyncÖzniteliğe sahip komut dosyası indirildikten sonra yürütülür. Ilişkili komut dosyası deferDOM ayrıştırma işlemi tamamlandıktan sonra yürütülür.

  • Yüklenen komut dosyaları asyncherhangi bir sipariş garantisi vermez. deferÖzniteliğe sahip komut dosyaları DOM'da göründükleri sırayı korur.

<script async>Komut dosyası hiçbir şeye güvenmediğinde kullanın . komut dosyası kullanıma bağlı olduğunda.

En iyi çözüm, vücudun alt kısmına eklemek olacaktır.Konaklama veya oluşturma ile ilgili bir sorun olmayacaktır.


Burada biraz açıklama yapmak istiyorum, burada iki şey oluyor 1. Kaynağın indirilmesi 2. Kaynağın yürütülmesi. Her iki durumda da (async ve erteleme) kaynak indirme engellenmez, yani html'nin ayrıştırılmasını engellemezler, async'de yürütme ayrıştırmayı engeller ve erteleme durumunda, html işaretlemesi ayrıştırıldıktan sonra yürütme gerçekleşir, dolayısıyla bu durumda tıkanmaz.
08:06

5

Sanırım Jake Archibald 2013'te bize konuya daha da fazla pozitiflik katabilecek bazı görüşler sundu:

https://www.html5rocks.com/en/tutorials/speed/script-loading/

Kutsal kâse, oluşturmayı engellemeden hemen bir dizi komut dosyası indiriyor ve eklendikleri sırayla en kısa sürede yürütüyor. Ne yazık ki HTML sizden nefret ediyor ve bunu yapmanıza izin vermiyor.

(...)

Komut dosyası yükleme bölümünün altında gizlenmiş olmasına rağmen, cevap aslında HTML5 spesifikasyonundadır. " Eşzamansız IDL özniteliği, öğenin eşzamansız olarak yürütülüp yürütülmeyeceğini denetler. Öğenin" zaman uyumsuz "bayrağı ayarlanırsa, alma işleminde, zaman uyumsuz IDL özelliğinin true değerini ve ayarlandığında" zorla senkronize edilmemesi "gerekir bayrak önce ayarlanmamış olmalıdır… ".

(...)

Dinamik olarak oluşturulan ve belgeye eklenen komut dosyaları varsayılan olarak zaman uyumsuzdur, indirilmeleri engellemez ve yürütülmez çalıştırılmaz, yani yanlış sırada ortaya çıkabilirler. Ancak, bunları açıkça eşzamansız değil olarak işaretleyebiliriz:

[
    '//other-domain.com/1.js',
    '2.js'
].forEach(function(src) {
    var script = document.createElement('script');
    script.src = src;
    script.async = false;
    document.head.appendChild(script);
});

Bu, komut dosyalarımıza düz HTML ile gerçekleştirilemeyen bir davranış karışımı sağlar. Açıkça zaman uyumsuz olmamakla birlikte, komut dosyaları bir yürütme kuyruğuna, ilk düz HTML örneğimizde eklendikleri kuyruğa eklenir. Bununla birlikte, dinamik olarak oluşturularak, belge ayrıştırma işleminin dışında yürütülürler, bu nedenle oluşturma işlemi indirildiklerinde engellenmez (zaman uyumsuz komut dosyası yüklemesini XHR senkronizasyonu ile karıştırmayın, bu asla iyi bir şey değildir).

Yukarıdaki komut dosyası sayfaların başına satır içi olarak eklenmeli, komut dosyası yüklemelerini aşamalı oluşturmayı kesintiye uğratmadan mümkün olan en kısa sürede kuyruğa almalı ve belirttiğiniz sırayla en kısa sürede yürütülmelidir. “2.js”, “1.js” den önce ücretsiz olarak indirilebilir, ancak “1.js” başarıyla indirilip çalıştırılana veya hiçbiri başarısız oluncaya kadar yürütülmez. Yaşa! async-download ama sipariş-yürütme !

Yine de, komut dosyalarını yüklemenin en hızlı yolu bu olmayabilir:

(...) Yukarıdaki örnekte, hangi komut dosyalarının indirileceğini bulmak için tarayıcının betiği ayrıştırması ve yürütmesi gerekir. Bu, komut dosyalarınızı önceden yüklenmiş tarayıcılardan gizler. Tarayıcılar bu tarayıcıları bir sonraki ziyaret etme olasılığınızdaki sayfalardaki kaynakları keşfetmek veya ayrıştırıcı başka bir kaynak tarafından engellenirken sayfa kaynaklarını keşfetmek için kullanır.

Bunu belgenin başına koyarak keşfedilebilirliği tekrar ekleyebiliriz:

<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">

Bu tarayıcıya sayfanın 1.js ve 2.js'ye ihtiyacı olduğunu söyler. link [rel = subresource], link [rel = prefetch] 'e benzer, ancak farklı anlambilim içerir. Maalesef şu anda yalnızca Chrome'da destekleniyor ve hangi komut dosyalarının iki kez, bir kez bağlantı öğeleri aracılığıyla ve tekrar komut dosyanızda yükleneceğini bildirmeniz gerekiyor.

Düzeltme: Başlangıçta bunların önyükleme tarayıcısı tarafından alındığını, normal ayrıştırıcı tarafından alındıklarını söylemiştim. Ancak, önyükleme tarayıcısı bunları alabilir, henüz çalıştırılmaz, ancak yürütülebilir kodun içerdiği komut dosyaları hiçbir zaman önceden yüklenemez. Yorumlarda beni düzelten Yoav Weiss'a teşekkürler.


1

Erteleme ve zaman uyumsuz davranışı, en azından yürütme aşamasında tarayıcıya bağımlı görünüyor. NOT, erteleme yalnızca harici komut dosyaları için geçerlidir. Async'in aynı kalıbı takip ettiğini varsayıyorum.

IE 11 ve daha önceki sürümlerde, sıra şu şekildedir:

  • zaman uyumsuz (sayfa yüklenirken kısmen çalıştırılabilir)
  • yok (sayfa yüklenirken çalıştırılabilir)
  • ertele (sayfa yüklendikten sonra yürütülür, tümü dosyaya yerleştirme sırasına göre ertelenir)

Edge, Webkit, vb. 'De, zaman uyumsuz özellik yoksayılmış veya sonuna yerleştirilmiş gibi görünüyor:

  • data-pagespeed-no-erteleme (sayfa yüklenirken diğer komut dosyalarından önce yürütülür)
  • yok (sayfa yüklenirken yürütülebilir)
  • erteleme (DOM yüklenene kadar bekler, tümü dosyaya yerleştirme sırasına göre ertelenir)
  • zaman uyumsuz (DOM yüklenene kadar bekliyor gibi görünüyor)

Daha yeni tarayıcılarda, data-pagespeed-no-erteleme özelliği diğer harici komut dosyalarından önce çalışır. Bu, DOM'ye bağlı olmayan komut dosyaları içindir.

NOT: Harici komut dosyalarınızın yürütülmesi için açık bir sıraya ihtiyacınız olduğunda erteleme işlevini kullanın. Bu, tarayıcıya, ertelenen tüm komut dosyalarını dosyaya yerleştirme sırasına göre yürütmesini bildirir.

ASIDE: Harici javascriptlerin boyutu yüklenirken önemliydi ... ancak yürütme sırası üzerinde hiçbir etkisi olmadı.

Komut dosyalarınızın performansı konusunda endişeleriniz varsa, küçültmeyi veya XMLHttpRequest ile dinamik olarak yüklemeyi düşünebilirsiniz.


data-pagespeed-no-defersunucu tarafı PageSpeed ​​modülü tarafından kullanılan bir özelliktir . Kendisinin data-pagespeed-no-deferniteliğinin herhangi bir tarayıcıda hiçbir etkisi yoktur.
Qtax
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.