- สามารถรวม โปรเจกต์ Deno ที่สร้างด้วยเว็บแอปและโค้ด TypeScript ให้เป็นไบนารีแอปเดสก์ท็อปที่แจกจ่ายซ้ำได้ตามแพลตฟอร์ม
- เอาต์พุตจะรวมโค้ดแอปพลิเคชัน, Deno runtime, และเอนจินเรนเดอร์เว็บไว้ด้วยกัน โดยฟีเจอร์นี้ถูกรวมเข้ามาใน Deno v2.9.0 แล้ว แต่ยังไม่ใช่รุ่นเสถียร
- WebView backend เริ่มต้นใช้ webview ที่มีมาในระบบปฏิบัติการเพื่อให้ได้ ไบนารีขนาดเล็ก และหากต้องการความสม่ำเสมอของการเรนเดอร์ก็สามารถเลือก backend แบบ Chromium (CEF) ได้
- รองรับการตรวจจับโปรเจกต์ Next.js, Astro, Fresh, Remix, Nuxt, SvelteKit, SolidStart, TanStack Start และ Vite SSR แล้วรันเซิร์ฟเวอร์ให้เหมาะกับโหมดรีลีสและโหมดพัฒนา
--hmr
- การสื่อสารระหว่างโค้ด Deno กับ webview ใช้ in-process channel แทน IPC แบบ socket และยังครอบคลุมถึง cross compile กับการอัปเดตอัตโนมัติบนพื้นฐานของ bsdiff
บทบาทและสถานะปัจจุบันของ deno desktop
deno desktop ใช้แปลงโปรเจกต์ Deno ให้เป็น แอปเดสก์ท็อปแบบ self-contained
- อินพุตทำได้ตั้งแต่ไฟล์ TypeScript เดี่ยวไปจนถึงแอป Next.js
- เอาต์พุตคือไบนารีที่แจกจ่ายซ้ำได้ตามแพลตฟอร์ม
- ภายในไบนารีมีทั้งโค้ดแอปพลิเคชัน, Deno runtime และเอนจินเรนเดอร์เว็บ
- ฟีเจอร์นี้รวมอยู่ใน Deno v2.9.0 แล้ว แต่ยังไม่ใช่รุ่นเสถียร
- หากต้องการลองตอนนี้ ต้องติดตั้งบิลด์
canary ด้วย deno upgrade canary
- คำสั่ง, คีย์การตั้งค่า และ TypeScript API อาจเปลี่ยนแปลงได้ก่อนจะเสถียร
การเลือก backend และการรันโปรเจกต์เว็บ
- แนวทางนี้ใช้เทคโนโลยีเว็บเป็น UI toolkit สำหรับเดสก์ท็อป พร้อมลด trade-off ที่มักเจอในเครื่องมือทำแอปเดสก์ท็อปที่อิงเว็บสแตกเดิม
- เครื่องมืออย่าง Electron, Tauri และ Electrobun อาจมี trade-off เช่น ไบนารีขนาดใหญ่, รองรับแพลตฟอร์มไม่ครบ, ขาด ecosystem ของ JavaScript, ไม่มีระบบอัปเดตในตัว หรือไม่มีการผสานกับเฟรมเวิร์ก
- WebView backend เริ่มต้นใช้ webview ของระบบปฏิบัติการเพื่อมุ่งไปที่ ไบนารีขนาดเล็ก
- สามารถใช้ ecosystem ของ npm ได้ผ่านชั้นความเข้ากันได้กับ Node ของ Deno
- หากต้องการให้การเรนเดอร์เหมือนกันบน macOS, Windows และ Linux ก็สามารถเลือก CEF backend ที่ bundle Chromium มาได้
- การตรวจจับเฟรมเวิร์กอัตโนมัติเป็นแนวทางให้รันโปรเจกต์เว็บเดิมบนเดสก์ท็อปได้โดยไม่ต้องแก้โค้ด
- รองรับ Next.js, Astro, Fresh, Remix, Nuxt, SvelteKit, SolidStart, TanStack Start และ Vite SSR เป็นต้น
- ในโหมดรีลีสจะรัน production server
- ใน
--hmr จะรัน development server ที่มี hot reload
การสื่อสารใน runtime, การ build และการอัปเดต
- การสื่อสารระหว่าง backend กับ UI ใช้ in-process channel
- ค่าต่าง ๆ จะถูกเข้ารหัสเมื่อข้ามขอบเขตการเรียก
- ไม่มีการวิ่งไปกลับข้ามโปรเซสระหว่างโค้ด Deno กับ webview
- สามารถ cross compile สำหรับ macOS, Windows และ Linux ได้จากเครื่องเดียว
- backend จะไม่ถูก build แบบ local แต่จะดาวน์โหลดเมื่อจำเป็น
- ระบบอัปเดตอัตโนมัติเป็นการอัปเดตส่วนต่างของไบนารีในตัว โดยใช้ manifest
latest.json และ bsdiff patch
- runtime จะจัดการการ polling, การนำไปใช้ และการ rollback เมื่อการรันล้มเหลว
ตัวอย่างง่าย ๆ และโครงสร้างเอกสาร
- แอปเดสก์ท็อปแบบไฟล์เดียวสามารถสร้างได้โดยเขียน
main.ts ให้ Deno.serve() ส่งคืน HTML response แล้วรัน deno desktop main.ts
Deno.serve(() =>
new Response("Hello, desktop
", {
headers: { "content-type": "text/html" },
})
);
deno desktop main.ts
- ไบนารีที่คอมไพล์แล้วจะเปิดหน้าต่างที่ชี้ไปยัง local HTTP server ซึ่ง bind อยู่กับ handler ของ
Deno.serve()
- บน macOS/Linux ให้รันด้วย
./main
- บน Windows ให้รันด้วย
.\\main.exe
Deno.serve() จะ bind เข้ากับที่อยู่ที่ webview จะเปิดโดยอัตโนมัติ จึงไม่จำเป็นต้องส่งพอร์ตหรือชื่อโฮสต์
- เอกสารที่เกี่ยวข้องแบ่งเป็นการตั้งค่า, backend, HTTP serving, framework, การจัดการหน้าต่าง, binding, เมนู, tray และ dock, dialog, การแจ้งเตือน, HMR, DevTools, การอัปเดตอัตโนมัติ, การรายงานข้อผิดพลาด, การ deploy, การเปรียบเทียบ และ CLI reference
Deno.BrowserWindow เกี่ยวข้องกับวงจรชีวิตของหน้าต่าง, หลายหน้าต่าง และอีเวนต์
Deno.autoUpdate() เกี่ยวข้องกับ manifest, bsdiff และ rollback
bindings.() คือวิธี binding สำหรับเรียกโค้ด Deno จาก webview
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ดูเหมือนว่า Deno Desktop จะเลือกจุดประนีประนอมนี้แบบ ชัดเจนมาก พอสมควร: “ค่าเริ่มต้นให้เล็ก แต่ Node compatibility ให้ครบถ้วน”
ผมลองรัน Hello World 5 บรรทัดในบทความด้วย
deno desktop index.tsแล้วบน Windows 10 ผลลัพธ์ออกมาเป็น 442MBนึกว่าจะเล็กกว่า Electron build แต่กลับใหญ่กว่ามากจนน่าตกใจ โดย
libcef.dllมีขนาด 247MB และdeno-test.dllที่ใส่ Hello World มีขนาด 78MBเลยสงสัยว่าผมทำอะไรผิดหรือเปล่า
ก็เลยหวังว่าน่าจะมีทางออกแบบใช้ซ้ำพวก OS webview แล้วลดลงมาเหลือ ต่ำกว่า 20MB ได้ แต่พอเกิน 400MB มันก็รู้สึกเหมือนโฆษณาเกินจริงนิดหน่อย
อาจเป็นเพราะตั้งค่าผิดก็ได้ เลยสงสัยว่านอกจาก
deno desktop test.tsแล้วยังต้องทำอะไรเพิ่มอีกไหมตรงที่บอกว่า “แทนที่แต่ละแอปจะ bundle CEF กันเอง ถ้าจัดการ shared CEF runtime ได้ ก็อาจลดขนาดไบนารีต่อแอปลงเหลือไม่กี่ MB และอยู่ใน roadmap” น่าสนใจดี
ผมไม่ค่อยรู้เรื่อง CEF เลยสงสัยว่าการจัดการเวอร์ชันจะเป็นยังไง
ถ้าแต่ละแอปต้องการ CEF คนละเวอร์ชัน สุดท้ายจะย้อนกลับไปเป็นโมเดลแบบ Electron ที่แต่ละแอปต้องแบกเบราว์เซอร์ของตัวเองอยู่ดีไหม หรือแม้ในกรณีนั้นก็ยังมีข้อดีของ shared runtime เหลืออยู่หรือเปล่า
https://docs.deno.com/runtime/desktop/comparison/
https://github.com/chromiumembedded/cef
ผลลัพธ์ออกมาไม่ได้ดีนัก แต่ผมก็ไม่แน่ใจว่าเป็นปัญหาของตัวเทคโนโลยี CEF เอง หรือเป็นเพราะองค์ประกอบ/โปรเซสอื่น
https://www.riotgames.com/en/news/architecture-league-client...
แอป Electron บนเดสก์ท็อปแทบทั้งหมดในความเป็นจริงก็ใช้ Chromium คนละเวอร์ชัน กันอยู่แล้ว และบางครั้งก็ต้องค้างเวอร์ชันเก่าไว้เพราะกลัวอัปเกรดแล้วพัง
ถ้าเป็น Windows ก็แนวเดียวกับ WebView2
Deno ยังคงน่าประทับใจอยู่เรื่อย ๆ
ผมไม่ได้เริ่มโปรเจ็กต์ใหม่โดยไม่ใช้ Deno มาพักใหญ่แล้ว และตอนนี้ก็สนับสนุน ecosystem ของ Deno เต็มตัวมากกว่า Node.js ไปแล้ว
ไม่แน่ใจว่าจะได้ใช้ฟีเจอร์นี้บ่อยแค่ไหน แต่การมีตัวเลือกเพิ่มขึ้นก็ดีมากจริง ๆ
งานที่น่าประทับใจ
น่าจะน่าสนใจมากเวลาทำ desktop app ด้วย vibe coding
เครื่องมืออย่าง Lovable, Bolt, v0 มักใช้ TypeScript เป็นค่าเริ่มต้นเวลาสร้างเว็บแอป เลยดูเข้ากันได้ดี
ปกติผมใช้ Go/Wails แทนการ bundle Chromium กับ Node สำหรับเดสก์ท็อปแอปเล็ก ๆ ส่วน Electron ก็ทำหน้าที่ของมันได้ดี แต่ bundle ที่ใหญ่ขนาดนั้นเป็นสิ่งที่ผมรู้สึกต่อต้านอย่างชัดเจน
ผมสงสัยว่ามันจะผสานกับ ระบบสิทธิ์ ซึ่งเป็นหนึ่งในจุดแข็งที่สุดของ Deno ยังไง
โดยเฉพาะเวลาปล่อยให้เอเจนต์ไปวิ่งทำอะไรก็ได้บนเครื่องของผม เรื่องนี้ยิ่งสำคัญ
ในเอกสารอ้างอิงของ CLI บอกว่า “สิทธิ์ที่ให้ตอนคอมไพล์จะถูกฝังเข้าไปในไบนารีที่คอมไพล์แล้ว”
ถ้าสามารถแสดงออกมาให้ผู้ใช้รู้และตัดสินใจได้ว่าจะให้สิทธิ์อะไรบ้าง ก็น่าจะดี
https://docs.deno.com/runtime/reference/cli/desktop/#runtime...
ถ้าในจุดนั้นยังแสดง Deno permission prompt ขึ้นมา ผมคิดว่าอาจทำให้เข้าใจผิดมากกว่า เพราะไม่มี หลักประกันความถูกต้องสมบูรณ์ ของสิทธิ์นั้น
คือแนวทางนำระบบสิทธิ์ของ Deno มาใช้กับ desktop sandboxing โดยเด้ง permission prompt ทุกครั้งที่เข้าถึง filesystem หรือ network
เป็นฟีเจอร์ที่ฉลาดมากสำหรับการเปิดตัว
เวลาต้องตัดสินใจว่าจะใช้แพลตฟอร์มไหน ผมว่านี่น่าจะเป็นตัวเลือกที่ควรหยิบมาพิจารณาอย่างจริงจัง
ถ้าได้ทั้ง ขนาดติดตั้งเล็ก และ cross-platform ก็ดูเป็นทางเลือกที่ดีแทน Electron หรือ Tauri
ผมคิดว่าสำนวนที่ว่า “เว็บเทคโนโลยีคือ UI toolkit ที่เป็นที่รู้จักมากที่สุดในโลก” ไม่ค่อยเหมาะเท่าไร
เหตุผลที่แอป Electron ถูกวิจารณ์หนักก็เพราะมันแทบจะอยู่คนละขั้วกับการเป็น UI toolkit
หลายครั้งมันทำตามแพตเทิร์น UI ของ OS โฮสต์ได้ไม่ดีนัก
เว็บเทคโนโลยีก็เป็นแค่เว็บเทคโนโลยี มันเรนเดอร์ปุ่มได้ก็จริง แต่ไม่มีอะไรรับประกันว่าต่อให้เป็นปุ่มที่ยังไม่ใส่สไตล์จะดูเหมือน native ของ OS และยังต่างกันไปตามแต่ละเบราว์เซอร์
เป้าหมายไม่เคยเป็นแค่ “UI toolkit” หรือ “การทำตามแพตเทิร์น UI ของ OS โฮสต์”
Chromium มีความสามารถมหาศาลอยู่ในนั้น และ Electron ก็ดึงยูทิลิตีเหล่านั้นมาใช้ตรง ๆ ซึ่งเป็นข้อดี
เช่น ถ้าเคยทำงานวิดีโอมาก่อน จะรู้ว่าการใช้ศักยภาพทั้งหมดของเบราว์เซอร์สมัยใหม่ภายในเดสก์ท็อปแอปนั้นเปลี่ยนเกมมาก
ไม่ใช่แค่การเล่นวิดีโอ แต่รวมถึงการทรานส์โค้ดที่ทำได้ด้วยเว็บสมัยใหม่และ WebCodecs ซึ่งถ้าจะไปทำเองทั้งหมดนั้นเป็นงานใหญ่มาก และยิ่งเป็นเดสก์ท็อปแอปที่ต้องรันบน Windows/macOS/Linux ก็ยิ่งหนักเข้าไปอีก
ผมมีแอปตัวหนึ่งที่ทำด้วย Electron ในเวลาไม่กี่สิบชั่วโมง แต่ถ้าใช้วิธีอื่นน่าจะกินเวลาเป็นหลายสิบวัน และต่อให้ใช้ AI ถ้าไม่ใช่ผู้เชี่ยวชาญด้านวิดีโอก็คงยากอยู่ดี
ก็ไม่ได้เคยอ้างว่าเป็น UI แบบ “native”
UI แบบ native ของ Linux ดูไม่สวยมาตลอดอยู่แล้ว และผมกลับรู้สึกว่าการใช้ HTML+CSS layout ที่จัดมาดี ๆ ดีกว่ามาก
จากประสบการณ์ของผม Electron มักโดนด่าว่ากินทรัพยากรและช้าเป็นหลัก ส่วนเรื่องไม่ native เป็นแค่ประเด็นเสริมที่คนชอบหยิบมาเพิ่ม
ผมอยากทำการผสานกับเบราว์เซอร์โดยตรงมานานแล้ว ใช้ HTML+CSS ทำเลย์เอาต์แต่ไม่ต้องมี JavaScript runtime
ไม่รู้ว่า Servo เบาแค่ไหน แต่ก็หวังว่าวันหนึ่งไอเดียแบบนั้นจะเกิดขึ้นจริง
ในฐานะผู้ใช้ผมพอใจมาก แม้ว่าฟีเจอร์พื้นฐานอย่าง accessibility จะยังขาดอยู่บ้าง แต่คิดว่าน่าจะมีเร็ว ๆ นี้
ในมุมของนักพัฒนา นอกจาก Rust แล้วก็ไม่ค่อยรู้ว่ามีอุปสรรคอะไร และในขณะเดียวกัน Rust เองก็เป็นจุดเด่นด้วย
มันเป็นเรื่องของเมื่อราว 25 ปีก่อน และหลังจากที่แม้แต่ Microsoft ก็เริ่มไม่ใส่ใจแล้ว คนอื่นก็แทบไม่สนกันอีก
ผมไม่อยากให้แอปของตัวเองหน้าตาต่างกันไปตามแต่ละ OS
ผมไม่มีทรัพยากรพอจะทดสอบบนทุกอุปกรณ์ และการที่หน้าจอที่ทดสอบบนระบบหนึ่งดูเหมือนกันเป๊ะบนอีกระบบหนึ่งเป็นข้อดีใหญ่มาก
ยินดีที่มีคู่แข่งเกิดขึ้นในพื้นที่นี้
โดยเฉพาะ Deno ที่ตอนนี้ไม่ได้แค่ลบ type ออกเหมือน Node implementation ปัจจุบัน แต่ รัน TypeScript จริง ๆ ได้โดยตรง ซึ่งดีมาก
แต่ก็คิดว่าสิ่งนี้น่าจะดึงส่วนแบ่งตลาดของ Tauri ไปได้พอสมควร
ตอนนี้ยังมีเหตุผลอะไรให้ใช้ Tauri อีก?
สำหรับการเชื่อมต่ออินเทอร์เน็ตส่วนใหญ่ การเพิ่มขนาด bundle อีก 150MB ต่างกันแค่เวลาโหลด 1-10 วินาที แลกกับการได้ rendering engine ที่เชื่อถือได้
ถ้าจะตรวจ type ต้องรันด้วย
deno run --checkหรือใช้คำสั่งย่อยdeno checkแยกต่างหากระหว่างพัฒนาปกติ IDE ก็มักจะช่วยตรวจ type และ lint ให้อัตโนมัติอยู่แล้ว เลยไม่ใช่ปัญหาใหญ่
จริง ๆ แล้วไม่ใช้ JavaScript เลยก็ได้
และเราก็เห็นสตาร์ตอัปสาย developer framework อย่าง Astro, Nuxt, UV, Bun, Vite ถูกซื้อกิจการกันมาหลายรายแล้ว
ถ้าเป็นซอฟต์แวร์ที่ต้องอยู่และได้รับการสนับสนุนต่อเนื่องหลายปี กระแสแบบนั้นไม่ได้สร้างความเชื่อมั่นนัก
Deno Desktop กับ Tauri ไม่ใช่ว่าทั้งคู่ก็ใช้ system webview เหมือนกันหรอกหรือ?
แล้วทำไมต้องใช้ตัวนี้แต่ไม่ใช้ Electron?
ในเอกสารที่ Deno ปล่อยออกมา ส่วนที่ผมชอบที่สุดคือ หัวข้อเปรียบเทียบ
บรรทัดสุดท้ายระบุว่าการรองรับ iOS/Android ของ Electron เป็น “no” ส่วน Deno เป็น “not yet” ซึ่งถ้าทำได้จริงจะใหญ่มาก
ดูเหมือนจะเหมาะมากสำหรับการแจกจ่ายเว็บเกมเป็น แอปบน Steam หรือแอปสำหรับการซื้อออนไลน์
ผมน่าจะลองใช้ดู