Tutorial

สรุป <script> ควรไว้บน Head หรือ ล่าง Body

By Arnon Puitrakul - 18 มีนาคม 2021

สรุป <script> ควรไว้บน Head หรือ ล่าง Body

เป็นคำถามที่น่าสนใจมาก เพราะก่อนหน้านี้เราเองก็เคยสงสัยเมื่อนานมาแล้วเหมือนกัน โดยเฉพาะตอนที่เราเรียนพวกเรื่อง HTML ก็บอกกันว่า <script> ควรอยู่ที่ Head นะ สักพักนึงพอเราไปอ่าน Document ของพวกที่ใช้ Javascript รัน ก็บอกให้เอาไปไว้ท้าย Body เอ้า เลยไปไกลเลยนั่น วันนี้เรามาลองดูเหตุผลกันว่า ทำไมเขาถึงบอกแบบนั้นกัน และเราควรทำแบบไหน จะได้ไม่ลำบากลูกหลานน้อง ๆ โปรแกรมเมอร์ที่ต้องมานั่งหัวเสียต่อจากเรากัน

Web Browser จัดการกับ <script> อย่างไร ?

ก่อนที่เราจะไปชี้นิ้วบอกว่า แกต้องวางมันไว้ตรงไหน เรามาทำความเข้าใจกันก่อนว่ามันจัดการกับ Script Tag อย่างไร เรื่องราวมันจะต้องเริ่มจาก Web Browser ได้รับ HTML Document จาก Web Server ตามที่ Web Browser ได้ทำการ Request ไปก่อนหน้า

HTML Document ที่ได้รับจาก Web Server มันก็จะเป็น Text Format ธรรมดาที่เราสามารถอ่านได้ แต่ Web Browser ไม่สามารถทำความเข้าใจมันได้โดยตรง มันจะต้องทำการแปลง หรือ Parse เพื่อให้เป็นรูปแบบที่ Web Browser ทำงานได้ง่าย ซึ่งเราเรียก Format นี้ว่า Document Object Model (DOM)

Web Inspector in Safari

ถ้าเราอยากรู้ว่า Web Browser มัน Parse มาแล้วเป็นยังไง ลอง Inspect เราจะเห็นว่า HTML มันถูกอ่าน และแปลงให้เป็น Format ที่หน้าตาเหมือน Tree ถ้าเราจิ้ม Div Tag มันก็จะเปิดลูกของมันออกมา นั่นละคือการที่มันอ่าน HTML

ณ เวลาที่มันอ่าน มันก็จะค่อย ๆ อ่านไปทีละบรรทัดเรื่อย ๆ จนมาถึงบรรทัดเจ้าปัญหาของเราในวันนี้คือ <script> สิ่งที่มันทำคือ มันจะยิง Request ไปที่ Web Server หรือ Server ที่มีไฟล์ Javascript ตัวนั้นอยู่ และทำการโหลดไฟล์มา

หลังจากที่ไฟล์ถูกโหลดแล้ว Javascript ที่โหลดมาจะถูก Execute แต่ระหว่าง การโหลด และ Execute Javascript การ Parse HTML จะถูกหยุดชะงักไว้ก่อนจนกว่าจะทำเสร็จ หลังจากเสร็จ มันถึงจะกลับมา Parse HTML ต่อ ถ้าเจออีกก็ทำอีกไปเรื่อย ๆ

document.addEventListener('DOMContentLoaded', (event) => {
  // Do Sth
})

ทำให้เวลาเราเขียน Javascript เพื่อ Manipulate DOM เราจะต้องเขียน Block ด้านบนไว้ เพื่อสั่งให้ Script Block นี้มันทำงาน เมื่อ DOM ถูก Parse เรียบร้อยแล้ว ไม่งั้น เราจะได้เจอ Error ว่ามันหาตำแหน่งที่เราอ้างถึงไม่เจอนั่นเอง

ทำไมเราต้องวาง <script> ไว้ที่หลัง Body

พอเวลาเราไปอ่าน Document ของบาง Library เขาจะบอกให้เราวาง <script> ของเขาไว้ที่ท้ายของ Body คำตอบอยู่ที่เราบอกไปเมื่อกี้แล้วว่า เขาต้องการให้ DOM ถูก Parse ออกมาให้หมดก่อน แล้วค่อยให้ Script ทำงานทีหลังไป อาจจะเป็น Script ที่เข้ามา Manipulate DOM เลยยิ่งทำให้เราต้องวางมันไว้ที่ท้ายเสมอ

บาง Script ที่เขียนออกมา ที่บอกให้เราเอาไว้วางไว้ด้านล่างก็อาจจะไม่ได้เขียน Script สำหรับการเช็คสถานะการโหลด ก็ทำให้ถ้าเราเอาไปวางด้านบน มันก็จะมี Error ออกมาว่า มันหา DOM ตำแหน่งนั้น ๆ ไม่เจอ เราก็เลยต้องเอาไปไว้ข้างล่างนั่นเอง

สรุปแล้ว เราควรเอาไว้ไหน ?

คำตอบขึ้นกับว่า Script ของเราทำอะไร ถ้าเราต้องการ Manipulate DOM จาก Event ต่าง ๆ เช่นการกดปุ่ม แล้วมีอะไรเปลี่ยนแปลง อันนั้น เวลาเราเขียน เราจะต้องมี Target ของ DOM ที่เราต้องการเปลี่ยนแปลง และ แน่นอนว่าส่วนนี้มันจะเกิดขึ้นตอนที่หน้าถูกโหลดจนครบ User ถึงจะกดได้ ทำให้ของพวกนี้ เราจะต้องวางไว้ด้านล่าง เพื่อให้มั่นใจว่าหน้าทั้งหมดถูก Parse เรียบร้อยแล้วก่อนที่ User จะเห็นและกดนั่นเอง

ตรงกันข้าม ถ้าเราเรียกของที่เราอาจจะต้องใช้ก่อนที่หน้าจะโหลด เราก็สามารถเอาไปวางไว้ที่ Head ก็ทำให้ Script นี้ถูกโหลด และ รันก่อนที่หน้าจะโหลดได้นั่นเอง ดังนั้นมันเลยขึ้นกับว่า Script ของเราทำอะไร และเราต้องการมันตอนไหนนั่นเอง

แกร์ นี่ปี 2021 แล้วนะ มาใช้ Defer กับ Async ได้ละ

ข้อเสียของการที่เราต้องวาง Script บนบ้าง ล่างบ้าง ปัญหาคือ มันอยู่ไม่เป็นที่สักที ทำให้บางทีมันน่าปวดหัวในการเข้าไปนั่งหาอะไรแบบนี้ไปเรื่อย ๆ มันน่าจะดี ถ้าเราสามารถวางไว้บน Head และ ให้มันทำงานทีหลังได้ โดยที่ไม่กระทบกับ Performance ในการโหลดของเรา

ทำให้ Web Browser รุ่นใหม่ ๆ ก็มีการ Implement ของเพิ่มเติม เพื่อให้นักพัฒนาสามารถบอกให้ Web Browser จัดการกับ Script นี้อย่างไร ผ่าน 2 คำคือ Differ กับ Async

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

เราสามารถใส่ Async ไว้ใน Script Tag ได้เลย เพื่อเป็นการบอกให้ Web Browser รู้ว่า Script File นี้สามารถ โหลด และ Execute เป็นเบื้องหลัง ทำให้ไม่ต้องหยุดการ Parse HTML ได้ ทำให้ User ไม่เจอหน้าขาว ถ้า Script เราใช้เวลาในการทำงานนานแล้ว

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

แต่ถ้าเป็น Differ มันจะสั่งให้ Javascript ถูกโหลดจาก Server ลงมาก่อน และ ให้ Execute เมื่อหน้าทั้งหมดถูกโหลด และ Parse เรียบร้อยแล้ว และถ้ามีหลายอัน มันก็จะค่อย ๆ ไล่ Execute มาทีละอัน อีกด้วย ทำให้จริง ๆ แล้ว มันก็เหมาะกับ การที่เราเอาไปใส่กับพวก Script ที่ให้วางไว้ท้าย ๆ ของไฟล์

สรุป

สรุปของบทความนี้สั้นเลยคือ หยุด พักก่อน กับการเอา Script ไปใส่ไว้ที่ต้นบ้าง ท้ายบ้าง หรือที่อื่น ๆ บ้าง เขียนให้มันอยู่บน <head> ที่เดียวเลย แต่ถ้าอันที่เราต้องการให้มันทำงานแบบไหน เราก็เลือกใส่ Differ หรือ Async เข้าไป ก็จะช่วยทำให้ เราได้เรื่อง Performance ที่ดีขึ้น ผู้ใช้ไม่ต้องมานั่งดูหน้าขาว กว่าหน้าจะโหลด

Read Next...

จัดการ Docker Container ง่าย ๆ ด้วย Portainer

จัดการ Docker Container ง่าย ๆ ด้วย Portainer

การใช้ Docker CLI ในการจัดการ Container เป็นท่าที่เราใช้งานกันทั่วไป มันมีความยุ่งยาก และผิดพลาดได้ง่ายยังไม่นับว่ามี Instance หลายตัว ทำให้เราต้องค่อย ๆ SSH เข้าไปทำทีละตัว มันจะดีกว่ามั้ย หากเรามี Centralised Container Managment ที่มี Web GUI ให้เราด้วย วันนี้เราจะพาไปทำความรู้จักกับ Portainer กัน...

Host Website จากบ้านด้วย Cloudflare Tunnel ใน 10 นาที

Host Website จากบ้านด้วย Cloudflare Tunnel ใน 10 นาที

ปกติหากเราต้องการจะเปิดเว็บสักเว็บ เราจำเป็นต้องมี Web Server ตั้งอยู่ที่ไหนสักที่หนึ่ง ต้องใช้ค่าใช้จ่าย พร้อมกับต้องจัดการเรื่องความปลอดภัยอีก วันนี้เราจะมาแนะนำวิธีการที่ง่ายแสนง่าย ปลอดภัย และฟรี กับ Cloudflare Tunnel ให้อ่านกัน...

จัดการข้อมูลบน Pandas ยังไงให้เร็ว 1000x ด้วย Vectorisation

จัดการข้อมูลบน Pandas ยังไงให้เร็ว 1000x ด้วย Vectorisation

เวลาเราทำงานกับข้อมูลอย่าง Pandas DataFrame หนึ่งในงานที่เราเขียนลงไปให้มันทำคือ การ Apply Function เข้าไป ถ้าข้อมูลมีขนาดเล็ก มันไม่มีปัญหาเท่าไหร่ แต่ถ้าข้อมูลของเราใหญ่ มันอีกเรื่องเลย ถ้าเราจะเขียนให้เร็วที่สุด เราจะทำได้โดยวิธีใดบ้าง วันนี้เรามาดูกัน...

ปั่นความเร็ว Python Script เกือบ 700 เท่าด้วย JIT บน Numba

ปั่นความเร็ว Python Script เกือบ 700 เท่าด้วย JIT บน Numba

Python เป็นภาษาที่เราใช้งานกันเยอะมาก ๆ เพราะความยืดหยุ่นของมัน แต่ปัญหาของมันก็เกิดจากข้อดีของมันนี่แหละ ทำให้เมื่อเราต้องการ Performance แต่ถ้าเราจะบอกว่า เราสามารถทำได้ดีทั้งคู่เลยละ จะเป็นยังไง เราขอแนะนำ Numba ที่ใช้งาน JIT บอกเลยว่า เร็วขึ้นแบบ 700 เท่าตอนที่ทดลองกันเลย...