JavaScript Registry (JSR): A Better Alternative to NPM 🤷🏾?
We are going to look at what JSR is and what makes different from NPM and how backward compatible it is with NPM
Over a decade ago, NodeJS was born, and not long after, Node Package Manager (NPM) was born, and the two have become synonymous with each other. Even most Javascript third-party package registries - different from package managers - yarn, bun, etc. - that have come after that, such as GitHub Package Manager, the key differentiating factor has been value proposition (i.e., private repositories) rather than functionality - most offer the same features as NPM.
What’s a Registry?
Before discussing JSR, let’s talk about what a registry is. A registry is a centralized place to find and discover 3rd-party packages. Currently, NPM is the defacto package manager for Javascript and Typescript. With millions of Javascript libraries (packages), both public and private, that you can find and use.
npm is the world's largest software registry. Open source developers from every continent use npm to share and borrow packages, and many organizations use npm to manage private development as well. - NPMJS
Using 3rd party libraries saves a lot of time during development and borrows code from other developers to help solve common problems like developing web apps, where we have a few options such as React, Angular, Vue, etc. Most of these 3rd party libraries also benefit from being open source, with multiple contributors, and being consumed by countless people, which means they are battle-tested and improved quality.
Registries such as NPMJS and UNPKG, among others, help with the discovery and easy management of packages.
What is JSR?
JSR is brought to us by Deno and is a modern package repository for Javascript and Typescript (NodeJS, Bun, Deno, etc.). It is built to be fully backward compatible with NPM. JSR aims to bring in some much-needed standards for package publishing by development.
When I watched the introduction to JSR video by Ryan Dalh (creator of both Node and Deno) at DevWorld earlier this year, the one thing that stuck with me was how he described JSR. JSR is to NPM, as Typescript is to Javascript. You can watch the whole video here; it’s worth every second.
As a package author, there are many things to consider before publishing a package. Do you choose ESModules, or CommonJS, or both? This impacts how the end user consumes your package and can be very frustrating for both the author (most of which are doing it for free) and consumers.
JSR looks to bring some much-needed enforced standardizations like ES Modules only support so that developers ship their code the way they wrote instead of compiling it before pushing it to the repository.
So, what makes JSR Different
There are a few key features that JSR prides itself on:
First-Party Typescript Support
Let’s say you have built a library you want to ship to developers via NPM. You have to transpile it to Javascript and also generate Typescript declaration files (.d.ts
). This means that when you want to go to the definition for an NPM package, instead of landing on the actual code you want, you end up landing inside the Typescript declaration file. While this is useful, sometimes you want to look at the code and see the implementation details.
As you can see from the above video, when we go to the definition for the useReactTable hook, instead of landing on the package code, we end up in the Type declaration files instead.
However, by supporting Typescript out of the box, JSR encourages developers to ship Typescript code directly instead of using Javascript and Type Declaration. This has the added benefit of easy documentation generation and improved performance for your code editor. You can learn more about this here.
ESM Modules only Packages
Another key differentiator compared to NPM is that JSR doesn’t support CommonJS; it only supports ESModules - import
and exports
, not require
syntax.
Javascript has had, for a while now, two competing module standards - ESModules and CommonJS- and I will be writing a comprehensive write-up between the two and others, as well as the journey of how we got here in the future.
Compatibility with NPM
JSR is a superset of npm
Another key feature of JSR is that it is fully backward and compatible with NPM packages; you can consume both NPM and JSR packages. As a package developer, you can reference NPM packages to packages you publish to JSR. This is huge, as it means all NPM packages are available for you and aren’t limited to packages available in JSR.
This reminds me why I think BunJS is special: its compatibility with node. You don’t have to change your NodeJS code to run it with Bun. You can learn more about it in a previous issue here.
Please note: when installing a JSR package in an NPM project, JSR will transpile the Typescript project, before being installed locally (inside the
node_modules
directory).
Documentation Generation
JSR will generate documentation for your packages from your JS Docs automatically when you publish your packages; there is no need to maintain a separate docs site for package maintainers. You can learn more about this here.
All packages are scoped
Another key difference between JSR and NPM is that all packages are scoped; for instance, instead of just typescript, Microsoft would have to decide whether to scope it under Microsoft - @microsoft/typescript
or something else. To prevent abuse, JSR has reserved some common scopes, such as Google, Microsoft, etc., that can be used maliciously if they fall into the wrong hands.
If you like my content and want to support my work, please consider supporting me (you can buy me a double latte, the juice that powers my creativity and determination ☕️) through Github Sponsors.
How to get started with JSR
When I tried my hand at JSR for the first time, I was impressed by how easy it was to get started. It’s easy to start with JSR, and you can adopt it in your project today, just like with other NPM-compatible Javascript package registries.
First, once you find a package you intend to use, select your package manager - npm, pnpm, bun, deno, etc. JSR will give you the command you need to install the package in your environment, as shown below:
If you are on NPM like most developers will be, JSR will add JSR (@jsr:registry=https://npm.jsr.io
) as the registry in the NPM config file (.npmrc
) and then install the package inside the node_modules
just like a normal NPM package.
Finally, you can consume the package just like any other NPM package in your project, and both NPM and JSR packages can be used in the same project, as shown below.
Easy, right?
Conclusion
In this issue, we looked at JSR and what makes JSR different from NPM. We looked at the key differentiators of the Javascript repository and what set it apart compared to other package managers, such as first-class support for Typescript and ES Modules packages.
On top of that, JSR looks to generate documentation for the packages published in the repository, which is fully backward compatible with NPM. You can start using it today.
That's it for this issue. Thank you for getting this far. If you enjoyed this issue and would like to support my work, please share and like this issue and consider sharing All Things Typescript with friends and colleagues.
Did you know you can hire me to coach your team and help them improve their Typescript skills? If so, please get in touch with me to discuss it.
And until next time, please keep on learning.