วิศวกรรมเว็บเบราว์เซอร์ (2021)
(browser.engineering)- Web Browser Engineering เป็นหนังสือที่ครอบคลุมตั้งแต่ระบบเครือข่ายไปจนถึง JavaScript โดยให้ผู้อ่านลงมือสร้างเว็บเบราว์เซอร์พื้นฐานแต่สมบูรณ์ด้วย Python หลายพันบรรทัด
- ลำดับการเรียนรู้เริ่มจากการโหลดหน้าเว็บ ไปสู่การแสดงเอกสาร การรันแอปพลิเคชัน และฟีเจอร์ของเบราว์เซอร์ยุคใหม่ โดยเชื่อมโยง HTTP, HTML, CSS, DOM, ความปลอดภัย, rendering pipeline ตามลำดับ
- ช่วงต้นมุ่งเน้น การใช้งานพื้นฐานของเบราว์เซอร์ เช่น URL และคำขอ HTTP, การสร้างหน้าต่างและการวาดบน canvas, การตัดบรรทัดข้อความและระยะห่างระหว่างบรรทัด
- ช่วงกลางถึงท้ายครอบคลุมการสร้าง HTML tree, layout, การใช้ style, การส่งฟอร์ม, การตอบสนองต่อ event, cookie และ login รวมถึง XSS และ CSRF
- ช่วงท้ายต่อยอดไปสู่ compositing, event loop, animation ด้วย GPU, accessibility tree, iframe, invalidation และความถูกต้องของการแก้ไข ทำให้ได้สำรวจ องค์ประกอบการใช้งานของเบราว์เซอร์ยุคใหม่ อย่างกว้างขวาง
โครงสร้างเบราว์เซอร์ที่เรียนรู้ผ่านการลงมือสร้างเอง
- Web Browser Engineering จัดทำขึ้นในรูปแบบที่ให้ลงมือสร้างเบราว์เซอร์พื้นฐานแต่สมบูรณ์ด้วยตนเอง เพื่อทำความเข้าใจว่าเว็บเบราว์เซอร์ทำงานอย่างไร
- ภาษาที่ใช้ในการพัฒนาคือ Python และขนาดของ implementation ทั้งหมดอยู่ในระดับหลายพันบรรทัด
- ขอบเขตครอบคลุมตั้งแต่ระบบเครือข่ายไปจนถึง JavaScript
- หนังสือฉบับพิมพ์ซื้อได้ที่ Bookshop, B&N, Amazon
- ฉบับแปลมีฉบับภาษาเกาหลีโดย Hanbit และฉบับภาษาญี่ปุ่นโดย O’Reilly
- สามารถติดตามอัปเดตได้ทาง blog, Mastodon, Twitter และยังมี GitHub discussion forum
ลำดับสารบัญ
-
บทนำ
-
Part 1: Loading Pages
- Downloading Web Pages: URL และคำขอ HTTP
- Drawing to the Screen: การสร้างหน้าต่างและการวาดบน canvas
- Formatting Text: การตัดบรรทัดคำและระยะห่างระหว่างบรรทัด
-
Part 2: Viewing Documents
- Constructing an HTML Tree: การ parse และแก้ไข HTML
- Laying Out Pages: layout แบบ inline และ block
- Applying Author Styles: การ parse และใช้ CSS
- Handling Buttons and Links: hyperlink และ browser chrome
-
Part 3: Running Applications
- Sending Information to Servers: การส่งฟอร์มและเว็บเซิร์ฟเวอร์
- Running Interactive Scripts: การเปลี่ยนแปลง DOM และการตอบสนองต่อ event
- Keeping Data Private: cookie, login, XSS, CSRF
-
Part 4: Modern Browsers
- Adding Visual Effects: blending, clipping, compositing
- Scheduling Tasks and Threads: event loop และ rendering pipeline
- Animating and Compositing: animation ที่ลื่นไหลด้วย GPU
- Making Content Accessible: การป้อนข้อมูลด้วยคีย์บอร์ด, การซูมเข้า/ออก, accessibility tree
- Supporting Embedded Content: รูปภาพ, iframe, scripting
- Reusing Previous Computation: invalidation, การแก้ไข, ความถูกต้อง
-
ปิดท้ายและภาคผนวก
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
สิ่งหนึ่งที่ดีในหนังสือเล่มนี้คือมีส่วนที่พูดถึง “สิ่งที่ไม่ได้ทำ” แยกไว้ต่างหาก
เลย์เอาต์นั้นยากจริง ๆ และแม้จะจัดการแค่ตารางโดยไม่มี CSS ก็ยังยาก หากรวม CSS เข้าไปด้วย เลย์เอาต์จะซับซ้อนจนแทบเป็นไปไม่ได้
ผมสงสัยว่ามีใครสักคนไหมที่สามารถเก็บสเปก CSS ทั้งหมดและพฤติกรรมที่เกี่ยวข้องไว้ในหัวได้หมด CSS+HTML+JavaScript ในปัจจุบันใกล้เคียงกับภาษาเทคโนโลยีสำหรับหน้าแบบไดนามิก (PDL) ไปแล้ว และอาจเป็นหนึ่งในซอฟต์แวร์ที่ซับซ้อนที่สุดในยุคนี้
เสริมอีกอย่างคือ การถอดรหัสวิดีโอ ถูก offload ไปยังฮาร์ดแวร์ จึงไม่ได้กินแบตเตอรี่มากเท่าเมื่อก่อนแล้ว
ตัวอย่างเช่น ไฟล์นี้ใช้ทำแค่ block/inline context เท่านั้น แม้จะมี boilerplate ของ Rust อยู่บ้าง แต่ส่วนใหญ่เป็นลอจิกจริงที่จัดการกับหลายส่วนของสเปก ไฟล์แบบนี้มีเต็มโฟลเดอร์: https://github.com/servo/servo/blob/main/components/layout/f...
ถึงอย่างนั้น การทำ layout engine ก็เป็นไปได้ CSS ไม่ใช่เวทมนตร์ แต่มีสเปกที่สามารถแปลงเป็นโค้ดได้อย่างละเอียด การให้คนที่หงุดหงิดเพราะ CSS ดูเหมือนตามอำเภอใจได้เห็นโค้ดแบบนี้ ช่วยให้เข้าใจได้ว่าสภาพแวดล้อมการรันก็มีตรรกะของมันเช่นกัน
แน่นอนว่าเราคงไม่ได้คลิกเข้าไปดูบ่อย ๆ เหมือนเวลาส่อง implementation ของไลบรารี แต่ในแง่นั้นผมก็คิดว่าไม่ต่างจากอย่าง React มากนัก
อย่างแรก ส่วนแกนหลักที่สุดของเลย์เอาต์อย่าง CSS 2 ถูกออกแบบมาแบบค่อนข้างหลวม ๆ และฟีเจอร์แปลก ๆ ก็โต้ตอบกันเองอย่างแปลก ๆ เช่น float กับ clearance และ margin collapsing ส่วนแกนหลักบางส่วนนี้ตั้งใจให้ใช้ได้ทั่วไปกับ layout mode ทั้งหมด แต่กลับไม่ค่อยเข้ากับโหมดอื่น ๆ ตัวอย่างเช่น margin และ padding ในองค์ประกอบ grid นั้นมีจุดประสงค์ไม่ชัดเจน
อย่างที่สอง มันไม่ได้ถูกทำให้เป็นโมดูลดีเท่า JavaScript API โดย JavaScript API มักถูก implementation แยกกันได้ แต่ layout module สามารถซ้อนกันได้หลายแบบ จึงส่งผลกระทบถึงกันทั้งหมด สเปกสมัยใหม่อย่าง grid พยายามจะเข้มงวดขึ้น แต่ก็ยังมีโจทย์พื้นฐานที่ทรัพยากรร่วมอย่างหน้าจอ 2D จริง ๆ ต้องถูก layout mode หลายแบบแบ่งกันใช้
คงไม่ใช่แค่ผมคนเดียวที่อยากได้ภาษาเลย์เอาต์ที่เรียบง่ายกว่า CSS แต่สะท้อนบทเรียนจาก 20 ปีที่ผ่านมา และทำให้ผลคูณของความเรียบง่ายกับพลังในการสื่อความหมายสูงสุด ผมสงสัยว่ามีโปรเจกต์ไหนออกแบบสิ่งแบบนี้อย่างจริงจังอยู่ไหม หรือทุกคนยอมรับ CSS3 กันหมดแล้ว รอ LLVM backend หรือไม่ก็กลับไปใช้ข้อความธรรมดาแทน
https://github.com/facebook/yoga
เลย์เอาต์ไม่จำเป็นต้องซับซ้อนขนาดนี้ มี GUI framework เป็นสิบ ๆ ตัวที่มีระบบเลย์เอาต์เรียบง่ายกว่า และสำหรับแอปพลิเคชันที่ผู้คนใช้งาน สิ่งเหล่านั้นก็เพียงพอแล้ว
ดูเจ๋งดี ประมาณ 15 ปีก่อนผมเริ่มทำ headless browser และดูแลมันอยู่หลายปี
ใช้ SpiderMonkey เป็น JavaScript interpreter และทำ DOM เอง ตอนนั้นมันรัน JavaScript สมัยใหม่กับ AJAX ฯลฯ ได้ทั้งหมด และต่อมาก็เพิ่ม custom Flash runtime เข้าไปด้วย เป็นโปรเจกต์ที่ทำแทบทุกอย่าง ยกเว้นการวาดลงหน้าจอ เลยสนุกมากจริง ๆ
อยากอ่านหนังสือเล่มนี้แน่นอน
ดีใจที่เห็นว่าวิศวกรรมเบราว์เซอร์ดูเหมือนจะกลายเป็น เทรนด์ แล้ว
อีโคซิสเต็มในความเป็นจริงค่อนข้างบาง เพราะแทบมีแค่ Google, Apple, Mozilla เท่านั้นที่เป็นผู้กำหนด ผมอยากเห็นอนาคตที่มีเอนจินเบราว์เซอร์อิสระมากขึ้น
พื้นที่ที่น่าสนใจคือ เทคโนโลยี UI/เอกสารที่พ้นจาก HTML Typst ที่พูดถึงในอีกเธรดหนึ่งคล้ายกับ LaTeX ที่ดีกว่า และ Markdown ก็มีอิทธิพลมากเช่นกัน ยังมีพื้นที่อีกมากสำหรับการสร้าง “HTML แต่ดีกว่า” และไม่จำเป็นต้องเป็นรูปแบบมาร์กอัปด้วยซ้ำ Typst กับ React HTML ทำให้เส้นแบ่งระหว่างโค้ดกับข้อมูลพร่าเลือน ส่วน Jetpack Compose แสดงให้เห็นวิธีใช้ความสามารถ DSL ของ Kotlin เพื่อสร้างสิ่งที่ดูเหมือนคำอธิบาย UI แต่จริง ๆ แล้วเป็นโค้ด
แน่นอนว่าหากจะทำแบบนั้น ก็ต้องเผยแพร่ ‘เบราว์เซอร์’ สำหรับรูปแบบนั้น หรือหาวิธีแสดงผลในเบราว์เซอร์เดิมให้ได้ ถึงอย่างนั้นก็ยังสามารถคอมไพล์ไปเป็น JavaScript/HTML/WASM ได้ จะใช้ชุดเครื่องมือ GUI แบบพกพาอย่าง JavaFX ก็ได้ และยังได้ accessibility ด้วย จะทำทั้งสองอย่างก็ได้
หากนิยามภาษา UI ของตัวเอง ก็จะลองทำหลายอย่างที่ HTML ทำได้ไม่ดีได้ ตัวอย่างสำคัญคือการแยกเนื้อหาออกจากสไตล์ HTML เคยพยายามแล้วแต่ไม่เคยทำได้ดีจริง ๆ ส่วน XSL:T พยายามหนักกว่า แต่เป็นภาษา pure functional แปลก ๆ ที่ใช้ไวยากรณ์ XML React ทำได้ค่อนข้างดีในการแปลง JSON ให้เป็นกล่อง แต่โปรโตคอลพื้นฐานมักเป็นรูปแบบที่พอกเสริมแบบเฉพาะหน้าอยู่เสมอ จึงยากที่จะสร้างเครื่องมือที่มีประโยชน์ไว้บนมัน
อีกแนวคิดหนึ่งคือรูปแบบที่โดยพื้นฐานแล้ว มีภูมิคุ้มกันต่อ XSS ก็เป็นไปได้
แต่ผมต้องการทางเลือกแทน HTML ถ้าผมสร้างเบราว์เซอร์เอง ผมน่าจะทน HTML ไม่ไหวและโฟกัสกับการแทนที่มัน และก็อยากเปลี่ยน JavaScript ด้วยเพราะ runtime หนัก
เช่น ถ้ามี เบราว์เซอร์ที่แทบไม่มี JavaScript runtime และรันแค่ WASM ก็น่าจะตลกดี
ผมเป็นหนึ่งในผู้เขียนหนังสือเล่มนี้ ขอบคุณสำหรับคำชมดี ๆ และถ้ามีคำถามก็ยินดีตอบ
อยากรู้กระบวนการที่ทำให้เลือก Python เป็นภาษาสำหรับ implement เบราว์เซอร์ ดูเหมือนว่า JavaScript ผ่าน Node น่าจะให้ประสบการณ์การเขียนโปรแกรมที่เกี่ยวข้องมากกว่า
บทความที่อธิบายว่าทำไมผู้เขียนถึงเลือก Python: https://browserbook.substack.com/p/why-python
บางส่วนดูเหมือนจะคอมไพล์ Python เป็น JavaScript จนตอนนี้รันอยู่ในเบราว์เซอร์ได้แล้ว หรือก็คือรันอยู่ใน “ตัวหนังสือเอง”
https://browserbook.substack.com/p/compiling-python-to-js
หวังว่าพออ่านแล้วจะกลับมาคุยอะไรที่มีสาระมากขึ้นได้
ตื่นเต้นมากที่ได้เห็นสื่อแบบนี้ถูกสร้างขึ้น
เบราว์เซอร์ดูเหมือนกล่องดำลึกลับที่ถอดรหัสไม่ได้ และเป็นไปได้สูงว่า Google ก็คงอยากให้ถูกมองแบบนั้น แต่เมื่อเห็นความพยายามและผลลัพธ์ของโปรเจกต์อย่าง Ladybird กำแพงนั้นก็กำลังแตกร้าว
สักวันหนึ่งผมอยากลงมือมีส่วนร่วมในการทำลาย คูเมือง นั้นด้วยตัวเอง และหนังสือเล่มนี้ก็ดูเป็นจุดเริ่มต้นที่ยอดเยี่ยม
Firefox มีอยู่แล้ว เพียงแต่แทบไม่มีใครใช้ และเมื่อผู้ใช้เจอเว็บไซต์ที่ใช้กับ Firefox ไม่ได้ พวกเขาก็เรียนรู้แล้วว่าแค่เปิด Chrome ก็พอ
การมีส่วนร่วมกับเอนจินเบราว์เซอร์อย่าง Ladybird ด้วยความหวังว่าคูเมืองจะพังลงคงสนุก แต่คงพูดยากว่านั่นเพียงอย่างเดียวคือการช่วยทำลายคูเมือง อยากรู้ว่าอะไรที่จะช่วยได้จริง
ตรงกันข้าม คนที่ทำงานกับ Chrome, Firefox, Safari, Ladybird ทุกคนดูตื่นเต้นมากเวลาพูดถึงเบราว์เซอร์และวิธีการทำงานของมัน โลกของการพัฒนาเบราว์เซอร์เล็กกว่าที่คิด และวิศวกรก็ย้ายไปมาระหว่างบริษัทบ่อย ดังนั้นคงยากที่จะรักษา “แผนสมคบคิด” อะไรไว้ได้
แต่ก็จริงที่สื่อการเรียนรู้ยังขาดแคลนอยู่มาก นั่นคือเหตุผลที่เราเขียนหนังสือเล่มนี้ และโดยเฉพาะอย่างยิ่ง ยังขาด คำศัพท์ร่วมกัน สำหรับพูดคุยเรื่องภายในเบราว์เซอร์ในขั้นตอนหลัก ๆ อย่างเลย์เอาต์และการ rasterization Chris กับผมอยากใช้หนังสือเล่มนี้สร้างพื้นฐานแบบนั้น
ผมกำลังหาโปรเจกต์สนุก ๆ เพื่อเริ่มทำอยู่พอดี และตอนนี้ก็อ่านหนังสือเล่มนี้อย่างเพลิดเพลินมาก ชอบที่เขียนออกมาได้น่าสนใจเป็นพิเศษ
หนังสือการ์ตูนเล่มนี้ที่อธิบายว่า Chrome ทำงานอย่างไรก็เป็นแหล่งข้อมูลเริ่มต้นที่ดีเช่นกัน: https://www.google.com/googlebooks/chrome/med_00.html
กำลังเรียนรู้โครงสร้างภายในของเบราว์เซอร์อยู่ และหนังสือเล่มนี้ยอดเยี่ยมมาก
ช่วยให้สร้าง สัญชาตญาณความเข้าใจ ว่าเบราว์เซอร์ทำงานอย่างไร โดยไม่ต้องขุดลงไปในโค้ด Chrome หลายล้านบรรทัด
สงสัยว่ามีโค้ดโปรโมชันสำหรับ HN ไหม
ก่อนหน้านี้เคยใช้ HTMLUnit [1] ร่วมกับ Jython [2] แล้วพอใจมาก และในอนาคตก็สนใจมากกับความเป็นไปได้ที่จะสร้างโค้ดบางส่วนของเบราว์เซอร์แบบอัตโนมัติด้วยเทคนิคการสร้างโค้ดและการตรวจสอบความถูกต้อง แม้จะนับถือเครื่องมืออย่าง Playwright/Cypress/Selenium แต่ไม่เคยรู้สึกว่าใช้งานสบายเท่า HTMLUnit
[1] https://htmlunit.sourceforge.io/
[2] https://www.jython.org/
เป็นหนังสือที่ดี แนะนำให้แบ่งบทที่ 9 ออกเป็นสองบท
ส่วนที่ รัน JavaScript ด้วย Duktape ควรแยกเป็นบทหนึ่ง และส่วนที่โต้ตอบกับ DOM และอีเวนต์ควรเป็นอีกบทหนึ่งในภายหลัง
ยิ่งไปช่วงท้าย บทต่าง ๆ จะยาวขึ้นและครอบคลุมหัวข้อขั้นสูงมากขึ้น และแนะนำให้อ่านหนังสือไปพร้อมกับเขียนโค้ดตามไปด้วย