ประสิทธิภาพของ JavaScript ในเบราว์เซอร์อาจกล่าวได้ว่าเป็นปัญหาการใช้งานที่สำคัญที่สุดที่นักพัฒนาส่วนหน้าต้องเผชิญ
ในบรรดากฎ Yslow23 ของ Yahoo หนึ่งในนั้นคือการวาง JS ไว้ที่ด้านล่าง เหตุผลก็คือในความเป็นจริงเบราว์เซอร์ส่วนใหญ่ใช้กระบวนการเดียวในการดำเนินการหลายงานเช่น UI และการอัพเดท JavaScript รันและงานเดียวเท่านั้นที่ดำเนินการในเวลาเดียวกัน JavaScript ทำงานนานแค่ไหนใช้เวลารอนานแค่ไหนก่อนที่เบราว์เซอร์จะไม่ได้ใช้งานเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้
จากมุมมองพื้นฐานซึ่งหมายความว่าการปรากฏตัวของแท็ก <Script> ทำให้หน้าทั้งหมดรอเนื่องจากการแยกวิเคราะห์สคริปต์และการทำงาน ไม่ว่ารหัสจาวาสคริปต์ที่แท้จริงจะถูก inlined หรือมีอยู่ในไฟล์ภายนอกที่ไม่เกี่ยวข้องหรือไม่กระบวนการดาวน์โหลดหน้าและการแยกวิเคราะห์จะต้องหยุดและรอให้สคริปต์เสร็จสิ้นการประมวลผลเหล่านี้ก่อนดำเนินการต่อ นี่เป็นส่วนสำคัญของวัฏจักรชีวิตของหน้าเนื่องจากสคริปต์อาจแก้ไขเนื้อหาหน้าเว็บในระหว่างการรันไทม์ ตัวอย่างทั่วไปคือฟังก์ชั่น document.write () ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
<html>
<head>
<title> ตัวอย่างสคริปต์ </title>
</head>
<body>
<p>
<script type = "text/javascript">
document.write ("วันที่คือ" + (วันที่ใหม่ ()). todatestring ());
</script>
</p>
</body>
</html>
เมื่อเบราว์เซอร์พบแท็ก <script> เช่นเดียวกับในหน้า HTML ด้านบนมันเป็นไปไม่ได้ที่จะทำนายว่า JavaScript เพิ่มเนื้อหาลงในแท็ก <p> หรือไม่ ดังนั้นเบราว์เซอร์จะหยุดรันรหัส JavaScript นี้จากนั้นยังคงแยกวิเคราะห์และแปลหน้าเว็บต่อไป สิ่งเดียวกันนี้เกิดขึ้นเมื่อโหลด JavaScript โดยใช้คุณสมบัติ SRC เบราว์เซอร์จะต้องดาวน์โหลดรหัสสำหรับไฟล์ภายนอกก่อนซึ่งต้องใช้เวลาสักครู่แล้วแยกวิเคราะห์และเรียกใช้รหัสนี้ ในระหว่างกระบวนการนี้การแยกวิเคราะห์หน้าและการโต้ตอบของผู้ใช้จะถูกบล็อกอย่างสมบูรณ์
เนื่องจากสคริปต์บล็อกกระบวนการดาวน์โหลดของทรัพยากรหน้าอื่นวิธีที่แนะนำคือ: วางแท็กทั้งหมด <script> ใกล้กับด้านล่างของแท็ก <body> ให้มากที่สุดเพื่อลดผลกระทบต่อการดาวน์โหลดทั้งหน้า ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
<html>
<head>
<title> ตัวอย่างสคริปต์ </title>
<link rel = "stylesheet" type = "text/css" href = "styles.css">
</head>
<body>
<p> สวัสดีโลก! </p>
<-ตัวอย่างการวางตำแหน่งสคริปต์ที่แนะนำ->
<script type = "text/javascript" src = "file1.js"> </script>
<script type = "text/javascript" src = "file2.js"> </script>
<script type = "text/javascript" src = "file3.js"> </script>
</body>
</html>
รหัสนี้แสดงตำแหน่งที่แท็ก <Script> ที่แนะนำอยู่ในไฟล์ HTML แม้ว่าการดาวน์โหลดสคริปต์จะถูกบล็อกระหว่างกัน แต่หน้าเว็บได้รับการดาวน์โหลดและแสดงต่อหน้าผู้ใช้และความเร็วในการป้อนหน้าจะไม่ปรากฏช้าเกินไป นี่คือสิ่งที่กล่าวถึงข้างต้นเพื่อนำ JS ไปด้านล่าง
นอกจากนี้ Yahoo! สร้าง "Federal Handle" สำหรับ "Yahoo! ส่วนต่อประสานผู้ใช้ของเขา Library, Yui" ซึ่งนำไปใช้ผ่าน "เครือข่ายการส่งเนื้อหา (CDN) เว็บไซต์ใด ๆ สามารถใช้ URL" Federal Handle "เพื่อระบุไฟล์ที่รวมอยู่ในแพ็คเกจไฟล์ YUI ตัวอย่างเช่น URL ต่อไปนี้มีไฟล์สองไฟล์:
การคัดลอกรหัสมีดังนี้:
<script type = "text/javascript" src = "http://yui.yahooapis.com/combo?2.7.0/build/yahoo/yahoo-min.js&2.7.0/build/event/event-min.js"
URL นี้เรียกไฟล์ yahoo-min.js และ event-min.js ในเวอร์ชัน 2.7.0 ไฟล์เหล่านี้เป็นสองไฟล์แยกกันบนเซิร์ฟเวอร์ แต่เมื่อเซิร์ฟเวอร์ได้รับคำขอ URL นี้ไฟล์ทั้งสองจะถูกรวมเข้าด้วยกันและส่งกลับไปยังไคลเอนต์ ด้วยวิธีนี้ไม่จำเป็นต้องใช้แท็ก <Script> สองแท็กอีกต่อไป (ไฟล์หนึ่งไฟล์ถูกโหลดสำหรับแต่ละแท็ก) และแท็ก <Script> หนึ่งแท็กสามารถโหลดได้ นี่เป็นวิธีที่ดีที่สุดในการรวมจาวาสคริปต์ภายนอกหลายตัวในหน้า HTML
สคริปต์ขุนนาง
ข้างต้นเป็นวิธีที่ดีที่สุดในการโหลดสคริปต์ JavaScript หลายตัวในสถานะเริ่มต้นของหน้า JavaScript มีแนวโน้มที่จะบล็อกกระบวนการประมวลผลเบราว์เซอร์บางอย่างเช่นคำขอ HTTP และการรีเฟรชอินเตอร์เฟสซึ่งเป็นปัญหาด้านประสิทธิภาพที่สำคัญที่สุดที่นักพัฒนาต้องเผชิญ การรักษาไฟล์ JavaScript ให้สั้นและ จำกัด จำนวนคำขอ HTTP เป็นเพียงขั้นตอนแรกในการสร้างเว็บแอปพลิเคชันที่ตอบสนอง
แต่เช่นหน้าเว็บขนาดใหญ่ที่มีรหัส JS จำนวนมากการรักษาซอร์สโค้ดให้สั้นนั้นไม่ใช่ตัวเลือกที่ดีที่สุดเสมอไป ดังนั้นสคริปต์ที่ไม่ปิดกั้นเข้ามาเป็นสิ่งที่เราต้องการคือการค่อยๆเพิ่มจาวาสคริปต์ลงในหน้าซึ่งจะไม่ปิดกั้นเบราว์เซอร์ในระดับหนึ่ง
คีย์ที่จะไม่ปิดกั้นสคริปต์คือการโหลดซอร์สโค้ด JavaScript หลังจากโหลดหน้าเว็บซึ่งหมายความว่าการดาวน์โหลดรหัสเริ่มต้นหลังจากเหตุการณ์การโหลดของหน้าต่างออก
คำอธิบายที่เกี่ยวข้อง:
เหตุการณ์โหลดของหน้าต่างจะถูกยิงเพียงครั้งเดียวและเพียงครั้งเดียวหลังจากโหลดหน้าเว็บเท่านั้น
window.onload = function () {} ต้องรอเนื้อหาทั้งหมดในหน้าเว็บเพื่อโหลด (รวมถึงไฟล์ที่เกี่ยวข้องทั้งหมดขององค์ประกอบเช่นรูปภาพ) ที่จะดำเนินการนั่นคือ JavaScript สามารถเข้าถึงองค์ประกอบใด ๆ ในหน้าในเวลานี้
วิธีการต่อไปนี้คือ:
สคริปต์รอการตัดบัญชีรอการตัดบัญชี
HTML4 กำหนดแอตทริบิวต์เพิ่มเติมสำหรับแท็ก <Script>: DEFER
แอตทริบิวต์การเลื่อนเวลานี้บ่งชี้ว่าสคริปต์ที่มีอยู่ในองค์ประกอบไม่ได้ตั้งใจจะแก้ไข DOM ดังนั้นรหัสสามารถดำเนินการได้ในภายหลัง แอตทริบิวต์การเลื่อนเวลาได้รับการสนับสนุนโดย Internet Explorer 4+ และ Firefox 3.5+ เท่านั้นและไม่ใช่โซลูชันข้ามเบราว์เซอร์ในอุดมคติ ในเบราว์เซอร์อื่น ๆ แอตทริบิวต์การเลื่อนเวลาจะถูกละเว้น ดังนั้นแท็ก <script> จะถูกประมวลผลในวิธีเริ่มต้นปกติซึ่งหมายความว่าจะทำให้เกิดการอุดตัน หากได้รับการสนับสนุนจากเบราว์เซอร์กระแสหลักต่างๆนี่ยังคงเป็นทางออกที่มีประสิทธิภาพ
การคัดลอกรหัสมีดังนี้:
<script type = "text/javascript" src = "file1.js" defer> </script>
แท็ก <script> พร้อมแอตทริบิวต์การเลื่อนเวลาสามารถวางได้ทุกที่ในเอกสารและจะเริ่มการดาวน์โหลดเมื่อมีการแยกวิเคราะห์จนกระทั่งโหลด DOM (ก่อนที่จะเรียกว่ามือจับเหตุการณ์ OnLoad) เมื่อดาวน์โหลดไฟล์ JavaScript ที่เลื่อนออกไปจะไม่บล็อกกระบวนการประมวลผลอื่น ๆ ในเบราว์เซอร์ดังนั้นไฟล์เหล่านี้สามารถดาวน์โหลดได้ควบคู่ไปกับแหล่งข้อมูลอื่น ๆ
คุณสามารถใช้รหัสต่อไปนี้เพื่อทดสอบว่าเบราว์เซอร์รองรับแอตทริบิวต์การเลื่อนเวลา:
การคัดลอกรหัสมีดังนี้:
<html>
<head>
<title> ตัวอย่างสคริปต์เลื่อนตัวอย่าง </title>
</head>
<body>
<Script Defer> Alert ("Defer"); </script>
<script> Alert ("สคริปต์"); </script>
<script> window.onload = function () {alert ("โหลด");}; </script>
</body>
</html>
หากเบราว์เซอร์ไม่รองรับการเลื่อนเวลาของกล่องโต้ตอบป๊อปอัพคือ "เลื่อนเวลา", "สคริปต์" และ "โหลด"
หากเบราว์เซอร์รองรับการเลื่อนเวลาของกล่องโต้ตอบป๊อปอัพคือ "สคริปต์", "โหลด", "เลื่อน"
องค์ประกอบสคริปต์แบบไดนามิก
DOM ช่วยให้เราสามารถสร้างเนื้อหาเอกสารเกือบทั้งหมดของ HTML โดยใช้ JavaScript และองค์ประกอบ <Script> ใหม่สามารถสร้างได้อย่างง่ายดายผ่าน DOM มาตรฐาน:
การคัดลอกรหัสมีดังนี้:
1 var script = document.createElement ("สคริปต์");
2 script.type = "text/javascript";
3 script.src = "file1.js";
4 document.body.appendchild (สคริปต์);
องค์ประกอบ <Script> ใหม่โหลดไฟล์ต้นฉบับ File1.js ดาวน์โหลดไฟล์นี้ทันทีหลังจากเพิ่มองค์ประกอบลงในหน้า จุดสำคัญของเทคโนโลยีนี้คือไม่ว่าการดาวน์โหลดจะเริ่มต้นที่ใดการดาวน์โหลดและการรันของไฟล์จะไม่บล็อกการประมวลผลหน้าอื่น
เมื่อไฟล์ถูกดาวน์โหลดโดยใช้โหนดสคริปต์แบบไดนามิกโค้ดที่ส่งคืนมักจะถูกเรียกใช้งานทันที (ยกเว้น Firefox และ Opera ซึ่งจะรอให้การดำเนินการของสคริปต์แบบไดนามิกก่อนหน้านี้ทั้งหมดจะถูกดำเนินการ)
ในกรณีส่วนใหญ่เราหวังว่าจะเรียกฟังก์ชั่นเพื่อใช้การดาวน์โหลดแบบไดนามิกของไฟล์ JavaScript การห่อหุ้มฟังก์ชั่นต่อไปนี้ใช้การใช้งานมาตรฐานและการใช้งานเช่น:
การคัดลอกรหัสมีดังนี้:
function loadscript (url, callback) {
var script = document.createElement ("สคริปต์");
script.type = "text/javascript";
if (script.readyState) {// เช่น
script.onreadyStateChange = function () {
if (script.readyState == "โหลด" || script.readyState == "เสร็จสมบูรณ์") {
script.onreadystatechange = null;
การโทรกลับ ();
-
-
-
else {// อื่น ๆ
script.onload = function () {callback ();
-
-
script.src = url;
document.getElementByTagname ("head") [0] .AppendChild (สคริปต์);
-
loadscript ("file1.js", function () {// call
การแจ้งเตือน ("ไฟล์ถูกโหลด!");
-
ฟังก์ชั่นนี้ยอมรับพารามิเตอร์สองพารามิเตอร์: URL ของไฟล์ JavaScript และฟังก์ชันการเรียกกลับที่ถูกเรียกใช้เมื่อการรับ JavaScript เสร็จสิ้น การตรวจสอบแอตทริบิวต์ใช้เพื่อกำหนดเหตุการณ์ที่จะตรวจสอบ ขั้นตอนสุดท้ายคือแอตทริบิวต์ SRC และเพิ่มไฟล์ JavaScript ลงในหัว
การโหลดสคริปต์แบบไดนามิกเป็นรูปแบบที่ใช้กันมากที่สุดในการดาวน์โหลด JavaScript ที่ไม่ปิดกั้นเนื่องจากสามารถข้ามเบราว์เซอร์และใช้งานง่าย
การฉีดสคริปต์สคริปต์ xmlhttprequest การฉีดสคริปต์ XHR
อีกวิธีหนึ่งในการรับสคริปต์ด้วยวิธีที่ไม่ปิดกั้นคือการฉีดสคริปต์ลงในหน้าโดยใช้วัตถุ XMLHTTTPREQUEST (XHR) เทคนิคนี้จะสร้างวัตถุ XHR ก่อนจากนั้นดาวน์โหลดไฟล์ JavaScript แล้วฉีดรหัส JavaScript ลงในหน้าด้วยองค์ประกอบ <Script> แบบไดนามิก ดูการสาธิต:
การคัดลอกรหัสมีดังนี้:
var xhr = ใหม่ xmlhttprequest ();
xhr.open ("รับ", "file1.js", จริง);
xhr.onreadyStateChange = function () {
if (xhr.readystate == 4) {
if (xhr.status> = 200 && xhr.status <300 || xhr.status == 304) {// ตรวจสอบรหัสสถานะ http
var script = document.createElement ("สคริปต์");
script.type = "text/javascript";
script.text = xhr.responsetext;
document.body.appendchild (สคริปต์);
-
-
-
XHR.Send (NULL);
รหัสนี้จะส่งคำขอ Get File ไปยังเซิร์ฟเวอร์เพื่อรับ file1.js ตัวจัดการเหตุการณ์ onreadystatechange ตรวจสอบว่า ReadyState เป็น 4 หรือไม่จากนั้นตรวจสอบว่ารหัสสถานะ HTTP นั้นถูกต้องหรือไม่ (200 หมายถึงการยืนยันว่าคำขอของลูกค้าประสบความสำเร็จ 2xx หมายถึงการตอบสนองที่ถูกต้องและ 304 หมายถึงการตอบกลับที่แคช) หากได้รับการตอบกลับที่ถูกต้ององค์ประกอบ <Script> ใหม่จะถูกสร้างขึ้นและแอตทริบิวต์ข้อความถูกตั้งค่าเป็นสตริง ResponsETEXT ที่ได้รับจากเซิร์ฟเวอร์ การทำเช่นนี้จะสร้างองค์ประกอบ <script> ด้วยรหัสอินไลน์และเมื่อมีการเพิ่มองค์ประกอบ <Script> ใหม่ลงในเอกสารแล้วรหัสจะถูกเรียกใช้งานและพร้อมใช้งาน
ข้อดีของวิธีนี้คือมันมีความเข้ากันได้ดีและคุณสามารถดาวน์โหลดรหัส JavaScript ที่ไม่ได้ดำเนินการทันที เนื่องจากรหัสส่งคืนนอกแท็ก <script> มันจะไม่ถูกเรียกใช้งานโดยอัตโนมัติหลังจากดาวน์โหลดซึ่งช่วยให้คุณสามารถเลื่อนการดำเนินการได้
การกำหนดวิธีนี้ขึ้นอยู่กับข้อ จำกัด ที่คล้ายคลึงกันของเบราว์เซอร์ ไฟล์ JavaScript จะต้องอยู่ในโดเมนเดียวกับหน้าและไม่สามารถดาวน์โหลดได้จาก CDN (เครือข่ายการส่งเนื้อหา) ด้วยเหตุนี้หน้าเว็บขนาดใหญ่มักจะไม่ใช้เทคโนโลยีการฉีดสคริปต์ XHR
รูปแบบ noblocking ที่แนะนำ
วิธีที่แนะนำในการโหลดจาวาสคริปต์จำนวนมากไปยังหน้าแบ่งออกเป็นสองขั้นตอน:
ขั้นตอนแรกรวมถึงรหัสที่จำเป็นในการโหลด JavaScript แบบไดนามิกจากนั้นโหลดชิ้นส่วนยกเว้น JavaScript ที่จำเป็นสำหรับการเริ่มต้นหน้าเว็บ ส่วนนี้ของรหัสนี้มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้และอาจรวมฟังก์ชั่น loadscript () เท่านั้น มันดาวน์โหลดและทำงานได้อย่างรวดเร็วและจะไม่ทำให้เกิดการรบกวนมากนัก
ขั้นตอนที่สองคือการใช้เพื่อโหลด JavaScript ที่เหลือหลังจากรหัสเริ่มต้นพร้อม
ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
1 <script type = "text/javascript" src = "loader.js">
2 </script> <script type = "text/javascript">
3 loadscript ("The-rest.js", function () {
4 application.init ();
5});
6
7 </script>
วางรหัสนี้ก่อนที่แท็กปิดของร่างกาย </body> ประโยชน์ของการทำเช่นนี้เป็นครั้งแรกสิ่งนี้ทำให้มั่นใจได้ว่าจาวาสคริปต์ทำงานโดยไม่ส่งผลกระทบต่อส่วนอื่น ๆ ของหน้าอื่น ๆ เพื่อแสดง ประการที่สองเมื่อดาวน์โหลดส่วนที่สองของไฟล์ JavaScript DOM ที่จำเป็นทั้งหมดสำหรับแอปพลิเคชันได้ถูกสร้างขึ้นและพร้อมที่จะเข้าถึงหลีกเลี่ยงการใช้การประมวลผลเหตุการณ์เพิ่มเติม (เช่น window.onload) เพื่อทราบว่าหน้าพร้อมหรือไม่
อีกทางเลือกหนึ่งคือการฝังฟังก์ชั่น loadscript () ลงในหน้าโดยตรงซึ่งสามารถลดค่าใช้จ่ายของคำขอ HTTP ตัวอย่างเช่น:
การคัดลอกรหัสมีดังนี้:
1 <script type = "text/javascript">
function loadscript (url, callback) {
var script = document.createElement ("สคริปต์");
script.type = "text/javascript";
if (script.readyState) {// ie script.onreadyStateChange = function () {
if (script.readyState == "โหลด" || script.readyState == "เสร็จสมบูรณ์") {
script.onreadystatechange = null;
การโทรกลับ ();
-
-
} else {// อื่น ๆ
script.onload = function () {
การโทรกลับ ();
-
-
script.src = url;
document.getElementByTagname ("head") [0] .AppendChild (สคริปต์);
-
loadscript ("The-rest.js", function () {
Application.init ();
-
</script>
เมื่อดาวน์โหลดรหัสการเริ่มต้นหน้าเว็บแล้วคุณยังสามารถใช้ฟังก์ชัน LoadScript () เพื่อโหลดฟังก์ชั่นการทำงานเพิ่มเติมที่กำหนดโดยหน้า
แนะนำเครื่องมือทั่วไป Ryan Grove แห่ง Yahoo! การค้นหาสร้างไลบรารี LazyLoad (ดู: http://github.com/rgrove/lazyload/) LazyLoad เป็นฟังก์ชั่น loadscript () ที่ทรงพลัง Lazyload มีเพียง 1.5kb หลังจากปรับขนาด ตัวอย่างการใช้งานมีดังนี้:
การคัดลอกรหัสมีดังนี้:
<script type = "text/javascript" src = "lazyload-min.js"> </script>
<script type = "text/javascript">
lazyload.js ("the-rest.js", function () {
Application.init ();
-
</script>
สรุป
1. วางแท็ก <Script> ทั้งหมดที่ด้านล่างของหน้าใกล้กับแท็กปิด </body> วิธีนี้ทำให้มั่นใจได้ว่าหน้าจะแยกวิเคราะห์ก่อนที่สคริปต์จะทำงาน
2. แพ็คสคริปต์เป็นกลุ่ม แท็ก <Script> น้อยลงบนหน้าเว็บที่น้อยลงหน้าจะโหลดและตอบสนองได้เร็วขึ้น สิ่งนี้เป็นจริงสำหรับทั้งไฟล์สคริปต์ภายนอกและรหัสอินไลน์
3. มีหลายวิธีในการดาวน์โหลด JavaScript โดยใช้วิธีการไม่ปิดกั้น:
1). เพิ่มแอตทริบิวต์การเลื่อนเวลาลงในแท็ก <script>
2). สร้างองค์ประกอบ <script> แบบไดนามิกใช้เพื่อดาวน์โหลดและเรียกใช้รหัส
3). ใช้วัตถุ XHR เพื่อดาวน์โหลดรหัสและฉีดลงในหน้า
ผ่านกลยุทธ์ข้างต้นประสิทธิภาพที่แท้จริงของชาวเน็ตที่ใช้รหัส JavaScript สามารถปรับปรุงได้อย่างมาก
หนังสืออ้างอิง "High Performance JavaScript"