Skip to main content

JSR vs npm: JavaScript Package Registries in 2026

·PkgPulse Team

JSR vs npm: JavaScript Package Registries in 2026

TL;DR

npm is the world's largest software registry — 3M+ packages, universal compatibility, and the default for every JavaScript runtime. JSR (JavaScript Registry) is Deno's TypeScript-first registry that solves real problems npm has: immutable package versions, auto-generated documentation from TypeScript sources, native ESM, and cross-runtime support (Deno, Node.js, Bun, browsers). JSR is not a replacement for npm — it's complementary. Use npm for the existing ecosystem; consider JSR for new packages that should be TypeScript-first and cross-runtime. In 2026, JSR is gaining real traction with the Deno and Hono ecosystems.

Key Takeaways

  • npm registry: 3.2M+ packages — dwarfs every alternative
  • JSR launched in March 2024 — growing rapidly with 40k+ packages by early 2026
  • JSR packages are immutable — published versions can never be modified or deleted (unlike npm where you can unpublish within 72 hours)
  • JSR auto-generates documentation from TypeScript source — no manual doc comments required
  • JSR uses jsr: imports natively in Deno; maps to npm in Node.js/Bun via a special registry
  • JSR scores packages on a scale — TypeScript support, documentation, cross-runtime compatibility
  • npm provenance attestations (GitHub Actions integration) — npm now has similar trust guarantees for new packages

The Problem With npm in 2026

npm is ubiquitous but has accumulated technical debt:

  • CommonJS by default — many packages still ship CJS, causing ESM interop headaches
  • Mutable package versionsnpm unpublish in the first 72 hours, supply chain attacks
  • Types not guaranteed — many packages lack TypeScript types; require @types/* separately
  • No official documentation hosting — you link to an external docs site or just README
  • Package names are squatted — "is-odd", "left-pad", namespace pollution

JSR was designed specifically to solve these. It's not a reaction to npm — it's a deliberate redesign.


Publishing on npm

Package Setup

npm login

# Create package
mkdir my-package && cd my-package
npm init -y

# Set up TypeScript
npm install -D typescript tsup
{
  "name": "@yourorg/my-package",
  "version": "1.0.0",
  "type": "module",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs",
      "types": "./dist/index.d.ts"
    }
  },
  "files": ["dist"],
  "scripts": {
    "build": "tsup src/index.ts --format esm,cjs --dts",
    "prepublishOnly": "npm run build"
  }
}

Publishing

# Build
npm run build

# Check what will be published
npm pack --dry-run

# Publish to npm registry
npm publish --access public

# Publish a beta
npm publish --tag beta

npm Provenance (Supply Chain Security)

# .github/workflows/publish.yml — npm provenance via GitHub Actions
name: Publish to npm
on:
  push:
    tags: ["v*"]

permissions:
  id-token: write  # Required for provenance
  contents: read

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          registry-url: "https://registry.npmjs.org"

      - run: npm ci
      - run: npm run build

      - name: Publish with provenance
        run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Scoped Packages and Organizations

# Create npm organization (npmjs.com)
# Publish scoped package
npm publish --access public  # Public scoped package (free)
npm publish                  # Private scoped package (requires paid plan)

# Deprecate old versions
npm deprecate my-package@1.x "Upgrade to v2"

# Dist tags
npm publish --tag next       # Pre-release
npm dist-tag add my-package@2.0.0 latest  # Promote to latest

Publishing on JSR

Package Setup

# No npm needed — JSR uses jsr.json or package.json "exports"
mkdir my-jsr-package && cd my-jsr-package
// jsr.json
{
  "name": "@yourscope/my-package",
  "version": "1.0.0",
  "exports": {
    ".": "./src/index.ts"  // JSR accepts TypeScript source directly!
  }
}
// src/index.ts — ship TypeScript source directly
// JSR compiles for each target at download time

/**
 * Formats a number as currency.
 *
 * @example
 * ```typescript
 * formatCurrency(1234.56, "USD"); // "$1,234.56"
 * ```
 */
export function formatCurrency(
  amount: number,
  currency: string,
  locale?: string
): string {
  return new Intl.NumberFormat(locale ?? "en-US", {
    style: "currency",
    currency,
  }).format(amount);
}

/**
 * Validates an email address.
 * @returns `true` if valid, `false` otherwise
 */
export function isValidEmail(email: string): boolean {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

Publishing to JSR

# Install JSR CLI (or use deno)
npm install -g jsr
# Or: npx jsr publish

# Login (uses GitHub OAuth)
jsr whoami

# Publish — JSR reads jsr.json automatically
npx jsr publish

# Dry run to preview
npx jsr publish --dry-run

Auto-Generated Documentation

JSR automatically generates documentation from:

  1. TypeScript type signatures — every exported function, class, interface
  2. JSDoc comments/** ... */ comments become docs
  3. @example blocks — rendered as interactive code examples
  4. Module-level JSDoc — overview documentation
/**
 * A utility library for working with dates.
 *
 * @module
 */

/**
 * Adds days to a date without mutating the original.
 *
 * @param date The starting date
 * @param days Number of days to add (negative to subtract)
 * @returns A new Date instance
 *
 * @example
 * ```typescript
 * const result = addDays(new Date("2026-01-01"), 7);
 * // result is 2026-01-08
 * ```
 */
export function addDays(date: Date, days: number): Date {
  const result = new Date(date);
  result.setDate(result.getDate() + days);
  return result;
}

Result at jsr.io/@yourscope/my-package — fully documented, searchable, with live examples.


Using JSR Packages

In Deno

// deno.json
{
  "imports": {
    "@std/path": "jsr:@std/path@^1.0",
    "@hono/hono": "npm:hono@^4",  // Mix npm and jsr
    "@yourscope/utils": "jsr:@yourscope/utils@^1.0"
  }
}
// Direct import with version pinning
import { formatCurrency } from "jsr:@yourscope/my-package@^1.0";
import { Hono } from "npm:hono";

const app = new Hono();
app.get("/price", (c) => {
  return c.json({ price: formatCurrency(9.99, "USD") });
});

In Node.js / Bun

# JSR packages are available on npm via the @jsr/* namespace
# But prefer using the JSR CLI for proper resolution
npm install jsr
npx jsr add @yourscope/my-package
# → Adds to package.json as "jsr:@yourscope/my-package@^1.0"
# → Creates .npmrc pointing npm to jsr.io
// Node.js usage after `npx jsr add @std/path`
import { join, resolve } from "@std/path";

const fullPath = join("/home/user", "documents", "file.txt");
console.log(resolve(fullPath));

In Browsers

<!-- JSR packages work in browsers via ESM CDN -->
<script type="module">
  import { formatCurrency } from "https://jsr.io/@yourscope/my-package/1.0.0/src/index.ts";
  console.log(formatCurrency(9.99, "USD")); // $9.99
</script>

JSR vs npm Feature Comparison

FeaturenpmJSR
Package count3.2M+40k+ (early 2026)
Package immutability❌ (72hr unpublish)✅ Versions are permanent
TypeScript source❌ (build required)✅ Ship .ts files
Auto-generated docs✅ From types + JSDoc
Publish sizeDistributedSmall (TS source)
ESM-firstOptional✅ Required
Cross-runtimeNode-first✅ Deno/Node/Bun/Browser
Scope requirementOptional✅ Required (@scope/pkg)
Security attestations✅ (Provenance, 2023)✅ Built-in
Slow abuse prevention✅ Score system
Private packages✅ (paid)✅ (free for scopes)
Access control
GitHub Actions integration
PopularityDominantGrowing fast

The Score System

JSR gives each package a score (0–100%) based on:

Documentation       25% — Are all exports documented?
TypeScript          25% — Does it ship TypeScript source?
Description         10% — Is there a package description?
README              10% — Does it have a README?
Runtime compat      30% — Does it work on Deno, Node, Bun, browser?

A score of 100% means the package is:

  • Written in TypeScript (source)
  • All exports have JSDoc
  • Compatible with all major runtimes
  • Has a description and README

This incentivizes quality in ways npm's model doesn't.


Should You Publish on JSR?

Publish on JSR if your package:

  • Is written in TypeScript and targets multiple runtimes
  • Provides utilities that work in Deno, Node.js, Bun, and browsers without modification
  • Benefits from automatic documentation generation
  • Is new and doesn't have npm distribution history to maintain

Keep npm as primary if your package:

  • Depends on Node.js-specific APIs (fs, http, child_process)
  • Has existing npm users and changing the import path would break them
  • Uses CommonJS internally or depends on CJS-only packages
  • Is targeted specifically at Node.js tooling

Publish to both (recommended for new packages):

# Dual publishing is easy — maintain both
jsr.json → publishes TypeScript source to JSR
package.json → publishes compiled output to npm

Ecosystem Adoption in 2026

The JSR ecosystem is growing around Deno's standard library and Hono:

  • @std/ packages* — Deno's standard library now lives on JSR (50+ packages)
  • @hono/hono — Hono is published on both JSR and npm
  • @fresh/* — Deno Fresh framework packages
  • @oak/oak — Oak web framework for Deno

The Deno Company is betting on JSR becoming the standard for cross-runtime TypeScript packages. Whether it challenges npm's dominance remains to be seen — but for new TypeScript-first packages, JSR is worth considering as a primary or dual-publishing target.


Methodology

Data sourced from official npm registry (npmjs.com), JSR registry (jsr.io), GitHub repositories, and official documentation. Package counts as of early 2026. JSR score system documented from official JSR documentation. Publishing workflows verified against current CLI versions: npm 10.x, jsr CLI 0.5.x, Deno 2.1.


Related: Bun vs Deno 2 vs Node 22 for JavaScript runtime comparisons, or pnpm vs npm vs Yarn 2026 for package manager comparisons.

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.