Mari kita lihat baris kod ini dahulu:
<script src = "allMyClientSideCode.js"></script>
Ini sedikit... tidak bagus. "Di manakah saya harus meletakkan ini?" pembangun akan tertanya-tanya, "Lebih tinggi, dalam teg
? Atau turun ke bawah, dalam teg Sama ada pendekatan akan membuat skrip kaya. Penghujung tapak adalah tragis?" . Skrip besar dalam teg akan menghentikan semua kerja pemaparan halaman, meninggalkan pengguna dalam keadaan "skrin putih kematian" sehingga skrip dimuatkan. Skrip besar pada penghujung teg hanya akan membenarkan pengguna melihat halaman statik yang tidak bermaya, dan tempat pemaparan sisi klien harus dilakukan berselerak dengan kawalan tidak berfungsi dan kotak kosong.Penyelesaian sempurna untuk masalah ini memerlukan pembahagian dan penaklukan skrip: skrip yang bertanggungjawab untuk menjadikan halaman kelihatan lebih baik dan lebih mudah untuk digunakan harus dimuatkan dengan segera, manakala skrip yang boleh dimuatkan kemudian harus dimuatkan kemudian. Tetapi bagaimana kita boleh menyahmampat skrip ini sambil memastikan ketersediaannya apabila dipanggil?
1. Memahami semula teg
1. Ke mana perginya skrip menyekat?
Versi standard teg
Atas sebab di atas, semakin popular untuk meletakkan skrip pada penghujung teg
Dengan cara ini, dalam satu pihak, pengguna boleh melihat halaman dengan lebih pantas, dan sebaliknya, skrip juga boleh mengakses DOM secara aktif tanpa menunggu peristiwa untuk mencetuskan diri mereka sendiri. Untuk kebanyakan skrip, "langkah" ini merupakan peningkatan yang besar.Tetapi tidak semua skrip dicipta sama. Sebelum menurunkan skrip, tanya diri anda 2 soalan.
Adakah mungkin skrip ini dipanggil terus oleh JavaScript sebaris dalam teg Jawapannya mungkin jelas, tetapi ia masih bernilai diperiksa.
<html> <head> <!--metadata and stylesheets go here --> <script src="headScripts.js"></scripts> </head> <body> <!-- content goes here --> <script src="bodyScripts.js"></script> </body> </html>
Adalah disyorkan untuk meletakkan kebanyakan skrip dalam kerana ini akan membolehkan pengguna melihat halaman web dengan lebih cepat dan mengelakkan overhed untuk mengikat acara "sedia" sebelum memanipulasi DOM. Tetapi kaedah ini juga mempunyai kelemahan, iaitu penyemak imbas tidak boleh memuatkan skrip ini sebelum memuatkan keseluruhan dokumen, yang akan menjadi halangan untuk dokumen besar yang dihantar melalui sambungan perlahan.
Sebaik-baiknya, skrip hendaklah dimuatkan pada masa yang sama semasa dokumen dimuatkan dan tidak menjejaskan pemaparan DOM. Dengan cara ini, anda boleh menjalankan skrip sebaik sahaja dokumen sedia kerana skrip telah dimuatkan dalam susunan teg
添加defer(延迟)属性相当于对浏览器说:“请马上开始加载这个脚本吧,但是,请等到文档就绪且所有此前具有defer 属性的脚本都结束运行之后再运行它。”在文档
标签里放入延迟脚本,既能带来脚本置于标签时的全部好处,又能让大文档的加载速度大幅提升!不足之处就是,并非所有浏览器都支持defer属性。这意味着,如果想确保自己的延迟脚本能在文档加载后运行,就必须将所有延迟脚本的代码都封装在诸如jQuery 之$(document).ready 之类的结构中。
上一节的页面例子改进如下:
<html> <head> <!-- metadata and stylesheets go here --> <script src="headScripts.js"></scripts> <script defer src="deferredScripts.js"></script> </head> <body> <!-- content goes here --> </body> </html>
请记住deferredScripts 的封装很重要,这样即使浏览器不支持defer,deferredScripts 也会在文档就绪事件之后才运行。如果页面主体内容远远超过几千字节,那么付出这点代价是完全值得的。
3、 脚本的并行加载
如果你是斤斤计较到毫秒级页面加载时间的完美主义者,那么defer也许就像是淡而无味的薄盐酱油。你可不想一直等到此前所有的defer 脚本都运行结束,当然也肯定不想等到文档就绪之后才运行这些脚本,你就是想尽快加载并且尽快运行这些脚本。这也正是现代浏览器提供了async(异步)属性的原因。
<script async src = "speedyGonzales.js"> <script async src = "roadRunner.js">
如果说defer 让我们想到一种静静等待文档加载的有序排队场景,那么async 就会让我们想到混乱的无政府状态。前面给出的那两个脚本会以任意次序运行,而且只要JavaScript 引擎可用就会立即运行,而不论文档就绪与否。
对大多数脚本来说,async 是一块难以下咽的鸡肋。async 不像defer那样得到广泛的支持。同时,由于异步脚本会在任意时刻运行,它实在太容易引起海森堡蚁虫之灾了(脚本刚好结束加载时就会蚁虫四起)。
当我们加载一些第三方脚本,而且也不在乎它们谁先运行谁后运行。因此,对这些第三方脚本使用async 属性,相当于一分钱没花就提升了它们的运行速度。
上一个页面示例再添加两个独立的第三方小部件,得到的结果如下:
<html> <head> <!-- metadata and stylesheets go here --> <script src="headScripts.js"></scripts> <script src="deferredScripts.js" defer></script> </head> <body> <!-- content goes here --> <script async defer src="feedbackWidget.js"></script> <script async defer src="chatWidget.js"></script> </body> </html>
这个页面结构清晰展示了脚本的优先次序。对于绝大多数浏览器,DOM的渲染只会延迟至headScripts.js 结束运行时。进行DOM渲染的同时会在后台加载deferredScripts.js。接着,在DOM 渲染结束时将运行deferredScripts.js 和那两个小部件脚本。这两个小部件脚本在那些支持async 的浏览器中会做无序运行。如果不确定这是否妥当,请勿使用async!
二、可编程的脚本加载
虽然