2 คะแนน โดย GN⁺ 2024-10-16 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เป็นศูนย์รวมเอกสาร WebAssembly·JavaScript API ไว้ในที่เดียวสำหรับนักพัฒนาที่ต้องการ ใช้งาน sqlite3 โดยตรง บนเบราว์เซอร์รุ่นใหม่ที่รองรับ WASM
  • หากต้องการเริ่มใช้งานอย่างรวดเร็ว สามารถเริ่มจาก HOWTO 3 ขั้นตอน และตรวจสอบเส้นทางการติดตั้งและการเผยแพร่ได้จากเอกสารดาวน์โหลด·npm module·การบิลด์·รายละเอียด Emscripten
  • เอกสาร API ครอบคลุมตั้งแต่วิธีการโหลด, สูตรสำหรับโค้ดฝั่งไคลเอนต์, persistent storage, C structs ใน JS API, ไปจนถึงการสร้าง virtual tables และ table-valued functions
  • ยังรวบรวมกรณีใช้งานจริงอย่าง SQLime, Evolu, SQLiteNext, sqlite-wasm-esm, sqlite-wasm-http รวมถึง โปรเจ็กต์ที่มาก่อน เช่น sql.js, wa-sqlite, absurd-js
  • เชื่อมโยงเอกสารเกี่ยวกับ Browser SQLite, OPFS, IndexedDB และ WASI เพื่อให้เปรียบเทียบทางเลือกในการใช้งาน SQLite บนเว็บได้อย่างรวดเร็ว

ขอบเขตของเอกสาร sqlite3 WASM

  • เป็นเอกสาร WebAssembly·JavaScript API ของโครงการ SQLite และครอบคลุม API ที่ทำให้สามารถใช้ sqlite3 บนเบราว์เซอร์รุ่นใหม่ที่รองรับ WASM ได้
  • ข้อมูลโครงการและช่องทางการสนับสนุน

  • เอกสารการรัน·ติดตั้ง·บิลด์

    • three-step HOWTO: สาธิตวิธีรวมและรัน sqlite3 WASM module พร้อม JavaScript API ที่เกี่ยวข้อง
    • Downloads: ให้บริการจากหน้าดาวน์โหลดหลักของโครงการ
    • Building sqlite3 WASM: ครอบคลุมขั้นตอนการบิลด์ sqlite3 WASM และโค้ด JS ที่เกี่ยวข้อง
      • รายละเอียดการบิลด์ด้วย Emscripten
  • เอกสาร API และรายละเอียดการใช้งาน

    • The API index: อธิบาย รูปแบบ API หลายแบบ รวมถึงวิธีการโหลดและเข้าถึง
    • Cookbook: สูตรสำหรับโค้ดระดับไคลเอนต์
    • Persistent storage options: ตัวเลือกสำหรับ persistent storage
    • C-structs: วิธีใช้งาน C structs ใน JS API
    • virtual tables: วิธีสร้าง virtual tables และ table-valued functions ใน JS
    • API changes: การเปลี่ยนแปลง API ที่อาจส่งผลต่อไคลเอนต์
    • module symbols app: สร้างรายการ sqlite3 API symbols จาก JavaScript/WASM module
  • เอกสารและการดูแลรีโพซิทอรี

กรณีใช้งานและระบบนิเวศที่เกี่ยวข้อง

  • โปรเจ็กต์ของบุคคลที่สามที่ใช้โครงการนี้

    • SQLime: มีอินเทอร์เฟซสำหรับเรียกดูฐานข้อมูล
    • Evolu: แพลตฟอร์ม local-first ที่เน้นความเป็นส่วนตัว ใช้งานง่าย และไม่ผูกติดกับผู้ขายรายใด
    • SQLiteNext: เดโมการผสานโครงการนี้เข้ากับ next.js
    • sqlite-wasm-esm: สาธิตวิธีใช้โครงการนี้ใน Vite toolchain
    • sqlite-wasm-http: SQLite VFS ที่ให้การเข้าถึงแบบอ่านอย่างเดียวกับฐานข้อมูลที่ให้บริการผ่าน HTTP โดยตรง
  • งานก่อนหน้าและโปรเจ็กต์ใกล้เคียง

    • sql.js ของ Alon Zakai: เป็นที่รู้จักว่าเป็นกรณีแรก ๆ ของการใช้ sqlite3 โดยตรงในเบราว์เซอร์ หากไม่นับ WebSQL และสืบย้อนไปได้ถึง commit ปี 2012
    • wa-sqlite ของ Roy Hashimoto: เป็นที่รู้จักว่าเป็นการใช้งาน OPFS storage ครั้งแรกสำหรับฐานข้อมูล sqlite3 และยังรวมงานที่เกี่ยวกับ SQLite VFS ฝั่ง JS
    • absurd-js ของ James Long: สาธิตแนวทางเก็บฐานข้อมูล sqlite3 ไว้ภายในฐานข้อมูล IndexedDB
    • postgres-wasm: รัน Postgres database server ในเบราว์เซอร์
    • Jaccwabyt: ไลบรารี JS ขนาดเล็กสำหรับจัดการ C structs ที่โฮสต์อยู่บน WASM จากโค้ด JS และถูกสร้างขึ้นเพื่อช่วยรองรับการใช้งาน OPFS sqlite3_vfs ของโครงการนี้
    • CoWasm: “Collaborative WebAssembly for Servers and Browsers” และมี WASM build ของแอปพลิเคชัน sqlite3 shell อยู่ใน demo app
    • absurder-js: โปรเจ็กต์ที่ Nicholas G. Piesco นำ absurd-js มาคิดต่อใหม่ และมี การนำเสนอใน SQLite forum ด้วย
    • sqlite-wasm-rs: ให้ Rust SQLite bindings สำหรับการบิลด์ wasm32-unknown-unknown
  • เอกสารและบทความภายนอก

    • Porting WebSQL to OPFS: บทความเกี่ยวกับ SQLite WASM จากทีม Google Chrome dev
    • building SQLite3 for WASI: บทความการบิลด์ SQLite3 สำหรับ WASI จากทีม VMWare OCTO

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

 
GN⁺ 2024-10-16
ความคิดเห็นบน Hacker News
  • น่าจะน่าสนใจถ้ารัน SQLite แบบ in-memory ในเบราว์เซอร์ แล้วสตรีมสำเนา WAL log ไปยังเซิร์ฟเวอร์ คล้ายกับวิธีที่ Litestream และ Cloudflare Durable Objects ใช้
    จะใช้ WebSocket ก็ได้ หรือใช้ fetch() POST แบบเป็นครั้งคราวก็น่าจะทำได้ จากนั้นในการเข้าชมครั้งถัดไป ก็ใช้ข้อมูลฝั่งเซิร์ฟเวอร์เพื่อเติมข้อมูลกลับเข้าไปใน SQLite ฝั่งไคลเอนต์
    อย่างไรก็ตาม เมื่อดู โพสต์ในฟอรัม SQLite แล้ว ดูเหมือนว่า build SQLite WASM พื้นฐานจะไม่มีโหมด WAL รวมอยู่ จึงน่าจะต้องใช้ custom build

    • ในเรื่องนี้มีหลายระดับที่ “มันไม่ได้ทำงานแบบนั้น”
      SQLite แบบ in-memory ไม่ได้ใช้ WAL และ Wasm บนเบราว์เซอร์ก็ไม่รองรับสิ่งอย่าง shared memory API ที่โหมด WAL ของ SQLite คาดหวัง
      Litestream ต้องการการตั้งค่า WAL ที่แม่นยำมาก และในคอนฟิกพื้นฐานของ native SQLite มันบังเอิญเข้ากันได้ดี แต่การทำซ้ำใน Wasm นั้นยาก
      Cloudflare Durable Objects อาจได้รับแรงบันดาลใจจาก Litestream แต่การทำงานจริงค่อนข้างต่างกันมาก และ LiteFS หรือ Turso ก็เช่นกัน
      แนวคิดใหญ่เรื่องการสตรีมส่วนเปลี่ยนแปลงของ SQLite นั้นทำได้ แต่มีงานเยอะ และทำให้การใช้งานยุ่งยากเพราะ concurrency model ของ Wasm บนเบราว์เซอร์
      ผมเคยเขียนโพสต์ในฟอรัมนั้นมาก่อน และทำให้ WAL ทำงานได้ใน build ของ Wasm SQLite ฝั่งเซิร์ฟเวอร์ แต่ไม่ใช่ตัวเลือกที่ใช้งานได้ดีหรือเป็นไปได้ในเบราว์เซอร์
    • เมื่อเดือนสิงหาคม 2022 ผมเคยทำ proof of concept คล้าย ๆ แบบนี้และส่ง Twitter DM ไป แต่ไม่ได้รับคำตอบ handle คือ justjs14
      ตอนนั้นต้องไปค้นโค้ดอีกที แต่ผมคอมไพล์ SQLite ที่มี VFS เป็น Wasm ในเบราว์เซอร์ เปิด DB แก้ไข แล้วให้ push/pull WAL ไปยังเซิร์ฟเวอร์ได้ นอกจากนี้ยังซิงก์ระหว่างเบราว์เซอร์ได้ไม่ว่าจะทำเองแบบ manual หรือผ่าน WebRTC และถ้าให้ GitHub token กับไคลเอนต์ในเบราว์เซอร์ ก็ทำงานบน GitHub Pages ได้ด้วย
      ถ้าสนใจ ผมสามารถทำใหม่ให้รันได้ตั้งแต่ต้นอีกครั้งได้ ตอนนั้นผมทดลองแนวทางนี้ไว้เยอะ และมองว่าอย่างน้อยก็น่าจะมีประโยชน์กับบางแอปพลิเคชัน
      มีเดโมที่มีเฉพาะฟังก์ชัน pull อยู่ที่นี่ด้วย: https://just.billywhizz.io/sqlite/demo/#https://just.billywhizz.io/sqlite/demo/db/chinook.db
    • ต่างจากความเห็นอื่น ๆ ตรงนี้ ผมมองว่า การสตรีมสำเนา WAL เป็นไปได้ทางเทคนิค เพียงแต่ต้องทำภายใน VFS
      “shared memory” อาจเป็น SharedArrayBuffer ได้ และถ้าเปิดการเชื่อมต่อ DB เพียงครั้งละหนึ่งรายการ buffer ทั่วไปก็ทำได้เช่นกัน เช่น ทำแบบนั้นใน SharedWorker ซึ่งพบได้ทั่วไปอยู่แล้ว
      การ implement คงไม่ง่าย แต่เป็นไปได้แน่นอน จริง ๆ แล้วปัญหาที่ใหญ่กว่าคือมันจับการเปลี่ยนแปลงใน ระดับบล็อก ไม่ใช่ระดับแถว
      ดังนั้นจึงใช้ได้กับการ replicate DB ทั้งก้อน แต่การซิงก์บางส่วนในลักษณะแชร์บางแถวกับผู้ใช้คนอื่นนั้นทำได้ยาก
      ถ้าต้องการการเปลี่ยนแปลงระดับแถวสำหรับการซิงก์บางส่วน ก็ต้องใช้ trigger หรือส่วนขยาย SQLite session: https://sqlite.org/sessionintro.html
      ใน PowerSync เราใช้ trigger ฝั่งไคลเอนต์ และนอกจากงานบำรุงรักษา trigger แล้ว ก็ยังไม่พบข้อเสียใหญ่ ๆ
    • หมายถึงอะไรทำนอง https://electric-sql.com/ หรือเปล่า?
    • ผมยังไม่ได้เข้าใจแนวคิด “hydration” นี้ทั้งหมด แต่ช่วงหลังเริ่มสนใจการใช้ Wasm เพื่อรัน logic ฝั่ง backend บางส่วนในเบราว์เซอร์
      ตัวอย่างเช่น ถ้ารันการ render template ทั่วไปหรือ endpoint ของ Htmx บางส่วนด้วย Wasm แม้แต่เว็บเฟรมเวิร์กฝั่งเซิร์ฟเวอร์ทั่วไปก็สามารถให้ความสามารถแบบ offline ได้ด้วยที่เก็บข้อมูล SQLite Wasm คล้ายกับที่ OP พูดถึง
      ตัวอย่าง Django แบบครบชุด: https://github.com/m-butterfield/django_webassembly
      ตัวอย่าง Rust ขั้นต่ำที่แยก client/server ด้วย macro: https://github.com/richardanaya/wasm-service
      Clojure Electric ที่ทำสิ่งคล้ายกันโดยไม่ใช้ Wasm แต่ใช้ macro มากกว่า: https://github.com/hyperfiddle/electric
      ยังมีเครื่องมือเว็บฝั่ง Microsoft ช่วงหลังตัวหนึ่งที่ขึ้นต้นด้วย B ด้วย
      ในช่วงไม่กี่ปีที่ผ่านมา ส่วนต่าง ๆ ของ ecosystem Python จำนวนมากอย่างน่าประหลาดใจได้รับการรองรับ Wasm จนสามารถนำมาใช้กับแนวทางนี้ได้ ไม่ใช่แค่ไลบรารีที่เกี่ยวกับ machine learning อย่างชัดเจนเท่านั้น แต่ยังมีไลบรารีเกมอย่าง Pygame, Pyxel และเมื่อ SDL2 เพิ่มการรองรับแล้ว การรองรับ Kivy ซึ่งเป็นไลบรารี UI แบบ multitouch ก็น่าจะเป็นไปได้ในอีกไม่นาน
      ดูเหมือนว่าจะมีความเป็นไปได้ใหม่ ๆ มากมายในการรันโค้ดบนคอมพิวเตอร์ใดก็ได้ และถ้าจำเป็นก็ทำใน sandbox ของเว็บเบราว์เซอร์เพื่อเลี่ยงระบบราชการของแพลตฟอร์มหรือค่าธรรมเนียม
  • ในเอกสารระบุว่าคอมโพเนนต์เหล่านี้ออกมาเป็น public beta ครั้งแรกใน 3.40 และมีกำหนดทำให้ API เสถียรใน 3.41 ตามฟีดแบ็กจากชุมชน
    แต่รีลีสล่าสุดของ SQLite คือ 3.46.1 เมื่อ 2024-08-13 ดังนั้น API น่าจะเสถียรแล้ว เพียงแต่เอกสารยังไม่ได้อัปเดต
    ถ้าทีม SQLite ออกแพ็กเกจ npm อย่างเป็นทางการที่รวมเวอร์ชัน WASM ไว้ ก็น่าจะเป็นช่องทางเผยแพร่ที่ดี ภายหลังเห็นจากคำตอบว่ามีอยู่แล้ว
    โดยส่วนตัว SQLite-in-WASM ที่ชอบที่สุดยังเป็นแบบแปลงของ Pyodide อยู่ มันมีมาก่อน implementation ทางการของ SQLite นานมาก และเมื่อใช้ Pyodide ก็จะได้ WASM SQLite ติดมาด้วยในฐานะส่วนหนึ่งของ Python standard library
    ใช้อยู่แบบนั้นที่ https://lite.datasette.io/ และทดสอบได้ที่ https://pyodide.org/en/stable/console.html ด้วย
    ถ้าใช้ sqlite3.connect(':memory:') แล้วรัน select sqlite_version() จะได้ 3.39.0 จากวันที่ 2022-06-25 ดังนั้นดูเหมือน Pyodide ต้องอัปเวอร์ชันแล้ว เวอร์ชันนี้น่าจะสืบทอดมาจาก emscripten: https://github.com/emscripten-core/emscripten/blob/main/tools/ports/sqlite3.py

    • ใช่แล้ว API เสถียรแล้ว ครั้งหน้าที่ได้นั่งหน้าคอมพิวเตอร์จะลองอัปเดตข้อความนั้นดู
      แต่ทีม SQLite คงจะไม่ออกแพ็กเกจ npm อย่างเป็นทางการ เราเผยแพร่เฉพาะ JS ล้วน ๆ และปฏิเสธอย่างหนักแน่นที่จะลงไปในโพรงกระต่ายของการซัพพอร์ตเครื่องมือนอกภาษา ไม่มีสมาชิกโปรเจกต์คนไหนใช้เครื่องมือแบบนั้นเลย
      เราสนับสนุน npm build ที่ “ได้รับการรับรองอย่างเป็นทางการ” ซึ่ง Thomas Steiner ดูแลอยู่ แต่ไม่ได้ตั้งใจพัฒนาโดยเล็ง JS framework ใดเป็นพิเศษ
      ถ้าเรารองรับ framework ใด framework หนึ่งโดยตรง รวมถึง npm ด้วย อาจทำให้ดูเหมือนว่าเรารับรอง framework นั้น และเราเลี่ยง การรับรองโปรเจกต์ third-party อย่างจริงจัง
    • ดูเหมือนทีม SQLite ทำสิ่งนั้นมาสักพักแล้ว แค่นำ @sqlite.org/sqlite-wasm เข้ามาใน JS module ผ่าน jsdelivr แล้วโหลด sqlite3-bundler-friendly.mjs กับ sqlite3.wasm ก็พอ
      จากนั้นก็ใช้ C API ของ SQLite และ API เชิงวัตถุ oo1 ได้ และยังทำงานได้ทั้งในแท็กสคริปต์ type=module ปกติหรือใน Deno
      ตัวอย่าง HTML อยู่ที่นี่: https://github.com/Ciantic/experimenting-sqlite-wasm/blob/main/standalone.html
    • https://github.com/sqlite/sqlite-wasm
      sqlite-wasm โหลดได้เร็วกว่า Pyodide มาก ดังนั้นถ้าไม่ต้องใช้ Python ตัวแรกเป็นตัวเลือกที่ดีกว่า
    • DuckDB WASM ใช้แยกจาก Pyodide ได้ และยังขยาย SQLite ได้ด้วย
      แต่ดูเหมือนจะค่อนข้างจำกัด ไม่มี sqlite_version() เลยเช็กเวอร์ชันยังไม่ได้ และเวอร์ชันใน repository คือ 3.38.1 ซึ่งเก่าพอสมควร
      ตอนนี้ DuckDB web shell โหลด SQLite extension ไม่ได้ เพราะ SQLite extension สำหรับ 1.1.2 ที่เพิ่งออกเมื่อวานยังไม่ได้รีลีส เวอร์ชันก่อนหน้าทำงานได้กับ WASM edition ที่เพิ่งอัปเดตไม่นานนี้
      ยังต่อ spatial extension, GDAL, vector search และอื่น ๆ ได้ด้วย: https://github.com/duckdb/duckdb-wasm/releases/tag/v1.29.0
      การสร้าง “SQL web shell” เองก็ไม่ได้ยากมากนัก แต่เอกสารยังไม่สมบูรณ์พอ
      https://github.com/duckdb/sqlite_scanner/blob/main/src/sqlite/sqlite3.h
    • อ่าน FAQ ในหน้านั้นอาจช่วยได้
  • เวลาใช้กับ Go ผมชอบแพ็กเกจ Wasm SQLite ของ ncruces มาก https://github.com/ncruces/go-sqlite3
    แพ็กเกจ Go ของ cznic ก็ดีมากเช่นกัน แต่ เวอร์ชัน Wasm นี้ทำงานได้ดีแม้ในสภาพแวดล้อมอย่าง OpenBSD

  • WebSQL ควรจะเป็นแค่ SQLite ไปเลย และถ้าเป็นอย่างนั้น ระบบนิเวศของ offline-first และ app storage โดยรวมคงดีกว่านี้มาก
    ตอนนี้ยังมีโอกาสไหม? แทนที่จะ abstract SQLite และกำหนดสเปกมากเกินไป ทำไมไม่กำหนดเวอร์ชันของ SQLite API ที่เบราว์เซอร์ต้องรองรับ แล้วอัปเวอร์ชันเป็นระยะ ๆ?

    • วิธี “อัปเวอร์ชันเป็นระยะ ๆ” ในเบราว์เซอร์มีโอกาสเป็นปัญหาค่อนข้างมาก
      แก่นสำคัญอย่างหนึ่งของเว็บคือ ของเดิมควรจะทำงานต่อไปได้ถ้าเป็นไปได้ และ breaking changes แบบนั้นทำได้ยาก
      ต่อให้สเปกระบุเวอร์ชันไว้หลายเวอร์ชันแล้วให้เว็บเพจเลือก เบราว์เซอร์ก็ต้องแบกรับภาระยุ่งยากในการเก็บ SQLite เวอร์ชันเก่า ๆ ที่อาจไม่ได้รับซัพพอร์ตแล้วต่อไป แต่ละเวอร์ชันยังกินพื้นที่ราว 1MB ด้วย
      ถ้าอย่างนั้นปล่อยให้แต่ละเว็บไซต์รับต้นทุนจากตัวเลือกของตัวเองเหมือนตอนนี้น่าจะดีกว่า
      ถ้ากังวลเรื่องการดาวน์โหลดทรัพยากรร่วมซ้ำ ๆ นั่นเป็นปัญหาที่ CDN อื่น ๆ ยอมรับอยู่แล้ว วิธีแก้เรื่อง shared caching สำหรับ dependency ร่วมจะมีคุณค่ามากกว่าการจำกัดไว้แค่ SQLite มาก
      แนวทางปัจจุบันดูดีกว่าเวอร์ชันที่เบราว์เซอร์จัดมาให้
    • ผมชอบ SQLite แต่ก็ต้องยอมรับว่ามันมี พฤติกรรมแปลกเฉพาะหลายอย่าง เกินกว่าจะใส่ไว้ในทุกเบราว์เซอร์ ดังนั้น API ที่คล้าย SQLite น่าจะดีกว่า
    • ผมกลับมองว่าโชคดีที่ WebSQL ไม่ได้เป็นมาตรฐานแพร่หลาย
      ตอนนี้เมื่อจำเป็น เราดึง SQLite ล่าสุดมาได้ในรูป WASM blob บีบอัดขนาด 410KB ถ้าถูกผูกติดกับเวอร์ชัน SQLite ที่เบราว์เซอร์บังคับไว้ ป่านนี้เราอาจยังใช้เวอร์ชันอายุ 10 ปีอยู่ก็ได้
  • อ่านผ่าน ๆ หน้าเอกสารแล้วยังไม่ค่อยเห็นกรณีใช้งานชัดเจน
    ถ้าพูดให้เจาะจงกว่านั้น สิ่งนี้จะเป็น ตัวแทน IndexedDB ได้ไหม? ข้อมูลคงอยู่ถาวรหรือเปล่า หรือว่าต้องเก็บไฟล์ SQLite เองไว้ใน File System API หรือ IndexedDB/localStorage?

    • ตามหน้าแนะนำ หนึ่งในเป้าหมายของโปรเจกต์นี้คือการรองรับ ที่เก็บข้อมูลถาวรฝั่งไคลเอนต์ ด้วย JS API ที่ใช้งานได้เท่าที่เป็นไปได้
      ปัจจุบันรวมถึงการจัดเก็บผ่าน Origin-Private FileSystem(OPFS) และแบ็กเอนด์ window.localStorage, window.sessionStorage แม้จะมีข้อจำกัดมาก
  • ช่วงหลังสนใจสาย local-first มาก แต่ถ้าเทียบกับการใช้ API ที่เก็บข้อมูลในตัวของเบราว์เซอร์ โดยเฉพาะ IndexedDB การฝัง SQLite ดูค่อนข้างหนัก
    ไลบรารีโอเพนซอร์สหลัก ๆ ก็ดูเหมือนจะใช้ API ในตัวกันเป็นส่วนใหญ่
    อยากเห็นโซลูชันโอเพนซอร์สที่ให้ API คล้าย SQLite และการซิงก์บนที่เก็บข้อมูลเนทีฟของเบราว์เซอร์ มากกว่าจะใส่ไฟล์ปฏิบัติการอีกตัวผ่าน WebAssembly

    • มองได้ว่า SQL ใช้ง่ายกว่า IndexedDB API และเช่น การใช้เงื่อนไข WHERE แทนตัวกรอง if() ก็อาจใช้ หน่วยความจำและ CPU น้อยกว่า
    • คุณอาจสนใจ TinyBase เป็นไลบรารีที่ผมสร้างเอง
  • แม้จะดาวน์โหลดจากหน้าดาวน์โหลดทางการแล้วลบไฟล์ mjs และไฟล์แบบ “bundler-friendly” ทั้งหมดออก การพึ่งพาขั้นต่ำของ SQLite Wasm ก็ยังอยู่ที่ประมาณ 1.3MB
    สำหรับแอปเบราว์เซอร์ดูจะค่อนข้างใหญ่ แต่ทุกวันนี้ Wasm ก็รันในที่อื่นได้ด้วย ดังนั้นในสภาพแวดล้อมแบบนั้นอาจสมเหตุสมผลกว่า

    • ถึงอย่างนั้นก็บีบอัดได้ดี sqlite3.js กับ Wasm รวมกันต้นฉบับ 1.3MB แต่ถ้าย่อ JS และบีบอัดทั้งสองไฟล์ด้วย Brotli จะลดลงเหลือ 410KB
    • ผมมองว่า 1.3MB เป็นขนาดที่สมเหตุสมผลพอสำหรับเว็บแอปสมัยใหม่ โดยเฉพาะหลังผู้ใช้เข้าเว็บครั้งแรกแล้วก็น่าจะถูกแคชไว้
      ถ้าแค่เก็บการตั้งค่าผู้ใช้ แน่นอนว่าไม่จำเป็นต้องดาวน์โหลด SQLite แต่ถ้าเป็นงานที่ได้ประโยชน์จากฐานข้อมูลเต็มรูปแบบ ก็ไม่จำเป็นต้องกังวลกับ 1MB มากจนไปประดิษฐ์ล้อใหม่โดยเปล่าประโยชน์
      ถ้าคอมเมนต์อื่นพูดถูก บนเครือข่ายมันก็ไม่ใช่ 1.3MB ตั้งแต่แรกอยู่แล้ว
    • เป็นปัจจัยที่ควรพิจารณาร่วมกับข้อเท็จจริงที่ว่าเบราว์เซอร์มี IndexedDB ในตัวอยู่แล้ว
      ถึงอย่างนั้น สำหรับแอปเบราว์เซอร์ที่โค้ดแอปพลิเคชันและข้อมูลเดิมก็มีขนาดใหญ่อยู่แล้ว เช่น แอปคล้าย Figma หรือ Photoshop หรือแอปแมชชีนเลิร์นนิง 1.3MB อาจไม่ใช่ภาระเพิ่มเติมมากนัก
      อีกอย่างที่ควรพิจารณาคือการพาร์ส Wasm เร็วกว่า JS ค่อนข้างมาก ตอนนี้ผมหาแหล่งอ้างอิงของข้ออ้างนี้ไม่เจอ แต่เคยมีบทความดี ๆ ที่เกี่ยวข้องอย่างน้อยหนึ่งบทความ
      https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
    • ต้องคำนึงถึงโมเดลแซนด์บ็อกซ์ของ WebAssembly ด้วย ในทางทฤษฎี โปรแกรม ซึ่งในที่นี้คือ SQLite สามารถรันได้ทุกที่ที่เหมาะกับการรัน
      อาจเป็นในเครื่อง, เซิร์ฟเวอร์กลาง หรือ เอดจ์ ใกล้ผู้ใช้ก็ได้
    • ฝั่งเซิร์ฟเวอร์มีความเป็นไปได้สูงว่าจะต้องใช้ Wasm SQLite build แยกต่างหากที่จัดการ concurrency และ file locking ต่างออกไป
      อีกทั้ง WASI ยังห่างไกลจากคำตอบ SQLite amalgamation บิลด์ด้วย WASI ได้ดี แต่ concurrency ยังเป็นปัญหาที่ยังไม่ถูกแก้
      ต้องสร้าง VFS ตั้งแต่ต้นเพื่อทำให้ไดรเวอร์ SQLite บน Wasm อยู่ในสภาพที่ใช้งานได้
      https://github.com/ncruces/go-sqlite3/blob/main/vfs/README.md
  • เคยพยายามทำให้สิ่งนี้ทำงานในระบบนิเวศ Rust อยู่พักหนึ่ง แต่ rusqlite และ sqlx ซึ่งเป็น SQL wrapper ใน blessed.rs ดูเหมือนยังใช้ประโยชน์จากมันไม่ได้
    การห่อเองก็ยุ่งยาก เพราะหาวิธีให้โค้ด emscripten Wasm ทำงานเข้ากันได้ดีกับ wasm32-unknown-unknown ไม่เจอ
    สุดท้ายก็ต้องมี JS wrapper ไม่รูปแบบใดก็รูปแบบหนึ่ง แล้วต้อง implement อินเทอร์เฟซที่ crate เหล่านั้นคาดหวังและ expose จาก JS ถ้าเรื่องนี้แก้ได้ใน Rust ก็คงดีมาก

    • กำลังทำงานที่เกี่ยวข้องอยู่ ถ้าสนใจหรืออยากมีส่วนร่วม เข้ามาที่นี่ได้: https://github.com/rhashimoto/wa-sqlite/discussions/154
      โดยแก่นแล้วต้องนำ SQLite emscripten build เข้ามาใน wasm-bindgen ผ่านเฮดเดอร์ extern C และคอมไพล์ในโหมดมัลติเธรดเพื่อให้เข้าถึง shared array buffer ได้ พร้อมกับ implement VFS ใหม่ด้วย Rust
      จากนั้นก็จะสามารถเข้าถึงแถวของ SQLite ในรูปแบบไบต์ Wasm ดิบ และสร้าง wrapper หรือ integration สไตล์ Rust-SQLite ได้
      ฟีเจอร์อำนวยความสะดวกอย่าง connection pooling อาจยังไม่มีอยู่ดี แต่ใน Wasm มีความเป็นไปได้สูงว่าการใช้ DB ใน โหมด exclusive จะเหมาะกว่า
    • มีตัวที่ทำให้ SQLite build นี้ทำงานร่วมกับ Diesel SQLite ของ Rust ได้ที่นี่: https://github.com/xmtp/diesel-wasm-sqlite
      กำลังเตรียมรีลีส 0.2 ในสัปดาห์นี้และจะขัดเกลาปัญหาบางอย่าง นอกเหนือจากนั้นก็สามารถใช้ Diesel ORM ได้เหมือนเนทีฟ
    • มีข่าวดีเรื่องการทำให้โค้ด emscripten Wasm เข้ากันได้ดีกับ wasm32-unknown-unknown
      มีแผนที่จะทำให้ Emscripten และ Rust ทำงานร่วมกันได้ดีบน Wasm: https://github.com/rustwasm/wasm-bindgen/pull/4014#issuecomment-2356908451
    • ผมก็รอสิ่งนี้มาค่อนข้างนานแล้ว มี PR อยู่สองสามอันที่ค้างมาประมาณ 1 ปี และเคยเห็น proof of concept แล้ว แต่ยังห่างไกลจากสิ่งที่ใช้งานจริงได้
  • ใช้ Wasm build ของ SQLite และรันไทม์ Chicory เพื่อสร้างไลบรารี SQLite ที่รันบน JVM ล้วน ๆ: https://github.com/dylibso/sqlite-zero
    แม้จะใกล้เคียงกับงานทดลองมากกว่าการมุ่งให้พร้อมใช้ในโปรดักชัน แต่ก็น่าจะมีประโยชน์ในการนำเครื่องมือ SQLite แบบไม่มี dependency เข้ามาสู่ ระบบนิเวศ JVM

    • การเข้าถึงระบบไฟล์เป็นแบบไหน? เป็น WASI หรือเปล่า?
  • เป็นคำถามทั่วไปว่า ในสถานการณ์แบบใดที่การส่ง DB ทั้งก้อนแล้วให้เบราว์เซอร์จัดการ query เองจะได้เปรียบกว่า?
    พูดอีกอย่างคือ จะใช้สิ่งนี้เมื่อใดเพื่อปรับปรุงประสบการณ์ผู้ใช้ให้ดีกว่าโมเดล DB ที่โฮสต์บนเซิร์ฟเวอร์แบบดั้งเดิม?

    • ส่วนตัวใช้กับ เว็บไซต์ที่โฮสต์แบบ static อยู่ ดังนั้นฐานข้อมูลที่โฮสต์บนเซิร์ฟเวอร์จึงไม่ใช่ตัวเลือกตั้งแต่แรก
      หากใช้ไดรเวอร์ที่เหมาะสม ก็สามารถสตรีมเฉพาะ chunk ของฐานข้อมูลที่ต้องใช้ แทนการส่งฐานข้อมูลทั้งก้อนได้: https://github.com/mmomtchev/sqlite-wasm-http
      สามารถทำการค้นหาแบบ full-text ของ SQLite ได้โดยไม่ต้องดาวน์โหลดฐานข้อมูล FTS ทั้งหมด ถ้าคำค้นหาสั้นพอ ส่วนใหญ่ก็อาจถูกดึงมา แต่ไม่ใช่ทั้งหมด
    • ตอนเห็นชื่อบทความนี้ สิ่งที่ผุดขึ้นมาในใจทันทีคือวิธีที่ PouchDB กับ CouchDB โต้ตอบกันใน แอปแบบ offline-first
      https://medium.com/offline-camp/couchdb-pouchdb-and-hoodie-as-a-stack-for-progressive-web-apps-a6078a985f18
    • สำหรับการใช้งานแบบออฟไลน์ อาจเหมาะเมื่อจัดการข้อมูลปริมาณมาก
      เป็นไปได้ตั้งแต่ไลบรารีเสียงไปจนถึงซอฟต์แวร์โมเดล 3D สร้างและ persist การเปลี่ยนแปลงไว้ในเครื่อง แล้วซิงก์กับฝั่งเซิร์ฟเวอร์เป็นระยะ ๆ หรือเมื่อกลับมาออนไลน์อีกครั้งก็ได้
    • กำลังทำแดชบอร์ดที่สื่อสารโดยตรงกับหลายบริการอยู่ บนเซิร์ฟเวอร์ของผมมีข้อมูลเพียงเล็กน้อยมากสำหรับการควบคุมการเข้าถึงและการจัดการโทเค็น ส่วนข้อมูลจริงจะไม่เข้ามาที่เซิร์ฟเวอร์ของผม
      แอปแบบนี้เป็นตัวเลือกที่เหมาะกับ DB แบบฝังตัวฝั่งไคลเอนต์