2 คะแนน โดย GN⁺ 2024-12-21 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Clay เป็นไลบรารีเลย์เอาต์ UI อัตโนมัติสไตล์ Flexbox ที่สร้างด้วยภาษา C โดยมุ่งให้สามารถจัดวาง UI แบบประกาศได้ แม้ในเอนจินแบบกำหนดเองหรือสภาพแวดล้อมระดับต่ำ
  • แจกจ่ายในรูปแบบ ไฟล์เฮดเดอร์ เดียว ใช้งานได้ใน C/C++ และเน้นว่ามีโค้ด C99 ประมาณ 2,000 บรรทัด พร้อมผลลัพธ์ที่คอมไพล์เป็น .wasm ขนาด 15KB
  • ไม่มี dependency แม้รวมถึง C standard library และสามารถใช้งานแยกจากวิธีเรนเดอร์อย่าง Raylib, WebGL Canvas, HTML ได้
  • เร็วพอที่จะคำนวณ UI ทั้งหมดใหม่ทุกเฟรม ใช้ หน่วยความจำพื้นฐาน 3.5MB และทำงานด้วยการจัดสรรแบบ static กับการนำกลับมาใช้ซ้ำ โดยไม่ต้องใช้ malloc/free
  • สามารถผสมลูป เงื่อนไข และฟังก์ชันของโค้ด C เข้ากับลำดับชั้น UI ได้ และตรวจสอบสถานะเลย์เอาต์แบบเรียลไทม์ด้วยเครื่องมือดีบักในตัว

เฮดเดอร์เดี่ยว C99 และโมเดลหน่วยความจำ

  • Clay เป็นไลบรารีเลย์เอาต์อัตโนมัติสไตล์ Flexbox บนพื้นฐานภาษา C
    • ใช้ไวยากรณ์แบบ declarative
    • ชูจุดเด่นด้านประสิทธิภาพระดับไมโครวินาที
    • เว็บเพจปัจจุบันเองก็จัดเลย์เอาต์ด้วย Clay
  • แจกจ่ายในรูปแบบ ไฟล์เฮดเดอร์ เดียว
    • ใช้ได้ใน C/C++
    • include ด้วยรูปแบบ #include clay.h
    • ประกอบด้วยโค้ด C99 ประมาณ 2,000 บรรทัด
    • ไม่มี dependency รวมถึง C standard library
    • เมื่อคอมไพล์เป็น .wasm จะมีขนาด 15KB
  • แนวทางด้านประสิทธิภาพและการใช้หน่วยความจำออกแบบมาโดยคำนึงถึง การอัปเดต UI แบบเรียลไทม์
    • เร็วพอที่จะคำนวณ UI ทั้งหมดใหม่ได้ทุกเฟรม
    • การใช้หน่วยความจำพื้นฐานคือ 3.5MB
    • ใช้การจัดสรรแบบ static และการนำกลับมาใช้ซ้ำ
    • ไม่ใช้ malloc และ free
    • สามารถทำให้การออกแบบ animation และ UI แบบ responsive ง่ายขึ้นได้ โดยไม่ต้องใช้เทคนิคหลบเลี่ยงด้านประสิทธิภาพแบบมาตรฐาน

UI แบบ declarative และการแยก renderer

  • ไวยากรณ์แบบ declarative เน้นการจัดลำดับชั้นขององค์ประกอบ UI ที่ซ้อนกันให้อ่านง่าย
    • สามารถผสมองค์ประกอบ UI เข้ากับลูป เงื่อนไข และฟังก์ชันของภาษา C ได้
    • สามารถสร้างไลบรารีคอมโพเนนต์ที่นำกลับมาใช้ซ้ำได้จากองค์ประกอบพื้นฐานของ UI เช่น ข้อความ รูปภาพ และสี่เหลี่ยม
  • Clay ไม่ผูกติด กับ renderer และแพลตฟอร์ม
    • Clay จัดการเลย์เอาต์ ส่วนการเรนเดอร์ทำได้ด้วย Raylib, WebGL Canvas, HTML ฯลฯ
    • เอาต์พุตเป็นอาร์เรย์ที่เรียงลำดับของคำสั่งเรนเดอร์พื้นฐาน เช่น RECTANGLE, TEXT, IMAGE
    • สามารถเขียน renderer เองด้วยโค้ดไม่กี่ร้อยบรรทัด หรือใช้ตัวอย่างที่มีให้
    • มี HTML renderer ให้ด้วย และหน้าปัจจุบันนี้เป็นตัวอย่างดังกล่าว
  • รวม เครื่องมือดีบัก ในตัว
    • มีเครื่องมือดีบักสไตล์ Chrome Inspector
    • สามารถดู hierarchy ของเลย์เอาต์และการตั้งค่าได้แบบเรียลไทม์
    • สามารถกดปุ่ม d บนหน้าเว็บเพื่อทดลองใช้เครื่องมือดีบักได้

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

 
GN⁺ 2024-12-21
ความคิดเห็นบน Hacker News
  • ดูดี และวิดีโอ YouTube ที่นักพัฒนาอธิบายเองก็ยอดเยี่ยม: https://www.youtube.com/watch?v=DYWTw19_8r4

    • คำอธิบายที่ชัดเจนและเข้าใจง่ายแบบนี้หาได้ยาก แต่วิดีโอนี้ดีจริง ๆ
    • ดูเหมือนนักพัฒนากำลังค้นพบแนวคิดของไลบรารี GUI ขึ้นมาใหม่
      รูปแบบสมัยใหม่คือ GUI แบบใช้เมาส์ที่ Xerox สร้างขึ้นในทศวรรษ 1970 ต่อมาถูกทำเป็นเชิงพาณิชย์ใน Xerox Star และเป็นสายธารที่ Jobs ได้รับอิทธิพลไปสู่ Apple Lisa ส่วน Gates ก็ได้รับอิทธิพลไปสู่ MS Windows
      GUI framework เป็นตัวกำหนดหน้าตาและความรู้สึกของแพลตฟอร์ม และชี้ขาดว่านักพัฒนาจะสร้างแอปได้ง่ายแค่ไหน จึงกลายเป็นแกนหลักของการแข่งขันระหว่างแพลตฟอร์มหลายแขนง เช่น ระบบปฏิบัติการ เบราว์เซอร์ และกราฟิกเอนจิน
  • ค่อนข้างเจ๋งที่ทำได้ด้วยโค้ดไม่กี่พันบรรทัด
    แต่ผมชอบ CSS Grid มากกว่า Flex เลยทำไลบรารีเลย์เอาต์ CSS Grid ด้วย Nim ล้วน ๆ และค่อนข้างภูมิใจกับมัน: https://github.com/elcritch/cssgrid
    อยากลองดู Clay และเปรียบเทียบอัลกอริทึมเลย์เอาต์ด้วย การได้เห็นกล่องปรับขนาดตัวเองด้วยอัลกอริทึมที่เราเขียนเองมันสนุกดี
    และก็สงสัยว่าจะเปิดเผย C interface ได้ไหม

    • เจ๋งดี ผมก็มีอิมพลีเมนต์ CSS Grid แบบแยกอิสระที่เขียนด้วย Rust: https://github.com/DioxusLabs/taffy
      รองรับทั้ง Flexbox และ Block layout ด้วย และไลเซนส์ทั้งคู่ก็ดูเหมือน MIT ดังนั้นจะหยิบส่วนที่ต้องใช้ไปก็ได้ แต่อาจเพิ่มไฟล์ LICENSE ไว้จะได้หาเจอง่ายขึ้น
      เป้าหมายคือให้เข้ากันได้กับเว็บอย่างสมบูรณ์ แต่ยังไปไม่ถึงเต็มที่ และส่วนที่น่าจะน่าสนใจเป็นพิเศษคือชุดทดสอบที่ค่อนข้างใหญ่
      การทดสอบนิยามเป็นชิ้นส่วน HTML แล้วรัน Chrome ผ่าน webdriver เพื่อดึง assertion ที่ถูกต้องออกมา จากนั้นแปลงเป็น unit test แบบโค้ดล้วน หากต้องการก็เขียนตัวสร้างการทดสอบเองแล้วนำชิ้นส่วนของเราไปใช้ซ้ำได้
      โครงสร้างพื้นฐานการทดสอบนี้ยังแชร์บางส่วนกับ Yoga ซึ่งเป็นอิมพลีเมนต์ Flexbox ภาษา C++ ที่ขับเคลื่อน React Native: https://github.com/facebook/yoga
    • การคำนวณเลย์เอาต์ CSS Grid ที่ถูกต้องนั้นใกล้เคียงกับการแก้ระบบสมการและข้อจำกัด
      ในกรณีง่าย ๆ ที่เซลล์ไม่ได้คร่อมหลายช่องเหมือน Flexbox จะทำได้ค่อนข้างง่าย แต่ถ้าไม่ใช่ก็ไม่ธรรมดา จึงต้องใช้แนวทางอย่างตัวแก้แบบซิมเพล็กซ์หรือ Cassowary: https://constraints.cs.washington.edu/solvers/cassowary-tochi.pdf
  • ตอนท้ายมีปุ่มสลับระหว่าง HTML กับ Canvas ซึ่งปกติแทบไม่เห็นความต่างเลย ถือว่าเจ๋ง
    แต่บน iOS Safari ร่วมกับ Dark Reader หน้า HTML จะเปลี่ยนเป็นโหมดมืด แต่หน้า Canvas ไม่เปลี่ยน เลยทำให้จุดว้าวสำหรับผมหายไป
    ถึงอย่างนั้นก็ดูดี

    • การเลือกข้อความและการซูมเข้า/ออกก็มีปัญหา
    • มีข้อความว่า “มี HTML renderer ด้วย สิ่งที่คุณกำลังดูอยู่ตอนนี้ก็คือมัน!” แต่ตอนที่อ่านอยู่นั้นผมสลับไปเป็น Canvas renderer แล้ว
    • ใน Chrome HTML renderer เร็วกว่าชัดเจน เลยสงสัยว่าเพราะอะไร
      Canvas ก็เร็วพออยู่แล้ว แต่รู้สึกได้ถึงความต่างตอนดูแอนิเมชัน “High performance” หรือเลื่อนหน้า
  • เลือกข้อความทั้งหมดที่อยู่หลังแอนิเมชันไม่ได้
    เหมือนมีอะไรบางอย่างแย่งโฟกัสไป และพอพยายามเลือกข้อความ การเลือกก็ถูกยกเลิกทันที

    • น่าจะเพราะรีเซ็ตทั้งหมดทุกเฟรม และแอนิเมชันกำลังเล่นอยู่
    • บนมือถือเกิดอาการเดียวกันทั้งในเบราว์เซอร์ที่ใช้ Chromium และ Gecko
      ที่น่าสนใจคือ Firefox เรนเดอร์หน้านี้ได้แย่กว่ามาก: https://imgur.com/a/DNYe2WN
  • เป็นการตีความสไตล์ UI ที่ผมชอบมากได้อย่างน่าพอใจ
    วิธีแยกตรรกะ UI กับการวาดออกเป็นชุดคำสั่งการวาดนั้นยอดเยี่ยมและยืดหยุ่นมาก ผมเห็นครั้งแรกใน microui และการแยกแบบนั้นทำให้ใช้ไลบรารีบนเบราว์เซอร์ผ่าน WASM กับ Canvas2D ได้ง่าย: https://rxi.github.io/microui_v2_an_implementation_overview.html
    อีกอย่าง ไอเดียการคำนวณเลย์เอาต์ใน WASM แล้วเรนเดอร์เป็น HTML ก็ดีมาก ไม่รู้ทำไมก่อนหน้านี้ถึงไม่เคยนึกถึง

  • ตอนแรกคิดว่าจำเป็นต้องทำด้วย C ไหม ใช้ Haskell หรือ OCaml น่าจะทำให้ปลอดภัยกว่าได้หรือเปล่า
    แต่ถ้าเป็นโค้ด C 2000 บรรทัดและไม่มี dependency ก็ถือว่าเจ๋งทีเดียว

    • อย่างน้อยทำแบบนี้ก็ใช้ได้จากภาษาอื่นด้วย
  • มี taffy ที่เขียนด้วย Rust ด้วย และ C binding กำลังอยู่ระหว่างทำ: https://crates.io/crates/taffy

  • ถือว่าดีสำหรับฉบับร่างแรก
    แต่ก็น่าเสียดายที่เอาต์พุต HTML มีแต่ div element และถ้าใส่ใจเรื่องการเข้าถึงอีกสักหน่อยก็น่าจะดีขึ้นมาก
    อีกปัญหาคือเมื่อพยายามเลือกข้อความในหลายจุด มันจะเรนเดอร์ใหม่จนการเลือกถูกยกเลิกก่อนจะกด control-c ได้

  • ถ้าถามกันจริงจัง ผมว่าแม้แนวคิดจะดูเจ๋ง แต่การเขียนเว็บเพจแบบนี้อาจจะเกินไปหน่อยหรือเปล่า
    เป็นรูปแบบที่มีการเรียกอย่าง CLAY(...), CLAY_TEXT(...), LandingPageBlob(...) ซ้อนลึกอยู่ใน LandingPageDesktop() และซอร์สตัวอย่างอยู่ที่นี่: https://github.com/nicbarker/clay/blob/35d72e5fba6872be48d15ed9d84269a86cd72b4e/examples/clay-official-website/main.c#L50C1-L67C2

  • เป็นงานที่ยอดเยี่ยม ผมคิดว่าในเบราว์เซอร์ ข้อความที่เลือกได้ เป็นสิ่งจำเป็น
    สำหรับไคลเอนต์และแอปที่ไม่ต้องการฟังก์ชันแบบนั้น หรือสามารถ提供เองได้ นี่ดูเป็นโซลูชันที่เล็กมากและดีมาก

    • การเห็นการเลือกข้อความและการคัดลอก/วางพังไปเป็นเรื่องแปลก แต่ก็ดูเหมือนจะแก้ได้
      อาจจะพูดเรื่องเดิมซ้ำอีกแล้ว แต่ผมรู้สึกว่าในบรรดาการเปลี่ยนแปลงของ UI ช่วงไม่กี่ปีที่ผ่านมา การถดถอยของ ความเป็นสากลของคลิปบอร์ด เป็นหนึ่งในความสูญเสียที่ถูกประเมินต่ำที่สุด ควบคู่ไปกับการถดถอยของความสามารถในการลิงก์และการฝังเนื้อหา