- Blitz คือ เอนจินเรนเดอริงแบบโมดูลาร์ ที่เน้นการเรนเดอร์ HTML/CSS โดยไม่ได้ให้ความสามารถของเบราว์เซอร์ครบชุดมาเป็นค่าเริ่มต้น และออกแบบให้เพิ่มความสามารถที่จำเป็นแบบเลือกใช้ได้
- สถานะปัจจุบันคือ pre-alpha โดยตัวเรนเดอเรอร์มีความสามารถพอสมควรแล้ว แต่ยังมีบั๊กและฟีเจอร์ที่ขาดอยู่มาก จึงยังไม่แนะนำให้นำไปใช้พัฒนาแอป
- เป้าหมายการรองรับได้แก่ modern HTML layout, advanced CSS, HTML form controls, accessibility ที่อิง AccessKit และการขยายผ่าน custom widgets โดยจะไม่รองรับความสามารถอย่าง WebRTC, WebSockets, Bluetooth, localStorage
- โครงสร้างแบ่งเป็น core DOM abstraction และโมดูลด้านเครือข่าย การเรนเดอร์ หน้าต่าง และการจัดการสถานะ โดยมี wrapper crate ระดับบน ชื่อ
blitz และ dioxus-native สำหรับเรนเดอร์ HTML/Markdown หรือ Dioxus VirtualDom
- เวอร์ชันใหม่ Blitz v0.2+ ใช้ Stylo ส่วนซอร์สของ v0.1 ยังคงอยู่ในสาขา
legacy แต่ไม่ได้มีการพัฒนาอย่างต่อเนื่องมากนัก
เอนจินที่เน้นการเรนเดอร์ HTML/CSS
- Blitz คือ เอนจินเรนเดอร์ HTML/CSS และเริ่มต้นจากมุมมองที่ว่าเบราว์เซอร์มีขนาดใหญ่เกินไปเมื่อเทียบกับกรณีใช้งานหลักอย่างการเรนเดอร์ HTML/CSS
- เป้าหมายไม่ใช่การสร้างความสามารถของเบราว์เซอร์ทั้งหมด แต่จะเน้นความสามารถที่จำเป็นต่อการเรนเดอร์ HTML/CSS และทำให้ความสามารถที่เหลือเป็นแบบ opt-in ให้ได้มากที่สุด
- ตอนนี้ยังอยู่ในสถานะ pre-alpha
- ตัวเรนเดอเรอร์มีความสามารถพอสมควรแล้ว
- ยังมีบั๊กและฟีเจอร์ที่ขาดอยู่อีกมาก
- ยังไม่แนะนำให้นำไปใช้สร้างแอป
- ดูความคืบหน้าเพิ่มเติมได้ที่ roadmap issue
ความสามารถที่ตั้งใจรองรับและความสามารถที่ไม่รวมอยู่
- ขอบเขตที่ Blitz ตั้งใจรองรับมุ่งไปที่ การเรนเดอร์ UI ด้วย HTML/CSS
- modern HTML layout เช่น flexbox, grid, table, block, inline, absolute/fixed
- advanced CSS เช่น complex selectors, media queries, CSS variables
- HTML form controls
- accessibility ที่อิง AccessKit
- ความสามารถในการขยายผ่าน custom widgets
- Blitz ไม่รองรับความสามารถอย่าง WebRTC, WebSockets, Bluetooth, localStorage
- ในแอปเนทีฟ ความสามารถเหล่านี้จำนวนมากสามารถจัดการได้ด้วย Rust crate ทั่วไป
- มุมมองของโครงการคือความสามารถเหล่านี้ไม่จำเป็นต้องผูกเข้ากับตัวเรนเดอเรอร์
- ยังไม่มี language binding สำหรับภาษาอื่นอย่าง JavaScript หรือ Python แต่ยินดีรับการมีส่วนร่วมในส่วนนี้
วิธีรันและตัวอย่าง
- หลังจากโคลนรีโพซิทอรีแล้ว สามารถรันแพ็กเกจ
browser ได้
cargo run --release --package browser
- มีตัวอย่างเป็นแอป TODO ขนาดเล็ก, Markdown renderer และการผสาน raw WGPU rendering
cargo run --release --package todomvc
cargo run --release --package readme ./README.md
cargo run --release --package wgpu_texture
สถาปัตยกรรมแบบโมดูลาร์
- Blitz ประกอบด้วย core DOM abstraction, โมดูลความสามารถเสริม และ wrapper ระดับบนสองตัว
- ความสามารถอย่างเครือข่าย การเรนเดอร์ หน้าต่าง และการจัดการสถานะ ถูกแยกออกเป็นโมดูลต่างหาก
- สามารถนำชิ้นส่วนเหล่านี้มาประกอบกันเพื่อสร้างเป็นเว็บเอนจินหนึ่งตัวได้
-
wrapper crate ระดับบน
blitz: frontend สำหรับ HTML/Markdown ที่สามารถเรนเดอร์สตริง HTML ได้
- มีประโยชน์สำหรับพรีวิวไฟล์ HTML หรือ Markdown
- ตอนนี้ยังไม่มีการโต้ตอบ
- ใช้
blitz-dom, blitz-html, blitz-shell, blitz-renderer-vello
dioxus-native: frontend สำหรับ Dioxus ที่เรนเดอร์ Dioxus VirtualDom
- รองรับการโต้ตอบเต็มรูปแบบผ่านการจัดการอีเวนต์ของ Dioxus
- ใช้
blitz-dom, dioxus-core, blitz-shell, blitz-renderer-vello
- wrapper ทั้งสองตัวสามารถเลือกใช้
blitz-net เพื่อดึงทรัพยากรย่อยได้
-
crate แกนหลักและ crate เพิ่มเติม
blitz-dom: core DOM abstraction ที่รวม style resolution, layout, event handling
- ไม่รวม parsing, rendering หรือ system integration
- ใช้ Stylo, Taffy, Parley
blitz-traits: crate พื้นฐานขนาดเล็กที่ทำให้ crate อื่น ๆ ทำงานร่วมกันได้โดยไม่ต้องพึ่งพากันโดยตรง
blitz-net: โมดูลเครือข่ายสำหรับดึงทรัพยากรจาก HTTP, ระบบไฟล์ และ encoded data URI
- ใช้ reqwest
blitz-paint: แปลงต้นไม้ blitz-dom เป็นคำสั่งวาดของ anyrender
- ใช้ anyrender
blitz-html: เพิ่มการ parse HTML ให้กับ blitz-dom
- ใช้ html5ever และ xml5ever
blitz-shell: shell ที่ทำให้ Blitz เรนเดอร์ลงหน้าต่างได้
- ผสาน Winit event loop, AccessKit, Muda เป็นต้น
- ใช้ winit, accesskit, muda
- AnyRender rendering abstraction ถูกย้ายไปยังรีโพซิทอรีแยก anyrender
การใช้ Dioxus Native เวอร์ชันพัฒนา
- Dioxus Native เวอร์ชันพัฒนาล่าสุดอยู่ในรีโพซิทอรีนี้
- เนื่องจาก Dioxus Native กำลังพัฒนาอย่างรวดเร็ว หากต้องการใช้ฟีเจอร์ล่าสุดและบั๊กฟิกซ์ก่อน official release สามารถใช้เวอร์ชันจาก git ได้
- ขั้นตอนการใช้เวอร์ชันจาก git มีดังนี้
- ลบ dependency ของ crate
dioxus ออกทั้งหมด
- เพิ่ม
dioxus-native = { git = "https://github.com/DioxusLabs/blitz", rev = "e64a3d8", features = ["prelude"] }
- เปลี่ยน
e64a3d8 เป็น git commit id ของเวอร์ชันที่ต้องการ
- ในโค้ด Rust เปลี่ยน
use dioxus::prelude::* เป็น use dioxus_native::prelude::*
- หากต้องการใช้ความสามารถของ
dioxus ที่ Dioxus Native prelude ไม่ได้ export ให้ import จาก sub-crate รายตัว เช่น dioxus-html, dioxus-signals, dioxus-router
- เวอร์ชัน git ของ Dioxus Native ยังคงพึ่งพาเวอร์ชันเสถียรบน crates.io คือ Dioxus v0.7.x
- ไลบรารีเสริมอย่าง
dioxus-sdk, dioxus-components, dioxus-free-icons ควรยังคงใช้งานได้ต่อ
เวอร์ชันและไลเซนส์
- รีโพซิทอรีนี้มี Blitz v0.2+ เวอร์ชันใหม่ และใช้ Stylo
- ซอร์สของเวอร์ชันก่อนหน้า v0.1 ยังคงอยู่ในสาขา legacy
- v0.1 ไม่ได้มีการพัฒนาอย่างต่อเนื่องมากนัก
- โครงการเผยแพร่ภายใต้ dual license แบบ Apache 2.0 และ MIT
- crate
stylo_taffy เพิ่ม MPL 2.0 เข้ามาด้วยเพื่อให้ทำงานร่วมกับโครงการ Servo ได้สะดวกขึ้น
- ดังนั้น
stylo_taffy จึงเป็นแบบ triple license: Apache 2.0, MIT, MPL 2.0
- การมีส่วนร่วมที่ส่งเข้ามายัง Blitz โดยเจตนา จะถือว่าได้รับ dual license ภายใต้ Apache 2.0 และ MIT เว้นแต่จะระบุเงื่อนไขอื่นไว้ต่างหาก
- การมีส่วนร่วมที่ส่งให้
stylo_taffy จะรวม MPL 2.0 ด้วย
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ผมเป็นหัวหน้านักพัฒนาของ Blitz ตอนนี้มันยังไม่ถึงขั้นสมบูรณ์ โดย ระบบรับข้อความ/โฟกัส ยังเป็นแบบพื้นฐาน และยังไม่รองรับการเลื่อนนอก root viewport CSS selector ที่ซับซ้อนอย่าง
nth-child,:hasยังทำงานได้ไม่ดีนัก และการผสานการจัดการอีเวนต์กับ Dioxus ซึ่งเป็นเฟรมเวิร์กคล้าย React ที่รันอยู่บน Blitz ก็ยังทำได้แค่ระดับคลิกเท่านั้น และยังไม่มีpreventDefaultตอนนี้ระบบเน็ตเวิร์กยังเรียบง่ายมาก โดยทำ synchronous request บน main thread และจำเป็นต้องมีเน็ตเวิร์กแบบ asynchronous หรือ multithreaded ที่เหมาะสมกว่านี้ งานด้านประสิทธิภาพก็แทบยังไม่ได้ทำ จึงมีการคำนวณ style/layout/paint ใหม่ทุกเฟรม และยังมี memory leak อยู่หลายจุดจาก node ที่ไม่ถูกเก็บกวาด ยังขาดเงา, เว็บฟอนต์,calc, float layout, และ form control อื่นนอกจาก text input พูดรวม ๆ คือใกล้เคียงกับคำว่า “การสร้าง webview เป็นงานใหญ่ และเรายังไปไม่ถึงจุดนั้น” มากกว่า โดยคาดว่าจะได้เห็นสภาพที่สมบูรณ์ขึ้น ภายใน 2~3 เดือน มีภาพหน้าจออยู่ที่นี่ด้วย: https://github.com/DioxusLabs/blitz/issues/23โปรเจกต์นี้ดูมีประโยชน์มากแม้ดูเผิน ๆ มันคือการสร้างแอปเนทีฟด้วย กระบวนทัศน์การจัดวาง HTML/CSS ที่ใช้กันอย่างแพร่หลาย แต่ตัดส่วนหนัก ๆ ที่มากับ JS/DOM/Browser API แบบเต็มออกไป ดูเหมือนว่าจะเปิดทางให้เกิดการปรับปรุงครั้งใหญ่ได้มากกว่าการแพ็กเอนจินเบราว์เซอร์แบบ Electron พอดีเมื่อไม่นานมานี้ผมฟัง Casey Muratori พูดวิจารณ์ CSS อย่างหนักในพอดแคสต์ของ Richard Feldman ตัวอย่างที่เขาเล่าว่าต้อง pre-render เว็บเพจและวัดผลแบบไดนามิกเพื่อสร้างความสัมพันธ์ด้าน layout ที่เรียบง่ายบางอย่างนั้นโดนใจมาก อย่างที่ Muratori ว่าไว้ การเขียน CSS ให้ความรู้สึกไม่ใช่การค่อย ๆ ประกอบจากองค์ประกอบพื้นฐานที่เรียบง่าย แต่ใกล้เคียงกับ การว่าความคดีในศาล มากกว่า แน่นอนว่าเพราะความคุ้นเคย ความเข้ากันได้ และความจริงที่ว่า “CSS ในเส้นทางที่ใช้งานได้ดี” นั้นมีประสิทธิผลสูงมาก ความต้องการที่โปรเจกต์แบบนี้ตอบโจทย์จึงมีอยู่มาก แต่ก็ดูเหมือนยังมีโอกาสในการมอบชั้นที่ง่ายกว่าและเป็นทั่วไปกว่าสำหรับผู้ใช้ที่อยากลงไปใช้งานในระดับล่าง อาจได้แรงบันดาลใจจาก CSS Houdini ที่พยายามทำให้ CSS ขยายความสามารถได้ผ่าน JS API และบางทีนี่อาจเป็นสิ่งที่ “Custom Widgets” หมายถึงก็ได้
floatออกก็ได้เมื่อหลายปีก่อน ไม่สิ 20 ปีก่อน ผมเคยทำโปรเจกต์โอเพนซอร์สคล้ายกันชื่อ Flying Saucer เป็น HTML + CSS2 renderer บน Java ล้วน ผมเคยจินตนาการว่าจะใช้มันเรนเดอร์ rich text UI ในเกม แต่สุดท้ายการใช้งานหลักจริง ๆ คือการสร้าง PDF ฝั่งเซิร์ฟเวอร์ ตอนนั้นการสร้าง HTML แล้วเรนเดอร์เป็น PDF ง่ายกว่าการใช้ API สำหรับสร้างรายงาน PDF หลายตัวที่มีให้เลือกในยุคนั้นมาก Blitz ดูเท่มาก และผมก็ตื่นเต้นที่จะได้เห็นไลบรารี GUI ฝั่ง Rust เพิ่มขึ้นอีก https://en.wikipedia.org/wiki/Flying_Saucer_(library) น่าประหลาดที่มันยังอัปเดตอยู่จนถึงทุกวันนี้: https://github.com/flyingsaucerproject/flyingsaucer/releases...
ฟังดูมีอนาคตดีมากกับคำว่า “WebView น้ำหนักเบาที่แทนที่ JavaScript engine ด้วย Native Rust API” โดยพื้นฐานแล้วถ้ามันเป็นอะไรประมาณ Tauri ที่ไม่มี JS อยู่ในเส้นทางการทำงาน แค่ได้ยินก็น่าสนใจแล้ว
น่าสนใจมาก วันนี้เองผมเพิ่งเจอเรื่องสยองกับ puppeteer และ headless Chromium และกำลังหาตัวแทน wkhtmltopdf อยู่พอดี อย่าไปรันโดยใส่ jemalloc ไว้ใน
LD_PRELOADเด็ดขาด ปัญหาแก้ได้แล้วก็จริง แต่ผมชอบแนว renderer ที่เรียบง่ายกว่ามากไม่ได้พูดถึง Blitz โดยตรง แต่ผมเพิ่งรู้จัก Dioxus เป็นครั้งแรก ผมสงสัยว่าพวกเฟรมเวิร์กที่คอมไพล์เป็น WASM มี กฎที่ไม่ได้พูดออกมา อะไรหรือเปล่าว่าอย่าโชว์เดโมให้ชัด ๆ หรือไม่ก็อย่าโฮสต์เว็บตัวเองด้วยเฟรมเวิร์กนั้น ผมรู้สึกว่าเจอแบบนี้มา 5–6 ครั้งแล้ว บนหน้าเว็บของ Dioxus มองเห็นว่าไฟล์ WASM ถูกโหลด แต่ไม่ชัดเจนว่ามันถูกใช้ตรงไหน หรือถูกใช้จริงหรือไม่
ถ้าใช้ร่วมกับ backend และ htmx ก็น่าจะเจ๋งดี แค่สงสัยว่าจะทำได้อย่างไรถ้าไม่มี JS engine เข้ามาเกี่ยวเลย
กับที่ส่ง HTTP request ได้ ทำไมถึงควรมีแค่ click กับ submit event ที่ใช้ทริกเกอร์ request ได้ ทำไมถึงควรมีแค่ GET กับ POST และทำไมถึงควรแทนที่ได้แค่ทั้งหน้าจอ ถ้ามองอีกแบบ HTMX ทำให้องค์ประกอบ HTML ถูกจำกัดน้อยลงและเป็นแบบทั่วไปมากขึ้น ถ้าออกแบบ web renderer โดยคำนึงถึงสิ่งนี้ตั้งแต่แรก มันอาจเรียบง่ายขึ้นด้วยซ้ำวันนี้ผมเพิ่งรู้จัก Dioxus เหมือนกัน https://dioxuslabs.com/
เจ๋งมาก อยากลองใช้ในโปรเจกต์ C++ คำถามหนึ่งที่ผุดขึ้นมาคือเรื่อง ประสิทธิภาพ ผมสงสัยว่าจะเรนเดอร์หน้าที่ค่อนข้างซับซ้อนด้วยเฟรมเรตสูง ๆ ได้ไหม ปกติผมใช้ ImGUI ซึ่งยอดเยี่ยมมากจนแทบไม่ต้องคิดเรื่องปัญหาประสิทธิภาพเวลาแสดงข้อมูลแบบเรียลไทม์ ตรงกันข้าม web rendering ของ Chromium แค่ให้อัปเดตข้อความใน DOM แบบง่าย ๆ ที่ 10 เฟรมต่อวินาทีก็กิน CPU หนักแล้ว ถ้าแก้จุดนี้ได้เกมอาจเปลี่ยนเลย