---
title: "Deno 2.9 livre un démarrage à froid 1,98x plus rapide, 2,2 à 3,1x moins de RSS en charge, le minimum-release-age npm activé par défaut, la politique de confiance no-downgrade et les tests par snapshot natifs"
description: "Deno 2.9 (Bartek Iwańczuk, publié le 2026-06-25 sur deno.com/blog/v2.9) est la plus grande release Deno du cycle. Le démarrage à froid passe de 34,2 ms à 17,3 ms (1,98x), le pic RSS sur la charge realworld de Deno.serve baisse d'un facteur 2,2 (142 Mo → 64 Mo) et de 3,1x sur les corps de 1 Mio (197 Mo → 63 Mo), et le débit Deno.serve grimpe de 1,27x en realworld (56,8k → 72,4k req/s), 1,11x en plaintext, et 1,18x sur les corps de 1 Mio. Durcissement supply chain : le npm minimum-release-age est activé par défaut avec une fenêtre de 24h (PR #35458), et une nouvelle politique de confiance opt-in no-downgrade (PR #34927) refuse de résoudre toute version dont la preuve de confiance (publication échelonnée, trusted publishing, attestation de provenance) est plus faible que la meilleure preuve sur toute version précédemment publiée du même paquet. Parité du runner de tests : t.assertSnapshot() natif (#35139), Deno.test.each (#34938), --shard pour fan-out CI (#35057), retry et repeats (#35053), sélection change-aware --changed et --related (#35199), et seuils de coverage (#35056). Interop lockfile : deno install seed deno.lock depuis package-lock.json, pnpm-lock.yaml, yarn.lock ou bun.lock (#34296, #35330, #35346, #35350, #35394), pnpm-workspace.yaml auto-migre vers deno.json / package.json (#34993), et les marqueurs de conflit de fusion git dans deno.lock se résolvent automatiquement (#34726). Plus : deno desktop sort de l'expérimental (PR #33441 du 16 juin), sous-commandes deno link / deno unlink / deno list / deno watch, --unsafe-proto stable (#34738), Web Locks API (#31166), Happy Eyeballs v2 (RFC 8305) (#31726), navigator.userAgentData (#34743), la proposition WebCrypto Modern Algorithms (ML-KEM, ML-DSA, SLH-DSA, ChaCha20-Poly1305, famille SHA-3, KMAC, Argon2) (#34447, #34448, #34914, #35223), compat Node 26.3.0 (#34746, #34747), Node-API v10 (#35270), et imports de modules CSS sous --unstable-raw-imports (#35093). Plus de 165 PRs mergent dans ce cycle."
date: 2026-06-26
image: "/images/heroes/2026-06-26--deno-2-9-cold-start-supply-chain-tests.png"
author: lschvn
tags: ["runtimes", "security", "performance"]
tldr:
  - "Deno 2.9 ([deno.com/blog/v2.9](https://deno.com/blog/v2.9), publié le 2026-06-25 par Bartek Iwańczuk) est la plus grande release Deno du cycle. Le démarrage à froid passe de 34,2 ms à 17,3 ms (1,98x), le pic RSS sur Deno.serve baisse de 2,2x en realworld (142 Mo → 64 Mo) et de 3,1x sur les corps de 1 Mio (197 Mo → 63 Mo), et le débit Deno.serve grimpe de 1,27x en realworld (56,8k → 72,4k req/s), 1,11x en plaintext, 1,18x sur les corps de 1 Mio. Le travail de perf couvre le lazy-loading des globaux node: hors du snapshot, le gating du bootstrap Node aux workers Node, un cache de code V8 pour l'ESM chargé en différé, un snapshot minifié (#34450, #35373, #35338, #35183), un chemin de service HTTP/1.1 détenu par Deno (#34446), et des ports en Rust de crypto.subtle (#34966) et console / Deno.inspect (#35087)."
  - "Le durcissement supply chain est l'autre gros morceau. Le npm minimum-release-age est activé par défaut avec une fenêtre de 24h ([PR #35458](https://github.com/denoland/deno/pull/35458)), de sorte qu'une version fraîchement publiée, potentiellement compromise, n'atterrit jamais dans votre arbre de dépendances au moment où elle apparaît. Une nouvelle politique de confiance opt-in no-downgrade ([PR #34927](https://github.com/denoland/deno/pull/34927)) classe chaque version de paquet selon ses preuves de confiance (publication échelonnée, trusted publishing, attestation de provenance) et refuse de résoudre une version dont la preuve est plus faible que la meilleure preuve sur toute version précédemment publiée, la même forme que [l'attaque s1ngularity d'août 2025](https://socket.dev/blog/npm-package-changelog-s1ngularity-nx-attack) que l'[attaque de la chaîne d'approvisionnement npm Axios](/articles/2026-03-31--axios-npm-supply-chain-attack) et l'[attaque npm Red Hat / Shai-Hulud](/articles/2026-06-06--npm-supply-chain-attack-red-hat-mini-shai-hulud) ont toutes deux étendue. La release résout aussi automatiquement les conflits de fusion git dans deno.lock (#34726) et permet à Deno de seeder un deno.lock neuf depuis package-lock.json, pnpm-lock.yaml, yarn.lock ou bun.lock à la première install (#34296, #35330, #35346, #35350, #35394), avec pnpm-workspace.yaml qui auto-migre vers deno.json / package.json (#34993)."
  - "La parité du runner de tests comble le gap de fonctionnalités avec Vitest / Jest. Le contexte de test gagne t.assertSnapshot() natif au format @std/testing/snapshot ([PR #35139](https://github.com/denoland/deno/pull/35139)), Deno.test.each enregistre un test indépendamment filtrable par ligne d'inputs (#34938), --shard fait du fan-out sur une matrice CI (#35057), retry et repeats détectent les tests flaky (#35053), --changed et --related font de la sélection change-aware avec conscience du graphe de dépendances (#35199), et les seuils de coverage sortent en code non-nul quand la couverture lignes / branches / fonctions passe sous la cible (#35056). La sous-commande Deno desktop qui a atterri comme PR le 16 juin ([article](/articles/2026-06-16--deno-desktop-subcommand-wef-cef-browserwindow), [PR #33441](https://github.com/denoland/deno/pull/33441)) sort dans la 2.9 comme première build taguée avec la fonctionnalité, plus les sous-commandes deno link / deno unlink / deno list / deno watch, --unsafe-proto stable (#34738), Web Locks API (#31166), Happy Eyeballs v2 (#31726), navigator.userAgentData (#34743), la proposition WebCrypto Modern Algorithms (ML-KEM, ML-DSA, SLH-DSA, ChaCha20-Poly1305, SHA-3, KMAC, Argon2) (#34447, #34448, #34914, #35223), compat Node 26.3.0 (#34746, #34747), Node-API v10 (#35270), imports de modules CSS sous --unstable-raw-imports (#35093), deno fmt reconstruit sur lax-markup / lax-css / lax-sql, deno compile --bundle et --include-as-is, deno bundle --declaration, deno task avec cache par inputs, deps JSR dans node_modules, preferPackageJson, et node_modules de workspace avec .bin."
faq:
  - question: "Quel est le changement phare de Deno 2.9 ?"
    answer: "Deno 2.9 a trois gros morceaux à peu près équivalents. Le travail de performance ramène le cold start à 17,3 ms (1,98x), baisse le pic RSS sur Deno.serve de 2,2 à 3,1x, et relève le débit Deno.serve de 1,11x à 1,27x selon la charge, le plus gros gain de perf en un cycle depuis Deno 1.x. Le durcissement supply chain active le npm minimum-release-age par défaut avec une fenêtre de 24h et ajoute une politique de confiance opt-in no-downgrade qui refuse de résoudre une version de paquet dont la preuve de confiance est plus faible que la meilleure preuve sur toute version précédemment publiée du même paquet. Le travail sur le runner de tests comble le gap de fonctionnalités avec Vitest / Jest via les snapshots natifs, Deno.test.each, --shard, retry et repeats, --changed et --related, et les seuils de coverage. Plus la [sous-commande deno desktop](/articles/2026-06-16--deno-desktop-subcommand-wef-cef-browserwindow) qui a atterri comme PR le 16 juin sort dans la 2.9 comme première build taguée."
  - question: "D'où viennent les gains 1,98x au cold start et 2-3x en mémoire ?"
    answer: "Le gain au cold start vient de quatre sources primaires ([#34450](https://github.com/denoland/deno/pull/34450), [#35373](https://github.com/denoland/deno/pull/35373), [#35338](https://github.com/denoland/deno/pull/35338), [#35183](https://github.com/denoland/deno/pull/35183)) : le lazy-loading des globaux node: hors du snapshot pour que le snapshot soit plus petit, le gating du bootstrap Node aux workers Node (l'isolate principal ne paye plus le coût du bootstrap pour du code qui ne touche jamais node:), un cache de code V8 pour les modules ESM chargés en différé pour que le deuxième démarrage saute l'étape parse-and-compile, et un snapshot minifié. Sur macOS, les fixups chaînés grignotent du temps pré-main supplémentaire ([#35409](https://github.com/denoland/deno/pull/35409)). Les gains de débit HTTP viennent d'un nouveau chemin de service HTTP/1.1 détenu par Deno qui remplace le chemin basé sur hyper que Deno livrait depuis la 1.x ([#34446](https://github.com/denoland/deno/pull/34446)), et du déplacement de crypto.subtle ([#34966](https://github.com/denoland/deno/pull/34966)) et console / Deno.inspect ([#35087](https://github.com/denoland/deno/pull/35087)) de JavaScript vers Rust. La planéité de la mémoire en charge est le changement le plus lourd en exploitation : un serveur qui grossissait avec la charge tourne désormais autour de 62 Mo quoi qu'il serve, ce qui laisse la même machine exécuter beaucoup plus d'instances Deno.serve concurrentes."
  - question: "Qu'est-ce que le npm minimum-release-age, et pourquoi est-il activé par défaut maintenant ?"
    answer: "Le npm minimum-release-age est un setting propre à Deno qui refuse d'installer toute version de paquet npm plus jeune qu'un âge configuré. Deno a livré le setting en 2.6, et la plupart des équipes qui l'avaient activé configuré une fenêtre de 24h à 72h. Le principe est qu'une grande classe d'attaques de chaîne d'approvisionnement npm se laisse attraper simplement en attendant : une version malveillante est généralement détectée et dépubliée dans le jour ou les deux suivant sa publication, donc une fenêtre de 24h en rejette la plupart à l'install. Dans la 2.9 le setting est activé par défaut avec une fenêtre de 24h ([PR #35458](https://github.com/denoland/deno/pull/35458)). La valeur par défaut se trouve au bas de la chaîne de précédence, donc tout ce que vous fixez explicitement dans `.npmrc` gagne (`min-release-age=72h` étend la fenêtre, `min-release-age=0` désactive). C'est la même défense que [celle que pnpm a livrée en 9.x](https://pnpm.io/npmrc#minimizereleaseage) et que [celle que Bun a livrée en 1.x](https://bun.com/docs/runtime/modules#minimum-release-age). Deno est le troisième grand gestionnaire de paquets à l'activer par défaut."
  - question: "Qu'est-ce que la politique de confiance no-downgrade, et comment fonctionne-t-elle ?"
    answer: "La politique de confiance no-downgrade ([PR #34927](https://github.com/denoland/deno/pull/34927)) est une politique de confiance npm opt-in qui défend contre les attaques par vol de token de mainteneur. Elle classe la manière dont chaque version de paquet a été publiée, dans cet ordre décroissant de force : publication échelonnée (un mainteneur qui approuve avec un challenge 2FA vivant), trusted publishing soutenu par une attestation de provenance, attestation de provenance seule, et enfin publication par token simple. Avec `trust-policy=no-downgrade` dans `.npmrc`, Deno refuse de résoudre une version dont la preuve de confiance est plus faible que la meilleure preuve sur toute version précédemment publiée du même paquet, comparée par date de publication. Si un paquet a systématiquement livré via trusted publishing ou avec provenance et qu'une version ultérieure apparaît soudainement comme une publication par token simple (la signature d'un token de mainteneur compromis, comme dans l'incident s1ngularity d'août 2025), l'install devient une erreur dure au lieu d'un downgrade silencieux. La politique suit [le design de pnpm](https://pnpm.io/npmrc#trustpolicy), et Deno livre deux échappatoires qui mirroir pnpm : `trust-policy-ignore-after` (en minutes) saute la vérification pour les versions anciennes, vraiment d'avant provenance, et `trust-policy-exclude[]=package` exempte des paquets nommés. La politique est désactivée par défaut parce que la provenance et le trusted publishing restent adoptés de façon inégale sur le registry."
  - question: "Que gagne le runner de tests dans la 2.9 ?"
    answer: "Six pièces comblent le gap de fonctionnalités avec Vitest / Jest. Le snapshot testing natif atterrit dans le contexte de test comme `t.assertSnapshot()`, au même format et sérialiseur que `@std/testing/snapshot`, sans import nécessaire ([#35139](https://github.com/denoland/deno/pull/35139)). `Deno.test.each` enregistre un test indépendamment filtrable par ligne d'inputs et supporte l'interpolation de nom style printf (%s, %i/%d, %f, %j, %o, $key) ([#34938](https://github.com/denoland/deno/pull/34938)). `deno test --shard=index/count` répartit les fichiers de tests découverts en groupes équilibrés pour le fan-out CI ([#35057](https://github.com/denoland/deno/pull/35057)). Les options `retry: N` et `repeats: N` rattrapent les tests flaky et les tests sensibles à la stabilité, avec un test qui ne passe qu'après un retry signalé comme flaky dans le résumé, pour que le signal ne se perde pas en silence ([#35053](https://github.com/denoland/deno/pull/35053)). `deno test --changed` et `deno test --related=path` font de la sélection change-aware avec conscience du graphe de dépendances qui traverse les membres du workspace et est suffisamment conservateur pour qu'un changement de config, lockfile, import map ou package.json désactive le filtrage ([#35199](https://github.com/denoland/deno/pull/35199)). Et les seuils de coverage sortent en code non-nul quand la couverture lignes / branches / fonctions passe sous la cible, configurable par métrique dans deno.json ([#35056](https://github.com/denoland/deno/pull/35056))."
  - question: "Comment fonctionne l'interop lockfile ?"
    answer: "Au premier `deno install` dans un projet qui a un package-lock.json, pnpm-lock.yaml, yarn.lock ou bun.lock mais pas de deno.lock, Deno seed un deno.lock neuf directement depuis lui, en reprenant les versions résolues exactes et les hashes d'intégrité ([PRs #34296](https://github.com/denoland/deno/pull/34296), [#35330](https://github.com/denoland/deno/pull/35330), [#35346](https://github.com/denoland/deno/pull/35346), [#35350](https://github.com/denoland/deno/pull/35350), [#35394](https://github.com/denoland/deno/pull/35394)). Il n'y a pas de re-résolution ni de montées de version surprises : les versions sous lesquelles vous tourniez sous npm sont les versions sous lesquelles vous tournerez sous Deno. Pour les workspaces pnpm, le `pnpm-workspace.yaml` séparé est auto-migré dans `package.json` (ou `deno.json`) sans perturber les commentaires ni les champs existants ([#34993](https://github.com/denoland/deno/pull/34993)). Pour un `deno.lock` qui contient déjà des marqueurs de conflit de fusion git depuis un rebase raté, Deno les résout désormais automatiquement, en unissant les sections additives et en prenant la version la plus haute sur les conflits de spécificateur véritables ([#34726](https://github.com/denoland/deno/pull/34726)). Quand un répertoire `node_modules` est utilisé, le nouveau setting opt-in `jsrDepsInNodeModules` y installe les dépendances `jsr:` via le registry de compatibilité npm de JSR, à la manière dont pnpm et npm gèrent déjà les paquets JSR ([#35029](https://github.com/denoland/deno/pull/35029))."
  - question: "À quoi ressemble deno desktop dans la 2.9 ?"
    answer: "La sous-commande deno desktop qui [a mergé comme PR #33441 le 16 juin](/articles/2026-06-16--deno-desktop-subcommand-wef-cef-browserwindow) sort dans Deno 2.9 comme première build taguée. La couverture de la PR du 16 juin est la pièce architecturale (backend WEF, CEF par défaut, alternatives webview / raw, API Deno.BrowserWindow, auto-détection de framework pour Next/Astro/Fresh/Remix/Nuxt/SvelteKit/SolidStart/TanStack Start/Vite SSR, multiplexeur CDP pour des DevTools unifiés sur deux isolates V8, auto-updater avec patches bsdiff, cross-compile). La release 2.9 ajoute les pièces pratiques qui font de la PR quelque chose de livrable : un backend UI par défaut webview (per [#35442](https://github.com/denoland/deno/pull/35442)) pour que les binaires restent petits et démarrent vite, Wayland natif au lieu de XWayland sur les systèmes Wayland ([#35485](https://github.com/denoland/deno/pull/35485)), descriptions d'usage Bluetooth et clés Info.plist macOS desktop ([#35472](https://github.com/denoland/deno/pull/35472), [#35484](https://github.com/denoland/deno/pull/35484)), symboles libc++ bundled masqués pour que le runtime desktop soit dlopen-able sous Linux ([#35424](https://github.com/denoland/deno/pull/35424)), formats de sortie installateurs Linux .deb et .rpm ([#35296](https://github.com/denoland/deno/pull/35296)), format de sortie installateur Windows .msi ([#35378](https://github.com/denoland/deno/pull/35378)), auto-détection du framework Vite ([#35470](https://github.com/denoland/deno/pull/35470)), et --compress pour des bundles auto-extractibles ([#35420](https://github.com/denoland/deno/pull/35420)). Le guide complet vit à [docs.deno.com/runtime/manual/desktop](https://docs.deno.com/runtime/manual/desktop), et `denidian`, une app de prise de notes construite avec deno desktop, est publiée à côté comme exemple de référence."
  - question: "Quelles nouveautés du web platform sortent dans la 2.9 ?"
    answer: "Six ajouts. La Web Locks API sort complète ([#31166](https://github.com/denoland/deno/pull/31166)), vous laissant coordonner l'accès à une ressource nommée à travers des tâches async et des workers via `navigator.locks.request(name, async lock => { /* accès exclusif ici jusqu'à ce que ce callback se résolve */ })`, avec modes shared vs exclusive, ifAvailable, steal, un AbortSignal, et `navigator.locks.query()` pour inspecter les locks tenus et en attente. Happy Eyeballs v2 ([RFC 8305](https://www.rfc-editor.org/rfc/rfc8305)) atterrit dans `Deno.connect` et `Deno.connectTls` ([#31726](https://github.com/denoland/deno/pull/31726)), mettant en course les adresses IPv6 et IPv4 sur les réseaux double-stack pour des connexions plus rapides et plus fiables, activé par défaut avec `autoSelectFamily: false` pour désactiver ou `autoSelectFamilyAttemptDelay` pour régler le décalage (par défaut 250ms). `navigator.userAgentData` sort dans les scopes window et worker ([#34743](https://github.com/denoland/deno/pull/34743)). `RequestInit` accepte le membre `priority` du standard Fetch (`auto`, `high`, `low`) ([#34716](https://github.com/denoland/deno/pull/34716)). `Deno.watchFs` supporte une option `ignore` pour des chemins comme `.git` ou une sortie `build` ([#31582](https://github.com/denoland/deno/pull/31582)). Et `process.kill` sur le process courant ne requiert plus `--allow-run` ([#34382](https://github.com/denoland/deno/pull/34382))."
  - question: "Quel est le travail WebCrypto Modern Algorithms dans la 2.9 ?"
    answer: "Deno 2.9 implémente la [proposition Modern Algorithms in the Web Cryptography API](https://wicg.github.io/webcrypto-modern-algos/) en commençant par les algorithmes post-quantiques du NIST. ML-KEM (FIPS 203) encapsulation de clé : ML-KEM-512, ML-KEM-768, ML-KEM-1024 ([#34447](https://github.com/denoland/deno/pull/34447)). Signatures ML-DSA (FIPS 204) : ML-DSA-44, ML-DSA-65, ML-DSA-87, y compris import/export JWK ([#34448](https://github.com/denoland/deno/pull/34448), [#34914](https://github.com/denoland/deno/pull/34914)). Signatures SLH-DSA (FIPS 205), les douze jeux de paramètres ([#35223](https://github.com/denoland/deno/pull/35223)). ML-KEM ajoute quatre nouvelles méthodes crypto.subtle : encapsulateKey / encapsulateBits et decapsulateKey / decapsulateBits. Au-delà du post-quantique, la 2.9 ajoute le chiffrement AEAD ChaCha20-Poly1305 ([#34417](https://github.com/denoland/deno/pull/34417)), la famille SHA-3 et les XOFs (SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256, cSHAKE, TurboSHAKE, KangarooTwelve), KMAC, et la dérivation de clé Argon2. Une nouvelle méthode synchrone de feature-detection `SubtleCrypto.supports()` ([#34903](https://github.com/denoland/deno/pull/34903)) permet au code utilisateur de tester le support à l'exécution. L'intégralité de l'implémentation crypto.subtle a été portée de JavaScript vers Rust ([#34966](https://github.com/denoland/deno/pull/34966)), grignotant le surcoût par appel sans changement de comportement. C'est la même famille de travaux que celle couverte par [la pièce Node.js 24.18.0 'Krypton' LTS Web Crypto](/articles/2026-06-24--node-js-24-18-krypton-lts-buffer-pool-turboshake) pour Node 24."
  - question: "Quels changements de compatibilité Node.js sortent dans la 2.9 ?"
    answer: "Deno 2.9 avance sa cible de compatibilité Node.js à Node 26. La `process.version` reportée passe à `v26.3.0` ([#34747](https://github.com/denoland/deno/pull/34747)), et la suite de tests node-compat que Deno exécute passe à 26.3.0 ([#34746](https://github.com/denoland/deno/pull/34746)). Les builtins Node nus se résolvent désormais sans configuration : `import fs` et `import path` mappent vers `node:fs` / `node:path` inconditionnellement, sans flag `--unstable-bare-node-builtins` ([#33316](https://github.com/denoland/deno/pull/33316)). Cela corrige aussi un bug où un paquet node_modules pouvait shadow un builtin ; les builtins gagnent désormais toujours, tandis que les imports `deno.json` et les mappings de dépendances `package.json` gardent leur précédence. À noter : `node:test` a gagné `mock.module()` et `mock.timers` ([#35329](https://github.com/denoland/deno/pull/35329), [#33946](https://github.com/denoland/deno/pull/33946)), `t.assert.fileSnapshot()` ([#35478](https://github.com/denoland/deno/pull/35478)), et `TestContext.runOnly()` ([#35158](https://github.com/denoland/deno/pull/35158)), et échoue désormais sur les rejets non gérés, applique les timeouts, et exécute les hooks dans le bon ordre ([#35297](https://github.com/denoland/deno/pull/35297), [#35393](https://github.com/denoland/deno/pull/35393)). Plus d'APIs runtime : `process.resourceUsage()` ([#35468](https://github.com/denoland/deno/pull/35468)) et `worker_threads.isInternalThread` ([#35234](https://github.com/denoland/deno/pull/35234)) sont désormais implémentés, et le contexte `AsyncLocalStorage` est préservé à travers les callbacks `node:net` ([#35237](https://github.com/denoland/deno/pull/35237)). L'implémentation NAPI de Deno reporte désormais la version 10 ([#35270](https://github.com/denoland/deno/pull/35270)), en ligne avec Node 26."
  - question: "Que devraient faire aujourd'hui les utilisateurs de Deno 2.8 et les utilisateurs de Node ?"
    answer: "Les utilisateurs de Deno 2.8 devraient upgrader immédiatement : `deno upgrade` tire la 2.9 sur place, et les gains au cold start et en mémoire sont assez gros pour que toute charge de production en bénéficie. Les défauts supply chain sont aussi strictement meilleurs que le comportement précédent : le minimum-release-age à 24h attrape une classe d'attaques que le défaut précédent n'attrapait pas, et la politique de confiance no-downgrade est opt-in pour les équipes qui veulent se durcir davantage. L'interop lockfile fait qu'un projet Node peut basculer avec un simple `deno install` et obtenir un deno.lock seedé directement depuis le package-lock.json, pnpm-lock.yaml, yarn.lock ou bun.lock existant, puis tourner non modifié via `deno task` et le shim `node` que Deno pose sur PATH quand aucun vrai Node n'est installé. Les équipes qui rencontrent une régression peuvent épingler Deno à une version spécifique avec `deno upgrade --version 2.8.3` ou fixer la version via le gestionnaire de versions standard (par exemple `vfox`, `asdf`, `mise`). Pour les utilisateurs Node, le travail WebCrypto Modern Algorithms est de la même famille que [la pièce Node.js 24.18.0 'Krypton' LTS Web Crypto](/articles/2026-06-24--node-js-24-18-krypton-lts-buffer-pool-turboshake), et la [Node.js 26.4.0 'Current'](/articles/2026-06-25--node-js-26-4-current-vfs-loader-package-maps) ramasse les mêmes ML-DSA / ML-KEM / ChaCha20-Poly1305 / AES-KW sous une forme différente ; les équipes qui évaluent Deno comme alternative à Node ont une raison de plus de l'examiner de plus près sur une charge réelle."
---

[Deno 2.9](https://deno.com/blog/v2.9) est sorti le 2026-06-25, publié par Bartek Iwańczuk avec [les notes de release sur deno.com](https://deno.com/blog/v2.9) et [le listing de l'API GitHub releases pour v2.9.0](https://github.com/denoland/deno/releases/tag/v2.9.0). C'est la plus grande release Deno du cycle et la première build taguée qui inclut la [sous-commande deno desktop](/articles/2026-06-16--deno-desktop-subcommand-wef-cef-browserwindow) (la [PR #33441 du 16 juin](https://github.com/denoland/deno/pull/33441)) ainsi qu'une longue liste de changements supply chain, performance, runner de tests, plateforme web et compatibilité Node.js. Le billet de blog ouvre avec trois nombres qui ancrent la release : le cold start passe de 34,2 ms à 17,3 ms (1,98x), le pic de resident set sur Deno.serve baisse de 2,2x sur la charge realworld et de 3,1x sur les corps de 1 Mio, et le débit Deno.serve grimpe de 1,27x en realworld, 1,11x en plaintext et 1,18x sur les corps de 1 Mio. Derrière ces chiffres se trouvent quatre changements de perf primaires ([#34450](https://github.com/denoland/deno/pull/34450), [#35373](https://github.com/denoland/deno/pull/35373), [#35338](https://github.com/denoland/deno/pull/35338), [#35183](https://github.com/denoland/deno/pull/35183)), plus un nouveau chemin de service HTTP/1.1 détenu par Deno ([#34446](https://github.com/denoland/deno/pull/34446)) et des ports Rust de crypto.subtle ([#34966](https://github.com/denoland/deno/pull/34966)) et console / Deno.inspect ([#35087](https://github.com/denoland/deno/pull/35087)).

La release 2.9 suit [Deno 2.8 du 1er juin](/articles/2026-06-01--deno-2-8-audit-fix-ci-pack-subcommands), qui se concentrait sur les correctifs d'audit, l'outillage CI et la sous-commande `pack`. Le cycle 2.9 prend une autre forme : plus de 165 PRs mergent, les gains de perf sont le plus gros saut en un cycle depuis deux ans, et le travail supply chain comble le retard sur les défauts [minimumReleaseAge de pnpm](https://pnpm.io/npmrc#minimizereleaseage) et [trustPolicy de pnpm](https://pnpm.io/npmrc#trustpolicy).

## Cold start, mémoire et débit

Les nombres en titre viennent du harness de benchmark interne de Deno, qui exécute trois charges Deno.serve à concurrence 100 contre Deno 2.8.0 sur une machine Linux x86_64 dédiée, avec serveur et générateur de charge épinglés sur des cœurs disjoints et médiane oha sur 3 runs. Le cold start est la moyenne de 150 runs hyperfine d'un programme hello-world. L'ensemble complet :

| Charge | Deno 2.8 | Deno 2.9 | Changement |
| --- | --- | --- | --- |
| Cold start (plus bas, mieux) | 34,2 ms | 17,3 ms | 1,98x plus rapide |
| Deno.serve realworld (req/s, plus haut, mieux) | 56,8k | 72,4k | 1,27x |
| Deno.serve plaintext (req/s) | 77,0k | 85,6k | 1,11x |
| Deno.serve corps 1 Mio (req/s) | 1 617 | 1 907 | 1,18x |
| RSS, realworld (plus bas, mieux) | 142 Mo | 64 Mo | 2,2x moins de mémoire |
| RSS, corps 1 Mio | 197 Mo | 63 Mo | 3,1x moins de mémoire |

La chute du cold start est le chiffre le plus frappant pris isolément. Le gain vient de quatre changements primaires. D'abord, le lazy-loading des globaux `node:` hors du snapshot, pour que le snapshot lui-même soit plus petit ([#34450](https://github.com/denoland/deno/pull/34450)). Ensuite, le gating du bootstrap Node aux workers Node, pour que l'isolate principal ne paye plus le coût du bootstrap pour du code qui ne touche jamais `node:` ([#35373](https://github.com/denoland/deno/pull/35373)). Troisièmement, un cache de code V8 pour les modules ESM chargés en différé, pour que le deuxième démarrage saute l'étape parse-and-compile ([#35338](https://github.com/denoland/deno/pull/35338)). Quatrièmement, un snapshot minifié qui compresse l'image disque ([#35183](https://github.com/denoland/deno/pull/35183)). Sur macOS, les fixups chaînés grignotent du temps pré-main supplémentaire ([#35409](https://github.com/denoland/deno/pull/35409)).

Les gains de débit HTTP reposent sur un nouveau chemin de service HTTP/1.1 détenu par Deno qui remplace le chemin basé sur hyper que Deno livrait depuis la 1.x ([#34446](https://github.com/denoland/deno/pull/34446)). Les deux ports Rust sont plus petits mais importants : crypto.subtle ([#34966](https://github.com/denoland/deno/pull/34966)) et console / Deno.inspect ([#35087](https://github.com/denoland/deno/pull/35087)) passent de JavaScript à Rust, grignotant le surcoût par appel sans changement de comportement. Le port WebCrypto est le prérequis pour [le travail WebCrypto Modern Algorithms](#webcrypto-modern-algorithms) qui atterrit dans la même release.

La planéité de la mémoire en charge est le changement le plus lourd en exploitation. En 2.8, la RSS grossissait avec la charge, d'environ 94 Mo en plaintext jusqu'à 197 Mo en streaming de corps de 1 Mio. En 2.9 elle reste essentiellement plate, autour de 62 Mo quoi que le serveur serve. Cela donne 2,2x moins de pic RSS sur la charge realworld et 3,1x moins sur les corps de 1 Mio, donc la même machine peut exécuter beaucoup plus d'instances Deno.serve concurrentes avant de saturer. L'équipe signale cela comme le point fort du cycle.

## Durcissement supply chain

Le deuxième gros morceau est le durcissement supply chain, et c'est la partie de la 2.9 qui se rattache le plus directement à [l'attaque de chaîne d'approvisionnement npm Axios](/articles/2026-03-31--axios-npm-supply-chain-attack) de mars et à [l'attaque npm Red Hat / Shai-Hulud](/articles/2026-06-06--npm-supply-chain-attack-red-hat-mini-shai-hulud) de début juin.

**npm minimum-release-age, activé par défaut.** La [PR #35458](https://github.com/denoland/deno/pull/35458) active le minimum-release-age par défaut avec une fenêtre de 24h. Le setting avait été introduit en Deno 2.6 et était déjà documenté, mais dans la 2.9 il est activé par défaut. Le principe est simple : une grande classe d'attaques de chaîne d'approvisionnement npm se laisse attraper en attendant, parce qu'une version malveillante est généralement détectée et dépubliée dans le jour ou les deux suivant sa publication. Une fenêtre de 24h en rejette la plupart à l'install. La valeur par défaut se trouve au bas de la chaîne de précédence, donc tout ce que vous fixez explicitement dans `.npmrc` gagne : `min-release-age=72h` étend la fenêtre, `min-release-age=0` désactive complètement. C'est la même défense que [celle que pnpm a livrée en 9.x](https://pnpm.io/npmrc#minimizereleaseage) et que [celle que Bun a livrée en 1.x](https://bun.com/docs/runtime/modules#minimum-release-age). Deno est le troisième grand gestionnaire de paquets à l'activer par défaut.

**Politique de confiance no-downgrade, opt-in.** La [PR #34927](https://github.com/denoland/deno/pull/34927) ajoute la politique de confiance qui manquait à Deno. Elle classe la manière dont chaque version de paquet a été publiée, dans cet ordre décroissant de force : publication échelonnée (un mainteneur qui approuve avec un challenge 2FA vivant), trusted publishing soutenu par une attestation de provenance, attestation de provenance seule, et enfin publication par token simple. Avec `trust-policy=no-downgrade` dans `.npmrc`, Deno refuse de résoudre une version dont la preuve de confiance est plus faible que la meilleure preuve sur toute version précédemment publiée du même paquet, comparée par date de publication. Si un paquet a systématiquement livré via trusted publishing ou avec provenance et qu'une version ultérieure apparaît soudainement comme une publication par token simple (la signature d'un token de mainteneur compromis, comme dans l'incident s1ngularity d'août 2025 qui s'est étendu à [l'attaque de la chaîne d'approvisionnement npm Axios](/articles/2026-03-31--axios-npm-supply-chain-attack) et à [l'attaque npm Red Hat / Shai-Hulud](/articles/2026-06-06--npm-supply-chain-attack-red-hat-mini-shai-hulud)), l'install devient une erreur dure au lieu d'un downgrade silencieux. La politique suit [le design de pnpm](https://pnpm.io/npmrc#trustpolicy), et Deno livre deux échappatoires qui mirroir pnpm : `trust-policy-ignore-after` (en minutes) saute la vérification pour les versions anciennes, vraiment d'avant provenance, et `trust-policy-exclude[]=package` exempte des paquets nommés. La politique est désactivée par défaut parce que la provenance et le trusted publishing restent adoptés de façon inégale sur le registry.

**Interop lockfile.** L'histoire supply chain s'étend aux lockfiles. Au premier `deno install` dans un projet qui a un `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` ou `bun.lock` mais pas de `deno.lock`, Deno seed un deno.lock neuf directement depuis lui, en reprenant les versions résolues exactes et les hashes d'intégrité ([#34296](https://github.com/denoland/deno/pull/34296), [#35330](https://github.com/denoland/deno/pull/35330), [#35346](https://github.com/denoland/deno/pull/35346), [#35350](https://github.com/denoland/deno/pull/35350), [#35394](https://github.com/denoland/deno/pull/35394)). Pour les workspaces pnpm, le `pnpm-workspace.yaml` séparé est auto-migré dans `package.json` (ou `deno.json`) sans perturber les commentaires ni les champs existants ([#34993](https://github.com/denoland/deno/pull/34993)). Pour un `deno.lock` qui contient déjà des marqueurs de conflit de fusion git depuis un rebase raté, Deno les résout désormais automatiquement, en unissant les sections additives et en prenant la version la plus haute sur les conflits de spécificateur véritables ([#34726](https://github.com/denoland/deno/pull/34726)). L'ensemble fait que basculer un projet Node vers Deno prend quelques commandes et préserve exactement le graphe de dépendances existant.

## Parité du runner de tests avec Vitest / Jest

Le travail sur le runner de tests comble le gap de fonctionnalités avec Vitest / Jest qui était la raison la plus citée par les équipes qui s'accrochent à un framework de test hébergé par Node même quand elles aiment Deno pour le code de production.

**Snapshot testing natif.** La [PR #35139](https://github.com/denoland/deno/pull/35139) ajoute `t.assertSnapshot()` au contexte de test, au même format et sérialiseur que `@std/testing/snapshot`, sans import nécessaire. Les snapshots sont écrits dans `__snapshots__/test_file.snap` à côté du test ; en cas de mismatch le runner affiche un diff et dit comment le mettre à jour (`deno test --update-snapshots`). Les snapshots à l'emplacement par défaut n'ont pas besoin de permissions read/write (le runner les gère), et les entrées obsolètes sont élaguées automatiquement quand un run complet les met à jour. Le snapshot testing fonctionne aussi via `node:test`, avec `t.assert.fileSnapshot()` ([#35478](https://github.com/denoland/deno/pull/35478)).

**Deno.test.each.** La [PR #34938](https://github.com/denoland/deno/pull/34938) enregistre un test indépendamment filtrable par ligne d'inputs. Les cas array sont spreadés comme arguments positionnels ; les cas object sont passés en argument unique et peuvent être interpolés dans le nom du test avec `$key`. Les templates de nom supportent les tokens style printf (`%s`, `%i`/`%d`, `%f`, `%j`, `%o`), `%#` pour l'index de cas, et `$key.nested` pour l'accès objet imbriqué. `Deno.test.only.each` et `Deno.test.ignore.each` se composent comme on s'y attend.

**`deno test --shard`.** La [PR #35057](https://github.com/denoland/deno/pull/35057) répartit les fichiers de tests découverts en groupes équilibrés pour le fan-out CI. Ça se branche direct dans une matrice GitHub Actions ; l'index est 1-based, le sharding se passe avant `--shuffle`, et un sur-sharding (plus de shards que de fichiers) laisse simplement certains shards vides et sort proprement. Le trade-off que la PR explicite : le shard est sélectionné au runtime, après que le graphe de modules pour la suite complète ait été construit et type-checké, donc chaque machine paye quand même le coût de build de graphe et de type-check pour toute la suite. Déplacer le pré-filtre de shard avant le type-check est un follow-up naturel.

**Retry et repeats.** La [PR #35053](https://github.com/denoland/deno/pull/35053) ajoute les options `retry: N` et `repeats: N`, soit par test soit sur tout le run. Un test qui ne passe qu'après un retry est signalé comme flaky dans le résumé, pour que le signal ne se perde pas en silence. Les options par test ont la précédence sur les flags CLI (y compris un `0` explicite pour qu'un test se désactive).

**Sélection change-aware.** La [PR #35199](https://github.com/denoland/deno/pull/35199) ajoute `deno test --changed` (tests affectés par les changements non commités), `deno test --changed=origin/main` (tests affectés depuis le branchement sur main), et `deno test --related=src/util.ts` (tests qui dépendent d'un fichier spécifique). La sélection a conscience du graphe de dépendances (elle traverse le graphe de modules, à travers les membres du workspace) et est conservatrice : changer la config, le lockfile, l'import map ou le package.json désactive le filtrage et exécute tout.

**Seuils de coverage.** La [PR #35056](https://github.com/denoland/deno/pull/35056) laisse la coverage faire échouer un run quand elle passe sous une cible, soit via `--threshold=90`, soit configurée par métrique dans `deno.json` (`lines`, `branches`, `functions`). Quand l'agrégat est trop bas, la commande sort en code non-nul et indique quelle métrique a raté.

## deno desktop sort en première build taguée

La [sous-commande deno desktop](/articles/2026-06-16--deno-desktop-subcommand-wef-cef-browserwindow) qui [a mergé comme PR #33441 le 16 juin](https://github.com/denoland/deno/pull/33441) sort dans Deno 2.9 comme première build taguée avec la fonctionnalité. L'article du 16 juin couvre la pièce architecturale (backend WEF, CEF par défaut, alternatives webview / raw, API `Deno.BrowserWindow`, auto-détection de framework pour Next.js / Astro / Fresh / Remix / Nuxt / SvelteKit / SolidStart / TanStack Start / Vite SSR, multiplexeur CDP pour des DevTools unifiés sur deux isolates V8, auto-updater avec patches bsdiff, cross-compile). La release 2.9 ajoute les pièces pratiques qui font de la PR quelque chose de livrable :

- **Le backend UI par défaut est webview** ([#35442](https://github.com/denoland/deno/pull/35442)), pour que les binaires restent petits et démarrent vite. `--backend cef` bascule vers le Chromium bundled pour un rendu garanti identique sur toutes les plateformes.
- **Wayland natif** au lieu de XWayland sur les systèmes Wayland ([#35485](https://github.com/denoland/deno/pull/35485)). La PR du 16 juin était X11-only et faisait tourner les sessions Wayland via XWayland ; le cycle 2.9 lève cette limite.
- **Formats de sortie installateurs Linux .deb et .rpm** ([#35296](https://github.com/denoland/deno/pull/35296)), produits depuis n'importe quel hôte sans toolchain de packaging spécifique à la plateforme.
- **Format de sortie installateur Windows .msi** ([#35378](https://github.com/denoland/deno/pull/35378)), idem.
- **Auto-détection du framework Vite** ([#35470](https://github.com/denoland/deno/pull/35470)), en plus de la liste Next / Astro / Fresh / Remix / Nuxt / SvelteKit / SolidStart / TanStack Start.
- **Descriptions d'usage Bluetooth et clés Info.plist macOS desktop** ([#35472](https://github.com/denoland/deno/pull/35472), [#35484](https://github.com/denoland/deno/pull/35484)), pour la préparation à la soumission App Store.
- **Symboles libc++ bundled masqués** ([#35424](https://github.com/denoland/deno/pull/35424)) pour que le runtime desktop soit dlopen-able sous Linux.
- **--compress pour les bundles auto-extractibles** ([#35420](https://github.com/denoland/deno/pull/35420)), qui se déballent au premier lancement et réduisent la taille des artéfacts pour les projets lourds en npm.

Le guide complet vit à [docs.deno.com/runtime/manual/desktop](https://docs.deno.com/runtime/manual/desktop), et `denidian`, une app de prise de notes construite avec deno desktop, est publiée à côté comme exemple de référence.

## WebCrypto Modern Algorithms

Le travail WebCrypto est de la même famille que [la pièce Node.js 24.18.0 'Krypton' LTS Web Crypto](/articles/2026-06-24--node-js-24-18-krypton-lts-buffer-pool-turboshake) et [le travail WebCrypto cSHAKE de Node.js 26.4.0 'Current'](/articles/2026-06-25--node-js-26-4-current-vfs-loader-package-maps) : la [proposition Modern Algorithms in the Web Cryptography API](https://wicg.github.io/webcrypto-modern-algos/) en commençant par les algorithmes post-quantiques du NIST.

- **ML-KEM (FIPS 203)** encapsulation de clé : ML-KEM-512, ML-KEM-768, ML-KEM-1024 ([#34447](https://github.com/denoland/deno/pull/34447)). Ajoute quatre nouvelles méthodes `crypto.subtle` : `encapsulateKey` / `encapsulateBits` et `decapsulateKey` / `decapsulateBits`.
- **ML-DSA (FIPS 204)** signatures : ML-DSA-44, ML-DSA-65, ML-DSA-87, y compris import/export JWK ([#34448](https://github.com/denoland/deno/pull/34448), [#34914](https://github.com/denoland/deno/pull/34914)).
- **SLH-DSA (FIPS 205)** signatures, les douze jeux de paramètres ([#35223](https://github.com/denoland/deno/pull/35223)).
- **ChaCha20-Poly1305** AEAD ([#34417](https://github.com/denoland/deno/pull/34417)).
- **Famille SHA-3 et XOFs** : SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256, cSHAKE, TurboSHAKE, KangarooTwelve.
- **KMAC** et dérivation de clé **Argon2**.

Une nouvelle méthode synchrone `SubtleCrypto.supports()` ([#34903](https://github.com/denoland/deno/pull/34903)) permet au code utilisateur de tester le support à l'exécution : `SubtleCrypto.supports("sign", "ML-DSA-65")` renvoie `true` sur une build 2.9. L'intégralité de l'implémentation `crypto.subtle` a été portée de JavaScript vers Rust ([#34966](https://github.com/denoland/deno/pull/34966)), grignotant le surcoût par appel sans changement de comportement, ce qui est le prérequis pour que le travail post-quantique atterrisse dans la même release.

## La compatibilité Node.js avance à 26

Deno 2.9 avance sa cible de compatibilité Node.js à Node 26. La `process.version` reportée passe à `v26.3.0` ([#34747](https://github.com/denoland/deno/pull/34747)), et la suite de tests node-compat que Deno exécute passe à 26.3.0 ([#34746](https://github.com/denoland/deno/pull/34746)). Les builtins Node nus se résolvent désormais sans configuration : `import fs` et `import path` mappent vers `node:fs` / `node:path` inconditionnellement, sans flag `--unstable-bare-node-builtins` ([#33316](https://github.com/denoland/deno/pull/33316)). Cela corrige aussi un bug où un paquet node_modules pouvait shadow un builtin ; les builtins gagnent désormais toujours, tandis que les imports `deno.json` et les mappings de dépendances `package.json` gardent leur précédence.

Les gains `node:test` sont une pièce importante en eux-mêmes : `mock.module()` et `mock.timers` ([#35329](https://github.com/denoland/deno/pull/35329), [#33946](https://github.com/denoland/deno/pull/33946)), `t.assert.fileSnapshot()` ([#35478](https://github.com/denoland/deno/pull/35478)), et `TestContext.runOnly()` ([#35158](https://github.com/denoland/deno/pull/35158)). Le runner échoue désormais sur les rejets non gérés, applique les timeouts, et exécute les hooks dans le bon ordre ([#35297](https://github.com/denoland/deno/pull/35297), [#35393](https://github.com/denoland/deno/pull/35393)). Plus d'APIs runtime : `process.resourceUsage()` ([#35468](https://github.com/denoland/deno/pull/35468)) et `worker_threads.isInternalThread` ([#35234](https://github.com/denoland/deno/pull/35234)) sont désormais implémentés, et le contexte `AsyncLocalStorage` est préservé à travers les callbacks `node:net` ([#35237](https://github.com/denoland/deno/pull/35237)). L'implémentation NAPI de Deno reporte désormais la version 10 ([#35270](https://github.com/denoland/deno/pull/35270)), en ligne avec Node 26. La persistance Web Storage / KV ([#34618](https://github.com/denoland/deno/pull/34618)) pour les sorties `deno compile` et le setting `preferPackageJson` ([#35392](https://github.com/denoland/deno/pull/35392)) sont le même travail ergonomique driven par la compatibilité, désormais stabilisés.

## Interop lockfile et gestion des dépendances

Le travail lockfile est la partie de la 2.9 la plus directement tournée vers le fait de laisser les projets Node basculer vers Deno. Les cinq PRs de lecture de lockfile ([#34296](https://github.com/denoland/deno/pull/34296), [#35330](https://github.com/denoland/deno/pull/35330), [#35346](https://github.com/denoland/deno/pull/35346), [#35350](https://github.com/denoland/deno/pull/35350), [#35394](https://github.com/denoland/deno/pull/35394)) signifient ensemble qu'exécuter `deno install` dans un projet avec un `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` ou `bun.lock` produit un deno.lock qui préserve les versions résolues exactes et les hashes d'intégrité du lockfile existant. Il n'y a pas de re-résolution ni de montées de version surprises : les versions sous lesquelles vous tourniez sous npm sont les versions sous lesquelles vous tournerez sous Deno. À partir de là `deno install` écrit un répertoire `node_modules` que Deno peut exécuter, et `deno task` exécute les scripts `package.json` que vous avez déjà, donc le reste de l'équipe peut continuer à travailler comme avant.

Pour les workspaces pnpm, le `pnpm-workspace.yaml` séparé est auto-migré dans `package.json` (ou `deno.json`) sans perturber les commentaires ni les champs existants ([#34993](https://github.com/denoland/deno/pull/34993)). Combiné avec le protocole `catalog:` que Deno a adopté en 2.8, les versions centralisées et partagées des dépendances continuent à fonctionner après la migration. Pour les fichiers `deno.lock` qui contiennent déjà des marqueurs de conflit de fusion git depuis un rebase raté, Deno les résout désormais automatiquement, en unissant les sections additives et en prenant la version la plus haute sur les conflits de spécificateur véritables ([#34726](https://github.com/denoland/deno/pull/34726)). Quand un répertoire `node_modules` est utilisé, le nouveau setting opt-in `jsrDepsInNodeModules` y installe les dépendances `jsr:` via le registry de compatibilité npm de JSR ([#35029](https://github.com/denoland/deno/pull/35029)), à la manière dont pnpm et npm gèrent déjà les paquets JSR.

Les nouvelles sous-commandes de gestion de dépendances complètent le tableau. `deno link` et `deno unlink` ([#34359](https://github.com/denoland/deno/pull/34359)) donnent un accès CLI de première classe au tableau `links` dans `deno.json` (le workflow style npm-link pour les paquets JSR locaux). Le champ `links` lui-même est stable dans la 2.9 : il avait été livré sous ce nom en 2.3 et n'avait jamais été gated derrière un flag runtime, donc la 2.9 se contente de laisser tomber le label instable restant ([#34996](https://github.com/denoland/deno/pull/34996)). `deno list` ([#34972](https://github.com/denoland/deno/pull/34972)) affiche les dépendances qu'un projet déclare dans `deno.json` et `package.json` et résout leurs versions, l'équivalent de `npm ls` / `pnpm list`. `deno watch` ([#35301](https://github.com/denoland/deno/pull/35301)) est un alias court, plus découvrable, pour `deno run --watch-hmr main.ts` qui ré-exécute sur les changements de fichiers avec hot module replacement, en redémarrant si le hot replacement échoue.

## deno fmt sur les engines lax

`deno fmt` se reconstruit sur les nouveaux engines de formatage lax, qui ne font jamais que déplacer du whitespace : ils ne réordonnent jamais, ne requotent jamais, ne laissent jamais tomber un token, et passent à travers les entrées malformées au lieu d'erreur. HTML, XML et SVG sont désormais formatés par lax-markup, et ils se formatent par défaut sans flag ([#35174](https://github.com/denoland/deno/pull/35174)). Les formats component (Vue, Svelte, Astro, Vento, Nunjucks, Mustache) sont disponibles sous `--unstable-component`. Un document de 10 Mo qui ne pouvait pas être formaté en 15 minutes prend désormais environ un dixième de seconde. CSS, SCSS et Less sont désormais formatés par lax-css (toujours sous `--unstable-css`), ce qui corrige une longue liste d'erreurs de parse et de bugs de mangling de valeurs ([#35160](https://github.com/denoland/deno/pull/35160)). Notez que la syntaxe indentée `.sass` n'est plus supportée. Le formatage SQL (sous `--unstable-sql`) est désormais alimenté par lax-sql, qui produit une sortie canonique, agnostique au dialecte ([#35161](https://github.com/denoland/deno/pull/35161)).

Deux nouvelles options de configuration pour JavaScript et JSON : `sortNamedImports` et `sortNamedExports` contrôlent comment les spécificateurs nommés sont ordonnés (`caseInsensitive` (le défaut), `caseSensitive`, `maintain` (laisser l'ordre source intact, pratique pour matcher l'ordonnancement de Biome)) ([#33313](https://github.com/denoland/deno/pull/33313)) ; et `json.trailingCommas` contrôle les virgules traînantes en JSON et JSONC (`never`, `always`, `maintain`, `jsonc`) ([#33383](https://github.com/denoland/deno/pull/33383)). `deno fmt` lit désormais les fichiers `.editorconfig` et les utilise pour remplir toute option de formatage que l'utilisateur n'a pas fixée explicitement, avec une précédence CLI flags → deno.json → .editorconfig → défauts intégrés ([#34071](https://github.com/denoland/deno/pull/34071)).

## deno task, deno compile, deno bundle

Le task runner récupère du cache par inputs, du contrôle de concurrence, et plusieurs nouveaux flags. Cache par inputs : déclarez les inputs d'une tâche avec `files` (et les outputs avec `output`), et Deno saute la tâche entièrement quand rien de pertinent n'a changé, restaurant les artéfacts de sortie déclarés directement depuis le cache ([#34509](https://github.com/denoland/deno/pull/34509)). L'empreinte inclut la commande, le contenu des fichiers matchés par `files`, les valeurs des variables `env` listées, les empreintes des dépendances de la tâche, l'OS hôte, l'architecture CPU, et la version Deno. Les arguments et l'env font partie de la clé : `deno task build foo` et `deno task build bar` cachent indépendamment, et changer une valeur env listée invalide le cache. Les dépendances cascadent (une tâche se ré-exécute quand l'une de ses dépendances s'est ré-exécutée, même si ses propres inputs n'ont pas changé). Safe par défaut : si les globs de fichiers ne matchent rien, la tâche est traitée comme non-cacheable et s'exécute toujours, donc une coquille ne peut jamais produire un faux hit de cache. Les scripts npm et les tâches sans `command` ne sont jamais cachés.

Contrôle de concurrence : `--jobs` (court `-j`, alias `--concurrency`) plafonne combien de tâches tournent en même temps dans un run de workspace ; `--jobs 1` force l'exécution séquentielle ; ça override la variable d'environnement `DENO_JOBS` et défaut au nombre de CPUs disponibles ([#35318](https://github.com/denoland/deno/pull/35318)). Autres flags : `--if-present` sort en 0 au lieu d'erreur quand la tâche nommée n'existe pas, à la manière de npm ([#35315](https://github.com/denoland/deno/pull/35315)) ; `--env-file` charge un fichier dotenv dans l'environnement des tâches sans forwarder le flag à chaque commande interne ([#34508](https://github.com/denoland/deno/pull/34508)) ; les groupes d'exclusion dans les wildcards de noms de tâches (`deno task test:*(!e2e|interactive)`) exécutent toutes les tâches `test:*` sauf celles exclues ([#34506](https://github.com/denoland/deno/pull/34506)).

`deno compile` gagne `--include-as-is`, qui embed un fichier ou répertoire dans le filesystem virtuel de l'exécutable sans aucune résolution de module ni transpilation ([#32417](https://github.com/denoland/deno/pull/32417)). Là où `--include` passe les fichiers à travers le graphe de modules, `--include-as-is` est fait pour les assets et bundles pré-construits que vous voulez juste rendre disponibles via les APIs filesystem à l'exécution. Les deux flags se combinent, donc vous pouvez résoudre certains modules et en embedder d'autres verbatim dans la même build. Les binaires compilés gagnent aussi du vrai stockage persistant : un `Deno.openKv()`, `localStorage`, et l'API caches par défaut persistent désormais dans un répertoire par app sous l'emplacement app-data de la plateforme au lieu de retomber sur du stockage en mémoire ([#34618](https://github.com/denoland/deno/pull/34618)). L'identité de stockage est le nouveau flag `--app-name`, qui défaut au nom du fichier de sortie, donc deux binaires construits avec le même `--app-name` partagent un store, et renommer un binaire ne perd plus ses données. Par défaut `deno compile` embed l'intégralité de l'arbre `node_modules` résolu dans le binaire ; le nouveau flag expérimental `--bundle` fait plutôt passer l'entrypoint à travers le bundler de Deno d'abord (tree-shaking et émission d'un seul module), ce qui peut rétrécir dramatiquement les binaires pour les projets lourds en npm (un hello-world lodash est passé de 11,6 Mo à 1,5 Mo dans les propres mesures de Deno). Combinez avec `--minify` pour rétrécir davantage le bundle embed ([#34527](https://github.com/denoland/deno/pull/34527), [#34532](https://github.com/denoland/deno/pull/34532), [#34536](https://github.com/denoland/deno/pull/34536)). `deno compile` récupère aussi un mode `--watch` ([#34860](https://github.com/denoland/deno/pull/34860)). `deno bundle` peut désormais émettre un `.d.ts` roulé-up aux côtés du JavaScript bundle avec `--declaration` ([#33838](https://github.com/denoland/deno/pull/33838)), et comprend la forme object du champ `browser` de `package.json` npm quand on bundle avec `--platform browser` ([#34407](https://github.com/denoland/deno/pull/34407)).

## Plateforme web et additions runtime

Six ajouts à la surface plateforme web sortent dans la 2.9. La [Web Locks API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API) sort complète ([#31166](https://github.com/denoland/deno/pull/31166)), vous laissant coordonner l'accès à une ressource nommée à travers des tâches async et des workers via `navigator.locks.request("config", async lock => { /* accès exclusif ici jusqu'à ce que ce callback se résolve */ })`, avec modes shared vs exclusive, `ifAvailable`, `steal`, un `AbortSignal`, et `navigator.locks.query()` pour inspecter les locks tenus et en attente. Happy Eyeballs v2 ([RFC 8305](https://www.rfc-editor.org/rfc/rfc8305)) atterrit dans `Deno.connect` et `Deno.connectTls` ([#31726](https://github.com/denoland/deno/pull/31726)), mettant en course les adresses IPv6 et IPv4 sur les réseaux double-stack pour des connexions plus rapides et plus fiables, activé par défaut avec `autoSelectFamily: false` pour désactiver. `navigator.userAgentData` sort dans les scopes window et worker ([#34743](https://github.com/denoland/deno/pull/34743)). `RequestInit` accepte le membre `priority` du standard Fetch (`auto`, `high`, `low`) ([#34716](https://github.com/denoland/deno/pull/34716)). `Deno.watchFs` supporte une option `ignore` pour des chemins comme `.git` ou une sortie `build` ([#31582](https://github.com/denoland/deno/pull/31582)). `process.kill` sur le process courant ne requiert plus `--allow-run` ([#34382](https://github.com/denoland/deno/pull/34382)).

Les imports de modules CSS sortent sous `--unstable-raw-imports` ([#35093](https://github.com/denoland/deno/pull/35093)), à la manière du standard web CSS module scripts : `import sheet from "./styles.css" with { type: "css" };` renvoie une instance `CSSStyleSheet`, donc le même code tourne sous Deno et dans le navigateur sans étape de bundling. Le `--unsafe-proto` stable ([#34738](https://github.com/denoland/deno/pull/34738), [#35192](https://github.com/denoland/deno/pull/35192)) remplace le flag instable, et quand un programme crashe après avoir touché l'accesseur désactivé `Object.prototype.__proto__`, Deno suggère de le relancer avec. Le fix WebAssembly ESM integration ([#34912](https://github.com/denoland/deno/pull/34912)) déballe les exports globaux des modules `.wasm` importés, à la manière de la spec WebAssembly/ESM et Node. `Deno.serve` ne compresse plus les corps de réponse automatiquement ([#35253](https://github.com/denoland/deno/pull/35253), [#35486](https://github.com/denoland/deno/pull/35486)) ; activez-le par serveur avec `automaticCompression: true`, ou au niveau process avec `DENO_SERVE_AUTOMATIC_COMPRESSION=1`. OpenTelemetry gagne `OTEL_TRACES_SAMPLER` (avec `OTEL_TRACES_SAMPLER_ARG`) pour du head-based sampling, `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT` et `OTEL_SPAN_EVENT_COUNT_LIMIT` pour des plafonds par span, et l'auto-instrumentation qui trace désormais aussi les clients et serveurs `node:http2` ([#34764](https://github.com/denoland/deno/pull/34764), [#34787](https://github.com/denoland/deno/pull/34787), [#34795](https://github.com/denoland/deno/pull/34795), [#34510](https://github.com/denoland/deno/pull/34510)).

## Ce que cette release fait à la trajectoire de Deno

Le cycle 2.9 est la première fois que Deno livre trois catégories phare à peu près équivalentes dans une seule build taguée : un gros saut de perf (cold start, mémoire, débit), un gros durcissement supply chain (minimum-release-age activé par défaut, politique de confiance no-downgrade opt-in), et une grosse livraison de fonctionnalités pour le runner de tests (snapshot testing, tests paramétrés, sharding, retries, sélection change-aware, seuils de coverage). La sous-commande desktop qui [a mergé comme PR #33441 le 16 juin](/articles/2026-06-16--deno-desktop-subcommand-wef-cef-browserwindow) sort enfin comme première build taguée, le travail d'interop lockfile fait qu'un projet Node peut basculer vers Deno avec quelques commandes et un graphe de dépendances préservé, et le travail WebCrypto Modern Algorithms met Deno sur la même piste de cryptographie post-quantique que Node 24 LTS et Node 26 Current.

Les pièces que l'équipe a signalées comme prochains candidats pour une release Deno sont visibles depuis les descriptions de PR : le sharding avant le type-check (le trade-off de la [#35057](https://github.com/denoland/deno/pull/35057)), l'expansion de la Web Locks API (timeouts, `steal` avec timeout), la politique de confiance no-downgrade gagnant des overrides par paquet au-delà du tableau `trust-policy-exclude[]` existant, et `deno fmt` qui promeut les engines lax d'instable à stable. La liste complète des 165+ PRs du cycle 2.9 est sur [la release Deno 2.9.0 GitHub](https://github.com/denoland/deno/releases/tag/v2.9.0).