JSR: Second Look

I blogged my JSR: First Impressions a couple of weeks ago. Since then JSR has officially launched in open beta. My article proved timely and received a lot of attention. JSR has already made changes so I figured a second look was required.

Open Source

The JSR GitHub repository has also gone public. The primary components are a Rust API, PostgreSQL database, and Fresh website.

Everything is hosted on Google’s cloud services. Notably the Fresh front-end is not hosted on Deno Deploy despite it being the flagship project †. Which is a good thing honestly, I’ve found Deno Deploy to be a little too slow and unreliable. Maybe it’s not just me.

Open source and MIT licensed is good to see. I cloned the @jsr-io/jsr GitHub repo and ran deno task prod:frontend. Fresh started on localhost:8000 but auth/login failed. I went back to RTFM (prerequisites). Once I had jsr.test resolving to localhost and visited that URL everything worked. It connects to the production database API. I edited a few pages, Fresh automated updated, good stuff indeed.

There is an open issue about mirroring package sources and data.

† Fresh is built by the Deno team and featured prominently on the Deno Deploy landing page, manual start page, and is the first template on the “New Project” page within Deno Deploy.

Types and NPM

The issues I had with types for Node & Bun are reportedly fixed.

JSR has a new Node CLI which is now the recommended way to install JSR packages for Node:

npx jsr add @dbushell/carriageway

I don’t use Node often but this looks more convenient.

Bun is Here!

I raised a question around the curious omission of Bun. Now Bun has been added alongside the other runtimes.

JSR runtime support

I was mulling over a conspiracy theory as to Bun’s whereabouts.

Browser Support

Last time I failed to comment on how browser support on JSR is a binary option. As every web developer knows JavaScript API support in browsers is varied. My @ssr/velocirouter package uses the URLPattern API. Only Deno and Chromium browsers support it natively without a polyfill. I opted to check “Browsers Supported” but I’d like a way to point people to the documentation that is more nuanced.

I have opened an issue to discuss more browser compatibility options.

Package Scores

I’d highly recommend Syntax episode #737 with guest Luca Casonato. They discuss one problem with NPM; older packages are prioritised in search simply due to them accumulating more downloads over time.

JSR wants to solve that and package score may be one factor:

JSR score card example

Check out my @dbushell/carriageway package for example.

Scoring criteria is currently:

  • Has a readme or module doc
  • Has examples in the readme or module doc
  • Has module docs in all entrypoints
  • Has docs for most symbols
  • No slow types are used
  • Has a description
  • At least one runtime is marked as compatible
  • At least two runtimes are marked as compatible

That last bullet point means that any runtime-specific package like my Deno Audio Duration has a maximum score of 94%. I’m OK with that.

Otherwise it’s not difficult to get 100% if you make a token effort towards documentation. You can even cheat this with worthless comments. Scores are colour coded: Red β€” below 60% β€” Orange β€” 60–90% β€” and Green for 90%+. I can imagine this score calculation changing over time. It’s not a perfect methodology but I like the concept.

I would like to see download stats and GitHub stars being surfaced. They are metrics of questionable relevance but together help paint a picture of overall package quality.

@scope Squatting

The Syntax episode also raised the concerns over name squatting. JSR has reserved some names of popular NPM packages. Obvious abuse will be handed over to the “rightful” owner; potentially controversial. However, packages will remain immutable once published, even if scope ownership changes hands. I can’t think of a better solution myself. JSR has the unenviable task of moderation in that respect. Anyway, there’s been no land rush for names.

On that note the @db scope was picked up by the Deno SQLite package. More than worthy. I’m glad I didn’t take it for my own vanity!

Deno Dependency Woes

I published my experimental DinoSsr web framework to JSR a little too soon. It was working fine until the Deno 1.41 update. Now it errors:

error: Uncaught (in promise) TypeError: Importing https://deno.land/x/[email protected]/mod.js blocked.
JSR packages cannot import non-JSR remote modules for security reasons.

This error comes from me attempting to load esbuild dynamically:

const esbuildWasm = 'https://deno.land/x/[email protected]/wasm.js';
const esbuildMod = 'https://deno.land/x/[email protected]/mod.js';
// Use WASM module in Deno Deploy runtime
const esbuild = Deno.env.has('DENO_REGION')
  ? await import(esbuildWasm)
  : await import(esbuildMod);

My code was working until this Deno fix landed. In fairness I was bypassing and “cheating” the JSR static analyzer. I can only blame myself but this does highlight one downside of JSR for Deno packages.

JSR packages can import from jsr: and npm: and even node: built-ins. JSR packages cannot import HTTP modules for “security reasons”. That’s kinda awkward because the Deno ecosystem is built upon HTTP imports. That was a big part of Deno’s philosophy when a registry was deemed unnecessary.

I have a dependency on esbuild. In turn esbuild for Deno has a dependency on denoflate. So I can’t publish to JSR until they do. If they do. They have no obligation to. Imagine the pain if this chain of dependencies was longer than two.

I could try to vendor in these sub-dependencies but I’d rather not bloat my package that way. Do I fork and re-publish these packages under my own scope? A lot of maintenance work. What happens if people search for these packages? That’d be a mess. I don’t want my version to become the de facto package for these projects simply by publishing first. I opened one JSR package request but I can’t expect anything.

JSR is clearly aimed at being “the Deno registry” in everything but name. Ironically though it’s harder to publish Deno packages to JSR because dependencies become a blocker.

Successful Launch?

JSR uptake has been, dare I suggest, slow? β€” if that’s even a fair statement after less than a week into the launch. What would fast look like? As I type this the 1000th package was published. Quantity is obviously not everything, but that’s not many. Let’s see if that pace picks up before judging too harshly. JSR has added some cool features. If it continues to improve I can see uptake climbing.

Sentiment around JSR seems mixed from my perspective. I’ve read a fair bit of skepticism and negativity. The same that lingers around discussions of Deno. It’s not just that Node is “good enough” or the usual anti-JavaScript crowd. Deno just seems to leave a bad taste in the mouths of many.

In my First Impressions article I said:

For Deno and TypeScript coders I think JSR will be the place to publish packages going forward.

That got quoted by a few blogs. Perhaps I should have said “a place” instead of “the place”. Ideally JavaScript packages should be published in registries, in code repos β€” everywhere that makes sense. I’ll remain positive and open towards JSR but I’m not going all-in.

Buy me a coffee! Support me on Ko-fi