using esbuild to package a deno package for the browser

last updated: Mar 06, 2024

Simon asks for the simplest way to package a deno package from jsr for the browser. Here's what I did:

# create a package
mkdir deno-esbuild && cd deno-esbuild && npm init -y

# install yassify
npx jsr add @kwhinnery/yassify

# install esbuild
npm add --save-dev esbuild

# create a test.js file
cat <<EOF > test.js
import * as mod from "@kwhinnery/yassify";

addEventListener("DOMContentLoaded", (_) => {
  const h1 = document.querySelector("h1");
  h1.innerText = mod.yassify(h1.innerText);
});
EOF

# compile it with esbuild
npx esbuild test.js --bundle > bundle.js

# create an html file
printf '<script src="bundle.js"></script><h1>hi simon</h1>' > index.html

Now, open the HTML file and you should see something like:

part 2: using datasette/table

The simplest way I found to bundle a file using the JSR version of datasette/table is to use deno, and use a URL import instead of a prefixed jsr: import.

mkdir deno-datasette && cd deno-datasette && deno init

Create a test.js file that looks like:

import * as mod from "https://jsr.io/@datasette/table/0.1.0/datasette-table.js";
console.log(mod);

Create a bundle.js file that looks like this:

import * as esbuild from "https://deno.land/x/esbuild@v0.19.11/mod.js";
import { denoPlugins } from "https://deno.land/x/esbuild_deno_loader@0.8.5/mod.ts";

const result = await esbuild.build({
  plugins: [
    ...denoPlugins({
      configPath: await Deno.realPath("deno.json"),
    }),
  ],
  entryPoints: ["./test.js"],
  outfile: "./bundle.js",
  bundle: true,
  format: "esm",
});

console.log(result.outputFiles);

esbuild.stop();

This file uses the esbuild deno loader plugin from github. Now you can build a bundle:

deno run --allow-read --allow-env --allow-run build.js

Then you can create an HTML file that looks like this:

<script src="bundle.js"></script>
<datasette-table
  url="https://global-power-plants.datasettes.com/global-power-plants/global-power-plants.json"
></datasette-table>

And if you run it, you will see a web page showing a datasette table:

a better way

Simon updated his note, the jsr team fixed their bug and now this more simple procedure works:

mkdir /tmp/datasette-demo3
cd /tmp/datasette-demo3
echo '@jsr:registry=https://npm.jsr.io' > .npmrc
npm install @jsr/datasette__table
echo 'import * as mod from "@jsr/datasette__table";' > index.js
npx esbuild index.js --bundle --outfile=bundle.js
echo '<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Datasette News</title>
</head>
<body>
  <datasette-table
  url="https://datasette.io/content/news.json"
></datasette-table>
<script src="bundle.js"></script>
</body>
</html>' > index.html

I tried to figure out how to do this same deal with only deno, but I wasn't successful; I don't know how to get esbuild to recognize the jsr: import of the deno-style file:

import * as mod from "jsr:@datasette/table";
↑ up