📍 Article principal : Deno 2 en production 2026
Introduction
Un freelance ivoirien maintient depuis trois ans une bibliothèque d’utilitaires UEMOA — validateurs de numéros de téléphone par pays, formateurs FCFA, codes BCEAO, helpers de validation des pièces d’identité régionales. Cette bibliothèque servait initialement uniquement à ses projets personnels en npm. En 2026, il décide de la republier sur JSR pour bénéficier du typage automatique, de la signature des packages, et de la portée multi-runtime (Deno, Node, Bun simultanément). En une demi-journée, sa bibliothèque @his/uemoa-utils est disponible sur JSR avec documentation auto-générée, types parfaits, et version sécurisée. Ce tutoriel décrit le processus complet de publication sur JSR depuis un projet Deno : configuration du scope, structure du package, automation via GitHub Actions, et comparaison pratique avec npm pour aider à choisir où publier selon le contexte.
Prérequis
- Compte JSR créé via GitHub OAuth (jsr.io)
- Deno 2.0+ installé
- Dépôt GitHub pour le code du package
- Connaissance basique de TypeScript et npm publish
- Niveau : intermédiaire — Temps : 1 heure
Étape 1 — Créer un scope sur JSR
Un scope JSR est l’équivalent de l’organisation npm. Il regroupe tous les packages d’un même éditeur sous un préfixe commun. Pour un freelance, c’est typiquement son pseudo GitHub. Pour une agence, c’est le nom commercial de la structure. La création se fait dans le tableau de bord JSR via le bouton « Create scope » — gratuit et sans formalité particulière, contrairement aux organisations npm qui demandent une vérification.
Une fois le scope créé, on devient le mainteneur principal et on peut inviter d’autres collaborateurs avec différents niveaux de permission (publier, gérer, admin). Les packages publiés dans ce scope adoptent le préfixe @scope/nom, par exemple @itskills/uemoa-utils. Cette convention reproduit celle de npm et facilite la migration ou la coexistence sur les deux registres.
Étape 2 — Structurer un package JSR
Un package JSR minimal contient un fichier jsr.json ou un champ "jsr" dans deno.json qui décrit le package. Trois informations essentielles : le nom du package (avec scope), la version (semver), et les exports (les fichiers ou symboles publics du package). JSR encourage l’usage des subpath exports pour offrir une API riche tout en évitant les imports profonds.
// jsr.json
{
"name": "@itskills/uemoa-utils",
"version": "1.2.0",
"exports": {
".": "./mod.ts",
"./telephone": "./src/telephone.ts",
"./fcfa": "./src/fcfa.ts",
"./pays": "./src/pays.ts"
},
"publish": {
"include": ["src/", "mod.ts", "README.md", "LICENSE"],
"exclude": ["**/*.test.ts", "examples/"]
}
}
Cette configuration permet aux consommateurs d’importer soit le package complet via import { validerTelephone } from 'jsr:@itskills/uemoa-utils', soit un sous-module précis via import { validerTelephone } from 'jsr:@itskills/uemoa-utils/telephone'. La granularité réduit la taille des bundles côté consommateur et clarifie l’organisation logique du package.
Étape 3 — Score de qualité JSR
JSR attribue à chaque package un score de qualité de 0 à 100 basé sur quatre critères. La couverture de documentation : chaque export public doit avoir un commentaire JSDoc descriptif. La présence de types : Deno garantit les types via TypeScript natif, mais on peut perdre le score si l’on utilise any excessivement. La fraîcheur des dépendances : les versions désuètes des dépendances pénalisent le score. Et la qualité de la documentation : un README complet avec exemples d’utilisation augmente significativement le score.
Ce score est public sur la page du package et influence la confiance des consommateurs potentiels. Un score supérieur à 80 indique un package bien maintenu et utilisable en production. Pour les freelances ouest-africains qui veulent positionner leurs libs comme professionnelles, viser un score de 90+ est un objectif raisonnable atteignable avec une heure de polish supplémentaire après la première publication.
Étape 4 — Publier le package
La publication depuis Deno se fait avec une commande unique. Avant la publication, Deno valide la conformité du package : tous les exports déclarés existent, aucun fichier exclu n’est référencé, les types sont valides, le score de qualité est calculé. Si une vérification échoue, l’erreur est affichée et la publication est annulée.
deno publish --dry-run
# Vérifie sans publier
deno publish
# Publie réellement
La première fois, deno publish ouvre une page web pour authentifier l’utilisateur via GitHub OAuth. Cette authentification est valable plusieurs jours, ensuite renouvelable. Pour la CI, on utilise un token JSR généré dans les paramètres du compte, stocké dans GitHub Secrets sous le nom JSR_TOKEN. Le workflow CI peut alors publier sans intervention humaine pour chaque tag de version.
Étape 5 — Publication automatique via GitHub Actions
Le workflow de publication suit un pattern simple : à chaque push d’un tag de la forme v1.2.3, on vérifie que les tests passent, on build si nécessaire, puis on publie. Cette automation garantit que les versions publiées correspondent exactement à un commit Git, sans modification manuelle locale qui pourrait introduire des écarts.
name: Publish to JSR
on:
push:
tags: ['v*']
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v1
with: { deno-version: v2.x }
- run: deno test --allow-net
- run: deno publish
La permission id-token: write permet à JSR de vérifier que la publication vient bien du dépôt GitHub déclaré, sans nécessiter de token explicite. Cette intégration OpenID Connect est plus sécurisée que les tokens stockés en secrets : aucun secret long-vivant à gérer, l’authentification est éphémère et liée au workflow spécifique.
Étape 6 — Compatibilité multi-runtime
Un package publié sur JSR fonctionne nativement sous Deno, Node, et Bun. Les consommateurs choisissent leur syntaxe d’import selon leur runtime. Sous Deno : import { validerTelephone } from 'jsr:@itskills/uemoa-utils'. Sous Node ou Bun, après npx jsr add @itskills/uemoa-utils qui configure les imports : import { validerTelephone } from '@itskills/uemoa-utils'. Cette compatibilité élargit la portée du package sans effort supplémentaire de l’auteur.
Pour les bibliothèques qui doivent rester compatibles avec un grand nombre d’environnements, JSR enrichit le contrat de publication : on déclare les runtimes ciblés (deno, node, bun, browsers, workers) dans jsr.json, et JSR vérifie automatiquement que le code n’utilise pas d’API spécifique à un runtime non déclaré. Cette validation préventive évite les bug reports du type « ne fonctionne pas sur Bun ».
Erreurs fréquentes
| Erreur | Cause | Solution |
|---|---|---|
| « Slow types » warning | TypeScript inférence trop dynamique | Annoter explicitement les types des exports publics |
| Score qualité bas | JSDoc absents | Ajouter commentaires sur chaque export public |
| Publication échoue avec 403 | Scope inexistant ou non possédé | Créer le scope ou demander invitation |
| Version déjà publiée | Tentative de republier une version | Incrémenter la version dans jsr.json |
| Import jsr: non trouvé | Cache Deno périmé | deno cache --reload |
JSR vs npm : quand publier sur lequel
JSR et npm ne sont pas mutuellement exclusifs. Trois scénarios déterminent le bon choix. Pour un nouveau package destiné principalement à Deno et aux runtimes modernes, JSR est le choix par défaut : meilleure expérience développeur, scoring de qualité, support TypeScript de première classe. Pour un package destiné à Node legacy avec compatibilité large, npm reste obligatoire. Pour les packages d’agence ou de freelance qui veulent maximiser la portée et la visibilité, publier sur les deux registres simultanément est l’option pragmatique — l’effort additionnel est minime et l’audience double.
Pour publier sur les deux, on configure deux workflows GitHub Actions distincts : l’un pour JSR (deno publish), l’autre pour npm (npm publish après build). Les deux peuvent se déclencher sur le même tag git. Pour les agences ouest-africaines qui veulent capitaliser leur expertise et la rendre visible auprès de la communauté technique francophone et internationale, cette double présence est aujourd’hui la meilleure stratégie de positionnement open-source.
Adaptation au contexte ouest-africain
Trois bénéfices spécifiques. Premièrement, JSR offre une infrastructure gratuite et sans formalité pour publier des packages techniques, accessible aux freelances et étudiants ouest-africains qui n’ont pas accès aux comptes Pro npm payants. Deuxièmement, le score qualité JSR pousse à produire du code documenté et bien typé, ce qui améliore mécaniquement la qualité technique régionale visible à l’international. Troisièmement, pour les SaaS qui veulent partager des SDK clients (par exemple un SDK officiel d’une fintech ouest-africaine pour intégrer ses API), JSR fournit une distribution moderne avec les standards 2026 — meilleure carte de visite que de demander aux développeurs externes de cloner un repo GitHub manuellement.
Pour un freelance qui débute en open-source, démarrer sur JSR avec un petit package utilitaire (50-200 lignes de code, bien documenté, bien typé) atteint plus facilement un score qualité élevé qu’un gros package npm typique. Cette visibilité initiale construit progressivement la réputation technique, particulièrement utile pour les développeurs ouest-africains qui veulent travailler avec des clients internationaux ou rejoindre des équipes remote globales.
Tutoriels frères
Pour aller plus loin
- 🔝 Pilier : Deno 2 en production 2026
- Articles : Publier sur npm avec Changesets
- Doc : JSR publishing
FAQ
JSR est-il adapté pour les packages privés d’entreprise ?
Pas en 2026. JSR vise les packages open-source. Pour des packages privés, npm Enterprise, GitHub Packages, ou Verdaccio auto-hébergé restent les options.
Combien coûte JSR ?
Gratuit pour les packages publics, sans limite. Le projet est financé par la fondation Deno et opère comme un service communautaire.
Peut-on importer un package JSR depuis du code Node sans configuration ?
Pas directement. Il faut soit installer via npx jsr add qui configure le projet, soit utiliser un loader spécialisé. Pour Deno, l’import jsr: est natif sans configuration.
JSR archive-t-il les anciennes versions ?
Oui, toutes les versions publiées restent accessibles indéfiniment. Le yanking (marquer une version comme déconseillée) est possible mais la version reste téléchargeable, contrairement à npm qui peut supprimer.
Adoption JSR dans l’écosystème
Depuis son lancement officiel en 2024, JSR a connu une adoption rapide sur les nouveaux packages mais reste minoritaire face à npm en volume absolu. Plusieurs projets de référence publient désormais sur JSR en parallèle de npm : Hono, Fresh, oslo, et plusieurs bibliothèques de la fondation Deno. Cette présence des projets phares contribue à légitimer JSR comme registre crédible pour les bibliothèques modernes. Pour les freelances et agences ouest-africaines qui hésitent, le critère décisif est l’audience cible : si le package est destiné prioritairement à la communauté Deno, JSR seul suffit ; si l’audience est mixte ou principalement Node, double publication.
L’adoption progressive de JSR s’accompagne d’une amélioration de la qualité moyenne des packages publiés. Le scoring qualité incite les auteurs à documenter, typer correctement, et maintenir leurs dépendances à jour. Ce signal de qualité différencie JSR de npm où la qualité est très hétérogène et où il faut souvent fouiller plusieurs packages pour trouver une bonne option. Pour les développeurs qui consomment des packages, JSR offre généralement une expérience plus fluide et plus de confiance dans les choix techniques.
Gérer les dépendances dans un package JSR
Un package JSR peut dépendre d’autres packages JSR, npm, ou d’imports URL. Cette flexibilité permet de migrer progressivement sans casser l’existant. Quand on publie un package qui dépend de bibliothèques npm, on déclare ces dépendances dans le package.json standard ; JSR les retourne automatiquement aux consommateurs. Pour une dépendance entre packages JSR, on importe simplement avec le préfixe jsr: et JSR gère la résolution.
Pour les versions, JSR suit semver strictement. Une version ^1.2.0 autorise toute version 1.x.y supérieure ou égale à 1.2.0. Pour les packages publiés très souvent (cas de monorepos avec releases automatiques), la discipline de versionnement devient cruciale pour éviter les surprises côté consommateurs. L’usage de Changesets (couvert dans notre tutoriel dédié) s’applique aussi bien à JSR qu’à npm.
Exemple pratique : un package UEMOA réutilisable
Pour donner un exemple concret, voici la structure d’un package JSR typique pour la communauté ouest-africaine. Le package @his/uemoa-utils exporte trois modules cohérents : la validation et le formatage des numéros de téléphone par pays UEMOA, le formatage des montants en FCFA avec séparateurs de milliers selon les conventions locales, et la liste des codes pays avec leurs métadonnées (préfixe téléphonique, devise, indicatif BCEAO). Chaque module est testé exhaustivement avec Vitest ou le runner Deno test natif, documenté avec des exemples concrets, et exporté via subpath pour permettre des imports granulaires.
Avec une centaine de lignes de code utile et une documentation soignée, ce package atteint un score qualité JSR autour de 90, le rendant immédiatement crédible pour les autres développeurs ouest-africains. Le coût d’installation pour les consommateurs est zéro, et le bénéfice est de ne plus dupliquer ces utilitaires d’un projet à l’autre. Pour le mainteneur, le bénéfice est la visibilité technique gagnée auprès de la communauté francophone et internationale, qui se traduit régulièrement par des opportunités de mission ou de collaboration.