Home

DuckDB In Vanilla JS With Observable's DuckDB Library

If all worked as planned, you'll see a scrolling table at the end of page. Said table was made from a query against four remote parquet files. This time, we're using Observable's helper library.

See the pure vanilla example for more commentary. We're just showcasing the differences.

Swap out DuckDB import for Observable

import { Library } from "https://cdn.jsdelivr.net/npm/@observablehq/stdlib@5.5.1/+esm";

Now, the remaining differences lie in how to instantiate the DuckDB instance and wire up the tables:

Observable differences

const { DuckDBClient } = new Library();

const db = await DuckDBClient().of({
  activity: {
    file: {
      name: "/tag-activity.parquet",
      url: (d) => "https://data.hrbrmstr.dev/tag-activity.parquet"
    }
  },
  tags: {
    file: {
      name: "/tags.parquet",
      url: (d) => "https://data.hrbrmstr.dev/tags.parquet"
    }
  },
  kev: {
    file: {
      name: "/kev.parquet",
      url: (d) => "https://data.hrbrmstr.dev/kev.parquet"
    }
  },
  ips: {
    file: {
      name: "/daily-ips.parquet",
      url: (d) => "https://data.hrbrmstr.dev/daily-ips.parquet"
    }
  }
})
  1. DuckDB is part of the Observable standard Library so we need to get to it.
  2. Note the need for (), here, as it's a class
  3. The Observable wrapper normalizes the DuckDB wrapper to the DatabaseClient standard.

The last differences in in how we execute the query.

Observable so fancy

const tagsAndIps = await db.sql`sql from the vanilla example`
  1. The DatabaseClient spec defines a sql tagged template literal function which just shortens the typing by a few keystrokes (but it does feel cooler when you use it).

The remaining code is the same as the vanilla example.

And, here is the result!

You can view this example standalone, as well.

NOTE: since I'm still learning Nue, you may need to hard refresh this page to see the table, as Nue does fancy rendering tricks that may not trigger the load. The parquet files may take multiple seconds to load, too.

⌛️ Loading…