simonw / til

Today I Learned

Home Page:https://til.simonwillison.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Get JSR @datasette/table to work

simonw opened this issue · comments

As shown in this TIL, I got stuck! https://til.simonwillison.net/javascript/jsr-esbuild

mkdir /tmp/datasette-demo2
cd /tmp/datasette-demo2

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

Error:

✘ [ERROR] Could not resolve "npm:lit@^2.2.7"

    node_modules/@jsr/datasette__table/datasette-table.js:1:36:
      1 │ import {LitElement, html, css} from 'npm:lit@^2.2.7';
        ╵                                     ~~~~~~~~~~~~~~~~

  You can mark the path "npm:lit@^2.2.7" as external to exclude it from the bundle, which will
  remove this error and leave the unresolved path in the bundle.

1 error

I want to run my https://jsr.io/@datasette/table component in a browser, installed via JSR.

Here's what it looks like when it works: https://simonw.github.io/datasette-table/

Code here: https://github.com/simonw/datasette-table/

I wonder if you're needing to manually add dependencies of your dependencies to your project? That seems weird though, but might work

Got some help on JSR Discord, it turns out this may actually be a bug!

Bill Mill figured out a workaround using Deno and a plugin: https://notes.billmill.org/programming/javascript/build_tools/using_esbuild_to_package_a_deno_package_for_the_browser.html

Looks like JSR is adding the npm: protocol/prefix to your lit import automatically when you publish. This is evident when comparing the code on JSR vs what's in your repo.

I assume this is to make your package compatible with Deno, which uses that specifier for Node compatibility: https://docs.deno.com/runtime/manual/node/npm_specifiers

My gut feeling tells me this is a JSR bug/edge case because I don't see this documented anywhere.
The primary use case for JSR is to publish TypeScript source, and then for npm compatibility, JSR will compile that to JavaScript. The TS source will be used by Deno/Bun while the JS dist will be used by Node/browser.

But since you're publishing JavaScript, the "source" and the "dist" is the same file, and so JSR tries to make it compatible with Deno by adding the npm: specifier, but that ironically breaks compatibility with npm.

My gut feeling could be wrong though.

EDIT: Oh wow, while researching and writing this it turns out you reached the same conclusion. 😅