dyedgreen / deno-sqlite

Deno SQLite module
https://deno.land/x/sqlite
MIT License
409 stars 36 forks source link

Question: Why not browser compatible #34

Closed timonson closed 4 years ago

timonson commented 4 years ago

Hi @dyedgreen, I am excited to test your great project in the coming days.

While going through your documentation I have become curious about one question in particular. And I gotta say, I don't know very much about databases and wasm yet, so it might be a silly question. But I am wondering what exactly the reason for the incompatibility of deno-sqlite with the browser is.

Considering that deno's APIs are largely browser compatible and that you chose a Virtual File System instead of persistent files, my best guess is that you can't import wasm files as ES modules. Is this the reason?

Thank you very much!

dyedgreen commented 4 years ago

Hi, thanks for the question!

You are right, I don’t think there is anything that prevents this library from being ported to the browser in principle (apart from the open/ safe functionality, as those require a file system.

It would however require some effort to bundle and port the module for use in the browser, and I simply haven’t had the time to do it. The main thing that would need to be done is to package the WASM binary into its own es6 module (I believe that’s what Deno is also doing internally).

This would then allow you to use SQLite directly in the browser.

Are you interested in looking into this, or would need browser compatibility for some project? 😊

timonson commented 4 years ago

Thanks for the quick response!

I think I was just really curious in the first place but I can definitely see me using sqlite in the browser at some point in the future.

I would imagine exporting the created database as a JavaScript typed array from the browser would be a good replacement for saving the database.

I will try to figure out if this would be a good task for me.

Thanks again!

timonson commented 4 years ago

Hi @dyedgreen, I really wanted to do this today but it is more complicated than I thought because browsers don't support top-level await yet. The problem really emerged when I tried to do what you said in terms of implementing the WASM binary into an ES module by converting it to base64 first and then to JavaScript via the new WebAssembly API. The big obstacle is that WebAssembly.compile() returns a promise and it is kinda difficult to deal with promises in ES modules. I found out that deno bundle does exactly that: It uses await WebAssembly.compile() as top-level await because it works in deno (and TS) already.

Now we could theoretically use the dynamic import function import() and wait for the promise at each step. But I think I will prefer to wait until browsers support top-level await. It is already possible to use it in Chrome's DevTools so I guess it won't take much time until it will be available in the browser.

dyedgreen commented 4 years ago

No worries, there is no rush. I think to properly support browsers, we’ll probably have to restructure the the code a little bit, or perhaps wait for Deno’s bundle functionality to become more mature.

I’m really happy you decided to look into it though 😁

dyedgreen commented 4 years ago

@timonson I just thought of a simple thing that should work: generate the bundle with deno bundle mod.ts bundle.js, and then replace the part at the bottom such that:

export default async function() {
  const __exp = await __instantiateAsync("mod");
  return {
    DB: __exp["DB"],
    Empty: __exp["Empty"],
    Status: __exp["Status"],
  };
}

Which should then be usable as:

import sqlite from "bundle.js";

(async () => {
  const { DB, Status, Empty } = await sqlite();
  ...
})();

(caveat: I haven't actually tried this)

dyedgreen commented 4 years ago

Another neat idea: If this works, we could set up a demo-site, where you can write some JS and have it execute against the module (i.e. you could try out all the features, and there could be a play-ground style thing in the examples page, maybe complete with a small example database to run queries agains 🤔)

timonson commented 4 years ago

Hi @dyedgreen, I will come back later to this issue. Just wanted to mention now that I made a demo for deno-sqlite like two weeks ago: https://github.com/timonson/deno-sqlite-example. You can use it if you want.

dyedgreen commented 4 years ago

Closing this now, since the code-base is browser compatible, using deno bundle and working around top level await.

dyedgreen commented 2 years ago

There is now an experimental branch to support easily building a module that works in browsers (persisting the data in indexedDB, and allowing the import and export of databases).

See #168