Human Who Codes Newsletter - JSR


Thoughts on JSR

This past month saw the public release of the JavaScript Registry (JSR), a direct competitor to npm. The folks behind JSR are the same folks behind Deno, a direct competitor to Node.js. While it may not be surprising that a Node.js competitor would also create an npm competitor, Deno actually started with a theory that the JavaScript community didn’t need npm or any other package manager. In fact, in Ryan Dahl’s original talk announcing Deno, he explicitly mentioned npm as a regret and believed that HTTP module specifiers were a better solution. Fast forward five years and Ryan changed his tune, at first adopting npm compatibility for Deno and then announcing JSR as an alternative to npm.

My initial reaction to this news was, “oh boy, here we go again.” We’ve been down this road before. GitHub, the current owner of npm, launched its own npm-compatible package registry in 2019. GitHub’s package registry featured deep integration with GitHub repositories, simplifying the process of publishing a package directly from a GitHub repo. Ultimately, the GitHub npm package registry never gained traction and GitHub ended up purchasing npm, Inc. and took over the formal administration of npm.

So how is JSR different?

Instead of taking the GitHub route of full npm compatibility, JSR reimagines what a package registry should be in 2024. JSR wants to be the only package manager you need, and just like Deno, isn’t relying on old paradigms and ways of doing things. If JSR succeeds, it will be because of how different it is from npm as opposed to the GitHub npm package registry, which would only succeed if it worked the same as npm. Some of the key features that make JSR intriguing:

Deep GitHub integration. JSR leans into GitHub’s popularity by using it for both user and package credentials. To get started with JSR, you need a GitHub account, and that account is tied to your JSR account. Further, any package you create must be linked to a GitHub repository – not by placing the GitHub URL in a package.json file, but rather, by linking the package through the JSR website. For CI publishing, your package can only be published directly from the linked GitHub repository, automatically generating the provenance information that npm only recently added. If you want to publish manually, you’ll be prompted to approve the publish on the JSR website.

Cross-runtime compatibility. JSR isn’t just a package manager for Deno, it’s designed to work with Node.js, Bun, and web browsers, as well. That means you don’t need to publish a package to both npm and Deno for your code to be usable on multiple runtimes. A runtime-agnostic jsr package enables publishing and installing JSR packages on any server-side runtime.

TypeScript- and ESM- focused. JSR is built for a world where everyone writes ESM modules and most people write in TypeScript. JSR doesn’t support CommonJS in any way, so there are no confusing processes to ensure compatibility. And because JSR treats TypeScript as a first-class citizen, there’s no need to transpile into JavaScript before publishing. JSR stores the TypeScript and will generate JavaScript on-demand when a package is used in a runtime that doesn’t have built-in TypeScript support. That doesn’t mean you can’t publish JavaScript packages, as well. JSR supports JavaScript packages with .d.ts files for maximum compatibility.

Git awareness. JSR won’t publish anything listed in your .gitignore file unless you override it in your jsr.json file, saving you from needing to create a second file just for JSR. Also, JSR won’t let you manually publish if the Git repository has uncommitted changes. Having fallen into this trap early on in the days of ESLint, this is an extra safety check I really appreciate. (You can override this check with a command line flag if you really want to publish uncommitted changes, which can happen in a CI process if you are generating some of the file at publish time.)

Responsible package name stewardship. One of the complaints about npm is how hands-off they are about package naming. There is a lot of package name squatting on npm and very little recourse should someone squat on a name that you have a right to. Further, because npm package names are case-sensitive, it’s easy for malicious actors to create packages that users might confuse for legitimate ones. JSR solves all of these problems by forcing all package names to be lowercase, explicitly disallowing squatting, and watching over package scopes that might be used by well-known packages. When I first went to register the “@eslint” scope, I was pleasantly surprised to see an error message saying that this scope was reserved and I’d need to contact support to request access.

Given all of that, will JSR succeed in overtaking npm? It’s too early to tell. Just like Deno introduced a lot of objective improvements over Node.js, JSR does the same for npm. However, the internet has a history of entrenched, “good enough” technologies outlasting better newcomers through sheer inertia. npm is a technology we’ve been using for 14 years, so we’re aware of all the sharp edges and performance characteristics. JSR is a couple of months old and yet to be really tested in production. However, it is the first significant competitor to npm in a long time, so I’ll grab some popcorn and watch intently.

Key Takeaways

  • JSR is a new TypeScript-focused competitor to npm created by the folks behind Deno.
  • JSR focuses on safety and security by helping publishers to avoid mistakes and ensuring, through GitHub integration, the origin of published packages.
  • JSR is designed to work with multiple runtimes and ultimately wants to be the package registry of choice for all of your JavaScript and TypeScript that runs in a browser, Node.js, Deno, and Bun.

Stuff I've Enjoyed This Month

📚 Speak Like Churchill, Stand Like Lincoln by James C. Humes
This book explores what made great speakers great. By breaking down famous speeches by leaders such as Abraham Lincoln and Winston Churchill, the author shows how certain techniques make for more impactful speeches and a long-lasting effect on the audience.

🎬 Container Training by Jérôme Petazzoni
A collection of free Docker and Kubernetes training talks and workshops.

📝 On popover accessibility: what the browser does and doesn't do by Hidde de Vries
There's a new HTML attribute called "popover" that has a lot of good accessibility baked in. This article explores exactly how the browser creates popovers in an accessible way.

📝 Using the Service Worker Static Routing API by Rachel Andrew
A new API that just landed in Chrome allows you to specify Service Worker behavior statically, without creating a full service worker. This is helpful for basic functionality, such as caching resources, that otherwise would have required a lot of boilerplate.


What I'm Working On

🏠 Real Estate: End of year bookkeeping is finally complete. The cost of insurance and property taxes increased tremendously in 2023. One of property, my insurance doubled and the property taxes increased by 33%. Unfortunately, that meant I had to raise rents on several properties to cover those costs. Follow my Instagram for real estate photos.

📝Writing: I wrote a couple of new posts:

💻 humanfs: I continued working on humanfs in the past month, focusing on eliminating more errors. In most cases, humanfs will not throw an ENOENT error, making it a lot easier to use than builtin file system APIs on Node.js, Deno, and Bun. Check it out if you haven't already!

💻 ESLint: ESLint v9.0.0-rc.0 has been released! This is the first release candidate for v9.0.0, which means the final release is just around the corner. We are still working on a couple of ecosystem changes to support v9.0.0, and when those are complete, the final release will be done.

Human Who Codes Newsletter

A once-per-month newsletter discussing topics important to senior-level software engineers, with a particular focus on frontend technology and leadership.

Read more from Human Who Codes Newsletter

Thoughts on Weaponizing Open Source When you think of open source software, you might think of it as a gift from someone to the world. They’ve written something of value, and instead of trying to make money off of it, they’ve posted it online for anyone to use (and potentially make money off of) for free. While many projects start that way (Linux, ESLint, etc.), there’s another way open source comes into being: as a weapon against a company’s competition. Android. Perhaps the best example of...

Thoughts on Rates of Change One of the first things I realized about working in codebases is that different parts of the codebase change at different rates. There are some files that are touched very frequently while others can go months, or even years, without being touched. This fascinated me, partly because it reminded me of my closet (why do I even still have those jean shorts?), and partly because people seemed to put such little thought into optimizing their projects to reflect this...

Thoughts on Node.js, Deno, and Bun If you started working in the tech industry after 2005, what’s going on now may seem like a shock. Large tech companies continue to lay people off despite record profits. Smaller tech companies are also laying people off, and in some cases, having “quiet layoffs,” where they find other ways to reduce headcount, including offering employees three months of salary to voluntarily leave the job. As a result, there are more software engineers looking for jobs in...