2 คะแนน โดย GN⁺ 2025-05-05 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • มีข้อจำกัดว่าใน HTML เพียงอย่างเดียว ไม่มีฟีเจอร์ include สำหรับนำองค์ประกอบเดียวกันไปใช้ซ้ำในหลายหน้าได้โดยตรง
  • แม้ว่า CSS จะเรียก CSS ได้ และ JavaScript จะเรียก JS ได้ แต่ HTML กลับไม่สามารถดึง HTML เข้ามาได้ จึงกลายเป็นคำถามที่น่าสงสัย
  • เพื่อแก้ปัญหานี้ จึงมีการใช้ JavaScript, ภาษาเทมเพลต และ static site generator หลากหลายแบบ
  • ปัญหาด้านประสิทธิภาพ ความปลอดภัย ความล่าช้าในการเรนเดอร์ และการ include แบบวนซ้ำ เป็นอุปสรรคสำคัญต่อการเพิ่มฟีเจอร์นี้
  • นักพัฒนาจำนวนมากต้องการ ฟีเจอร์ include แบบ declarative ที่เป็น native ของ HTML แต่จนถึงตอนนี้ก็ยังไม่ถูกรวมเข้าไปในมาตรฐานเว็บ

คำถามว่าทำไม HTML ถึงไม่มีฟีเจอร์ Include

การตั้งประเด็น

  • ในหลายหน้าอย่าง index.html, about.html, contact.html มีความไม่สะดวกจากการต้องแทรก header ที่ใช้ร่วมกัน ซ้ำ ๆ
  • นักพัฒนาต้องการ นำ header ที่นิยามไว้ครั้งเดียวกลับมาใช้ซ้ำโดยไม่เกิดความซ้ำซ้อน

วิธีทดแทนที่มีอยู่แล้ว

  • ใช้ fetch API ของ JavaScript เพื่อโหลด HTML ภายนอกแล้วแทรกลงใน DOM
  • มีทางออกอย่าง Server Side Includes (SSI), include ของ PHP, static site generator และภาษาเทมเพลต
  • องค์ประกอบ HTML อย่าง <iframe> และ <object> ก็พอใช้ได้เช่นกัน แต่ ไม่เหมาะสมเพราะมีปัญหาเรื่องการเข้าถึง ประสิทธิภาพ และการแยกสไตล์
  • สุดท้ายแล้ว ตัว HTML เองก็ยังไม่มีไวยากรณ์ include แบบง่าย ๆ

ทำไม HTML ถึงไม่มีฟีเจอร์นี้?

  • CSS และ JS ต่างก็มีไวยากรณ์อย่าง @import หรือ import ของตัวเอง แต่ HTML ไม่มีสิ่งนั้น
  • มาตรฐานเว็บโดยทั่วไปมักรับเอาฟีเจอร์ที่นักพัฒนาใช้กันมากเข้ามา แต่ HTML include กลับไม่เป็นเช่นนั้น
  • เหตุผลที่ถูกหยิบยกขึ้นมามีดังนี้:
    • อาจรบกวนการทำงานของ preload scanner
    • อาจเกิด ปัญหา layout shift หรืออาการกะพริบเมื่อโหลดแบบอะซิงโครนัส
    • มี ความซับซ้อนในการจัดการ include แบบซ้อนกันหรือแบบวนซ้ำ
    • อาจมี แรงต้านจากการเพิ่มปริมาณทราฟฟิกของเว็บโฮสติ้ง
    • มี ประเด็นด้านความปลอดภัย (CORS, CSP ฯลฯ) และ ความขัดแย้งด้านจังหวะเวลาของ document loading event
    • หรืออาจเป็นเพียงเพราะ ลำดับความสำคัญต่ำและยังไม่มีข้อเสนอที่ชัดเจน

การถกเถียงที่เกี่ยวข้อง

  • มีการถกเถียงกันอย่างคึกคักใน GitHub WHATWG issue thread #2791
  • ในอดีต Chrome เคยมี HTML Imports อยู่ช่วงหนึ่ง แต่ภายหลังถูกยกเลิกเพราะ เบราว์เซอร์อื่นไม่รองรับ
  • มีการแชร์แนวทางทางเลือก เช่น HTMX, Web Components, XSLT, SSI เป็นต้น

สรุปปฏิกิริยาจากชุมชน

  • การพัฒนาของ HTML ยังคงรักษาแนวคิดแบบ เน้น static markup และยังมีปรัชญาที่ ตัดความสามารถเชิงตรรกะออกไป อย่างชัดเจน
  • แม้หลายคนต้องการฟีเจอร์นี้ แต่ส่วนใหญ่เป็น นักพัฒนาอิสระที่ส่งเสียงได้ยากในกระบวนการทำมาตรฐาน
  • ก็มีการวิเคราะห์ด้วยว่า หากยังแก้ปัญหาเชิงออกแบบที่ซับซ้อนอย่าง ประสิทธิภาพ ความปลอดภัย การเรนเดอร์ และการป้องกันการวนซ้ำ ไม่ได้ ก็ยากที่จะนำมาใช้จริง
  • นักพัฒนาบางคนมองว่า ฟีเจอร์นี้หายไปเพียงเพราะแนวคิดที่ว่า HTML ควรรับผิดชอบแค่ “ผลลัพธ์” เท่านั้น

บทสรุป

  • จนถึงตอนนี้ HTML ก็ยัง ไม่มีฟีเจอร์ include แบบแท้ ๆ และยังต้องพึ่งเครื่องมือหรือภาษาภายนอกในการทดแทน
  • อย่างไรก็ตาม นักพัฒนาจำนวนมากก็ยังคาดหวัง โครงสร้างการนำกลับมาใช้ซ้ำที่เรียบง่ายบนพื้นฐานของ HTML

1 ความคิดเห็น

 
GN⁺ 2025-05-05
ความคิดเห็นบน Hacker News
  • ในทางประวัติศาสตร์ HTML เป็นแอปพลิเคชันของ SGML และ SGML รองรับฟังก์ชันการรวมอยู่แล้ว โดยสามารถกำหนด "เอนทิตี" ใหม่และสร้างเอนทิตี "system" เพื่ออ้างอิงในภายหลังและแทนที่ได้
    • เนื่องจากความซับซ้อนของ SGML จึงมีความพยายามหลายอย่างที่จะทำให้ HTML เรียบง่ายขึ้น และในกระบวนการนั้นความสามารถลักษณะนี้ก็ถูกตัดออกไป
  • ช่วงปลายยุค 90 มีความพยายามแก้ปัญหานี้อยู่ ในฐานะเว็บมาสเตอร์ของเว็บไซต์ Analog Science Fiction ผู้เขียนกำลังสร้างหน้าสแตติกจำนวนมากที่มีเฮดเดอร์และไซด์บาร์เหมือนกัน จึงได้ค้นพบฟีเจอร์ server-side include ของ Apache นี่เป็นวิธีดูแลสิ่งนี้ก่อนที่จะรู้จักหลักการ DRY
    • ปัญหานี้ถูกแก้ซ้ำแล้วซ้ำเล่าด้วยหลายวิธี สำหรับคนที่บอกว่า iframe ก็เพียงพอแล้ว ปัญหาคือ iframe ไม่ขยายตามเนื้อหา โซลูชันฝั่งเซิร์ฟเวอร์ก็ต้องมีเซิร์ฟเวอร์ แล้วทำไมถึงไม่มีวิธีง่ายๆ ฝั่งไคลเอนต์บ้าง? คิดว่านี่เป็นคำถามที่สมเหตุสมผล
  • เคยมีข้อเสนอฟีเจอร์ชื่อ HTML Imports ซึ่งถูกสร้างขึ้นมาเป็นส่วนหนึ่งของ Web Components
    • HTML Imports เป็นวิธีรวมเอกสาร HTML เข้าในเอกสาร HTML อื่นและนำกลับมาใช้ซ้ำ
    • Google ได้นำสเปกที่เสนอไปใช้งานใน Blink แต่บริษัทอื่นคัดค้านด้วยเหตุผลหลากหลาย Mozilla กังวลเรื่องความซับซ้อนของการพัฒนา ปัญหาด้านความปลอดภัย และความซ้ำซ้อนกับ ES6 modules เมื่อไม่มีการสนับสนุนจากผู้ผลิตรายอื่น ข้อเสนอนี้จึงถูกยุติอย่างเป็นทางการ
  • Netscape 4 เคยมีฟีเจอร์ชื่อ inflow layers
    • ชื่อของแนวคิดนี้คือ transclusion มันเป็นส่วนหนึ่งของ Project Xanadu และเดิมทีถูกมองว่าเป็นฟีเจอร์สำคัญของไฮเปอร์เท็กซ์
    • MediaWiki ใช้ transclusion อย่างกว้างขวาง บางครั้งวิกิก็ให้ความรู้สึกเหมือนเป็นรูปแบบที่แท้จริงของไฮเปอร์เท็กซ์
  • frameset ที่เหมาะสม (ไม่ใช่ iframe) เดิมทีถูกออกแบบมาให้ทำหน้าที่ลักษณะนี้ตั้งนานแล้ว อย่างน้อยมันก็ปรับขนาดอัตโนมัติได้ดีและผู้ใช้ยังปรับขนาดเองได้
    • แม้จะมีคำวิจารณ์ต่อเฟรมมากมาย แต่ก็ถูกนำไปใช้กับสิ่งที่มีประโยชน์ได้สำเร็จ เช่น เอกสาร Java API
    • คิดว่า frameset ไม่ถูกรักษาไว้เพราะมันให้ความยืดหยุ่นกับนักออกแบบไม่เพียงพอ และบนมือถือในปัจจุบันก็คงทำงานได้ไม่ดี
  • ฟีเจอร์ "Includes" ถูกมองว่าเป็นเรื่องฝั่งเซิร์ฟเวอร์และประมวลผลนอกเว็บเบราว์เซอร์ HTML อยู่ฝั่งไคลเอนต์ และเป็นเพียงไวยากรณ์มาร์กอัปแบบเรียบง่าย ไม่ใช่ภาษาโปรแกรม
    • ปัญหานี้ถือว่าได้รับการแก้ไปแล้ว ปัญหา "Includes" คือสิ่งที่นักเรียนออกแบบเว็บทุกคนใช้เรียนรู้ PHP ใน CMS ส่วนใหญ่ "Includes" จะกลายเป็น "template part" และเป็นหนึ่งในสิ่งแรกๆ ที่อธิบายในเอกสาร
    • ไม่มีความจำเป็นต้องใช้ "Includes" ด้วย HTML เพียงอย่างเดียว HTML เป็นฟอร์แมตสำหรับการนำเสนอ และถ้าไม่มี CSS กับ JS ก็ไม่สามารถทำสิ่งที่น่าสนใจได้มากนัก
  • ฟังก์ชันการรวมของ HTML มีปัญหาหลายอย่าง
    • หาก main.html รวม child/include1.html และ child/include1.html มีลิงก์ src="include2.html" เมื่อผู้ใช้คลิกลิงก์นั้นควรพาไปที่ไหน? ถ้าไปที่ "include2.html" หน้านั้นก็จะขาดส่วนอื่นทั้งหมดไป ถ้าไปที่ main.html แล้วจะระบุอย่างไรว่าให้ใช้ include2.html ครั้งนี้แทน include1.html?
    • ในทางกลับกัน article1.html, article2.html, article3.html ฯลฯ อาจรวม header.html, footer.html, navi.html ได้ แต่ถ้าต้องการเพิ่ม comments.html ให้ทุกบทความ ก็ต้องแก้ทุกบทความอยู่ดี สุดท้ายก็กลายเป็นการสร้างบทความจากเทมเพลต และเบราว์เซอร์ก็ไม่จำเป็นต้องรองรับ include
    • ถ้าเฮดเดอร์ต้องการรู้ชื่อเรื่อง หรือฟุตเตอร์ต้องการลิงก์ก่อนหน้า/ถัดไป ก็จำเป็นต้องมีวิธีส่งข้อมูลนี้ระหว่างส่วนที่รวมกัน สุดท้ายก็ต้องสร้างหน้าเพจขึ้นมาอยู่ดี และ include ไม่ใช่คำตอบ
    • สำหรับกรณีใช้งานส่วนใหญ่ การรวม HTML อาจแทบไม่มีประโยชน์จริงในทางปฏิบัติ
  • มี public issue ใน WHATWG เกี่ยวกับประเด็นนี้
    • ฟังก์ชัน include ฝั่งไคลเอนต์ของ HTML
  • HTML เคยมีความสามารถแบบรวมอยู่แล้ว แต่ความนิยมลดลง
    • คำว่า "include" ที่แท้จริงเป็นคำของฟีเจอร์ใน XML และเป็นสิ่งที่บทความนี้ต้องการ HTML มีแนวทางทดแทนที่มีมาก่อน XML แนวทางนั้นคือเฟรม เฟรมให้ความสามารถมากกว่า XML include ด้วยซ้ำ จึงทำให้ HTML ไม่ได้รับฟีเจอร์นั้น เฟรมเสื่อมความนิยมลงเพราะการใช้งานที่ผิด ว่าด้วยความปลอดภัย การเข้าถึง และปัญหาอื่นๆ อีกหลากหลาย