Oxlint apps_v1.72.0 et oxfmt apps_v0.57.0 sont sortis ensemble dans la soirée du 29 juin 2026, sur la base de crates_v0.138.0. Cette version est le cycle v0.138 que les notes de version v1.71 prédisaient explicitement : « la dernière version apps avant la version crates v0.138 qui arrivera lundi 2026-06-29 ». Le cycle achève la migration AstBuilder qui courait sur les versions v0.135 à v0.137, retire le repli Prettier pour CSS / LESS / SCSS et GraphQL dans oxfmt, et livre la plus grande entrée de perf unique de l'étirement v0.137 → v0.138 : la mémoïsation value_type qui transforme une chaîne d'addition arithmétique de 20 000 termes de 6,1 secondes à 4,7 millisecondes.
Cet article couvre la version apps Oxlint v1.72.0, la version apps Oxfmt v0.57.0, et la version crates_v0.138.0 ensemble parce que les trois sont conçues pour sortir comme un tout. Oxlint et oxfmt récupèrent la dernière ligne crates au moment de la version, et les changements cassants de ce cycle sont concentrés dans la couche crates.
Unification AstBuilder : la migration v0.135 → v0.138 aboutit
La plus grande histoire du cycle v0.138 est l'unification des anciennes et nouvelles API AstBuilder dans le crate oxc_ast. La migration court depuis au moins v0.135 début juin et constitue le plus grand changement d'API interne qu'Oxc ait fait depuis la réécriture du minifier.
Le pattern est de cinq PR dans cette version qui déplacent la surface API vers un builder unique. #23876 (overlookmotel) restreint le module oxc_ast::builder à exporter uniquement le type AstBuilder et la sentinelle NONE. #23834 (overlookmotel) fait passer oxc_ecmascript à la nouvelle AstBuilder. #23831 (overlookmotel) fait passer le transformer à la nouvelle AstBuilder. #23875 (overlookmotel) supprime la duplication interne en unifiant les builders. #23877 (overlookmotel) marque les méthodes AstBuilder héritées comme #[deprecated]. Le cycle ajoute aussi un flag de feature Cargo disable_old_builder pour oxc_ast (#23886, #23888) afin que les crates en aval puissent activer le flag et voir ce qui casse avant que les méthodes héritées ne soient supprimées.
Le côté allocateur reçoit son propre lot de changements. #23675 (overlookmotel) renomme le trait AllocatorAccessor en GetAllocator. #23676 (overlookmotel) fait passer GetAllocator::allocator à &self au lieu de self. #23781 (overlookmotel) fait prendre &GetAllocator aux méthodes Str et Ident. Ensemble, les trois changements achèvent la migration vers une API d'allocateur par emprunt : les appelants n'ont plus besoin de cloner ou de posséder un allocateur pour construire des chaînes et des identifiants.
Pour les utilisateurs d'oxlint et oxfmt, rien de tout cela n'est visible. Pour les crates en aval qui construisent des couches AST personnalisées sur Oxc, c'est le plus grand changement cassant en trois cycles. Les notes de version signalent la fenêtre de migration : les méthodes héritées portent des annotations #[deprecated] maintenant, compileront avec des avertissements, et seront supprimées dans un cycle futur. L'équipe signalait cela depuis deux cycles, les notes de version v0.137 avertissant déjà du changement cassant dans oxc_ast.
L'entrée de perf phare : la mémoïsation value_type transforme O(n²) en O(n)
La plus grande entrée de perf visible par l'utilisateur en v0.138 est la PR #23929 (Dunqing) : perf(minifier): memoize value_type to remove its O(n^2) re-walk on long binary chains. Le peephole post-order du minifier évalue Expression::value_type à chaque nœud, et sur une longue chaîne binaire associative à gauche l'évaluation parcourt à nouveau tout le sous-arbre gauche (to_primitive → value_type → to_primitive → …). Pour N nœuds le coût total était O(N²), et le cas dominant est celui des chaînes d'addition arithmétique non repliables : un a + a + … + a de 20 000 termes prenait 6 118 ms à minifier tandis que les phases de parsing et de sémantique étaient linéaires.
Le correctif mémoïse value_type par adresse de nœud sur MinifierState, avec un point de coupure unique à la méthode récursive Expression::value_type. Chaque nœud est calculé une seule fois, donc le coût total devient O(N) amorti. Le cache est exposé comme hooks opt-in sur GlobalContext (cached_value_type / cache_value_type), et seul le TraverseCtx<MinifierState> du minifier fournit un vrai cache. Tout autre appelant (WithoutGlobalReferenceInformation, la passe d'évaluation de constantes, l'analyse d'effets de bord, le harnais unitaire value_type) conserve le comportement non mis en cache exact précédent. Le cache est vidé au point unique de mutation (record_mutation, touché par chaque replace_* / drop_*) et à chaque reset par passe.
Les chiffres, directement tirés de la description de la PR :
| entrée | avant | après | effet |
|---|---|---|---|
a + a + … × 4 000 | 234 ms | 0,9 ms | passage à l'échelle 4,07x → 2,09x (O(n²) → O(n)) |
a + a + … × 8 000 | 953 ms | 1,9 ms | linéaire à partir d'ici |
a + a + … × 20 000 | 6 118 ms | 4,7 ms | ≈1300x plus rapide |
| antd.js (code réel) | 78,1 ms | 65,4 ms | ≈16% plus rapide sur entrée réelle |
Le point clé est que les chaînes d'addition arithmétique sur la sortie minifiée (celles qu'on trouve dans le code numérique généré et dans les gros polyfills) chutent de trois ordres de grandeur. Les bundles réels chutent de 16% au premier passage, les gains se composant sur des entrées plus grandes.
Le cycle comporte cinq autres entrées de perf qui méritent d'être signalées. semantic: Flatten hoisting_variables to avoid per-scope map allocation (Lawrence Lin) supprime l'allocation de map par scope qui se déclenchait à chaque mise à jour de variable hissée. isolated-declarations: Pool scope maps to avoid per-scope alloc/rehash (Boshen) mutualise les scope maps utilisés par oxc_isolated_declarations pour que l'alloc/rehash par fonction disparaisse. minifier: Bail member-expr folding before the side-effect walk (Lawrence Lin) plie les cas simples des chaînes a.b.c.d avant la marche des effets de bord. parser: Avoid span lookup for arrow expression body (camc314) supprime une recherche de hashmap par expression fléchée. Côté formateur, formatter_core: Add printable-ASCII fast path to TextWidth (Lawrence Lin) offre au calcul de largeur de ligne du formateur un fast path quand le texte est de l'ASCII imprimable pur, ce qui couvre la grande majorité de la sortie formatée.
Il y a aussi un cluster de trois PR qui déplacent l'allocation de nœuds AST hors de Box::new_in vers une allocation d'arène directe : parser: Allocate AST nodes in arena directly (overlookmotel), minifier: Allocate AST nodes in arena directly (overlookmotel), et isolated_declarations: Allocate AST nodes in arena directly (overlookmotel). Ensemble, ils remplacent l'indirection Box::new_in par une écriture directe en bump allocator, supprimant une allocation heap par nœud AST dans le parseur, le minifier, et le pipeline isolated-declarations.
Oxfmt v0.57 retire le repli Prettier pour CSS / LESS / SCSS / GraphQL
Le plus grand changement structurel d'oxfmt est le retrait du repli Prettier pour les grammaires CSS et GraphQL. Avant v0.57, oxfmt pouvait formater les fichiers CSS / LESS / SCSS et GraphQL, mais le faisait en déléguant à un Prettier groupé pour ces grammaires. v0.57 retire le repli et formate les deux grammaires nativement en Rust.
Le côté CSS arrive sous le nom d'oxc_formatter_css (leaysgur) et est connecté via l'entrée BREAKING Format parser:css,less,scss files + css-in-js by oxc_formatter_css (leaysgur). Le crate est une implémentation de formateur autonome qui prend les parseurs CSS / LESS / SCSS existants, parcourt l'AST, et émet une sortie compatible Prettier. Les notes de version mentionnent explicitement le css-in-js comme pris en charge : les template literals de style styled-components et Emotion, qu'oxfmt détecte déjà et route vers le parseur CSS, sont maintenant formatés par oxc_formatter_css plutôt que par le shim Prettier.
Le côté GraphQL arrive sous le nom d'oxc_formatter_graphql (leaysgur) et est connecté via l'entrée BREAKING Support draft syntax with removing prettier fallback (leaysgur). La partie « draft syntax » est la partie vraiment nouvelle : l'implémentation GraphQL précédente d'oxfmt gérait la spec stable 2021 ; la nouvelle gère la syntaxe draft GraphQL October 2021 et la syntaxe working-draft utilisée par Apollo Federation et Yoga. C'est une vraie fonctionnalité, pas juste un renommage : le repli Prettier ne pouvait pas non plus gérer la draft syntax, donc la mise à niveau comble aussi un vrai écart format-on-save pour les utilisateurs sur la stack Apollo.
Deux PR de parité avec Prettier rapprochent la sortie des nouveaux formateurs de celle de Prettier : formatter_css: Improve major prettier diffs (leaysgur) et formatter_graphql: Improve major prettier diffs (leaysgur). Les notes de version signalent que des diffs réels sur les bases de code existantes sont encore attendus (le pattern typique « premier passage change quelques lignes, passages suivants idempotents »), mais l'écart est bien plus petit qu'il ne l'était en v0.56.
La version ajoute aussi formatter_css: Handle frontmatter language (leaysgur), qui route le frontmatter Markdown dans les fichiers CSS (par exemple le bloc --- en haut du bloc <style> d'un SFC Vue quand il a des métadonnées frontmatter) vers le parseur frontmatter plutôt que de le traiter comme du CSS, et le fast path ASCII imprimable dans TextWidth mentionné plus haut.
La vue d'ensemble est qu'oxfmt n'est plus un « formateur JS / TS avec un sidecar Prettier pour tout le reste ». Après v0.57 les chemins JS / TS / JSON / JSONC restent sur le formateur interne (ce qui est le cas depuis v0.54), et CSS / LESS / SCSS / css-in-js et GraphQL les rejoignent. Les grammaires restantes que Prettier gère (Markdown, YAML, HTML) ne sont pas dans le périmètre d'oxfmt ; oxfmt les laisse explicitement à Prettier et aux parseurs Rust de Prettier 3.9 qui sont arrivés le 27 juin.
Le cycle touche aussi la commande de migration : fix(oxfmt): update --migrate prettier (leaysgur) remet au propre la commande de migration de configuration Prettier → oxfmt pour gérer les nouveaux formateurs CSS / GraphQL internes. La commande reste le chemin recommandé pour amener une configuration Prettier existante dans un projet oxfmt ; la mise à jour v0.57 ajoute les nouvelles grammaires à la table de conversion.
Oxlint v1.72 fonctionnalités et la décharge de perf
La version apps Oxlint v1.72.0 livre trois fonctionnalités, dix-huit corrections de bugs, et vingt-trois entrées de performance sur la base de crates_v0.138.0. La fonctionnalité phare est linter/react: Implement suggestion for no-unknown-property (Mikhail Baev), qui ajoute un Quick Fix à la règle React no-unknown-property. Avant v1.72 la règle signalait le problème sans action de code ; les éditeurs signalaient la propriété comme inconnue mais le développeur devait la renommer manuellement. Après v1.72 l'éditeur peut proposer un renommage sur place vers la propriété connue la plus proche.
La deuxième fonctionnalité est ast: Unify old and new AstBuilders (overlookmotel), la même unification qui motorise la version crates_v0.138.0. Côté apps, le chemin d'import bascule vers l'AstBuilder unifié, sur quoi le travail de règles de ce cycle se construit.
La troisième fonctionnalité est linter: Add schema for eslint/no-restricted-import (Sysix). Le schéma permet aux utilisateurs d'exprimer les tableaux paths et patterns de no-restricted-import via le schéma de configuration plutôt qu'en JSON brut, ce qui comble un écart de longue date dans le chemin de migration de configuration ESLint → oxlint.
Les dix-huit corrections de bugs vont des faux positifs de cas limite aux correctifs anti-panique. La plus marquante est linter/prefer-called-exactly-once-with: Avoid out-of-bounds slice panic at end of file (Jerry Zhao), qui a fermé une vraie panique qui pouvait crasher le linter sur les fichiers de test où l'assertion était la dernière expression. Autres correctifs notables : linter/unicorn/custom-error-definition: Handle non-ascii class names (camc314), linter/eslint/no-negated-condition: Add autofix for negated conditions (Yagiz Nizipli), linter/eslint/prefer-destructuring: Skip AssignmentExpression autofixes (camc314), et linter/eslint/no-restricted-globals: Handle shadowed locals (camc314).
Les vingt-trois entrées de performance continuent l'histoire du bucketed-dispatch v1.71. Les entrées phares : linter/jsx-a11y: Skip lowercasing non-aria attribute names (Lawrence Lin), qui supprime une allocation to_ascii_lowercase par attribut JSX ; linter/typescript/no-unsafe-declaration-merging: Use keyed binding lookup (Marius Schulz), qui remplace une recherche linéaire par la même table keyed-binding que le bucketed dispatch v1.71 a introduite ; linter/eslint/no-unused-vars: Precompute exported bindings (camc314) ; linter/unicorn/prefer-number-properties: Speed up global checks (camc314) ; linter/eslint/no-script-url: Match javascript: prefix without allocating (Lawrence Lin) ; et linter: Skip traversal without this expressions (camc314), qui court-circuite une classe de règles quand il n'y a aucune this-expression dans le fichier. Combinées avec la base bucketed-dispatch v1.71, les entrées de perf v1.72 amènent oxlint au point où le temps mural de la plupart des règles est dominé par le parcours d'arbre, pas par le churn d'allocation interne aux règles.
Les corrections de bugs du linter incluent aussi linter/jsx-a11y/role-supports-aria-props: Ignore nullish prop values (Mikhail Baev) et linter/eslint/no-warning-comments: Avoid dropping generated regex patterns (camc314), qui ferment toutes deux des écarts de faux positifs sur du JSX réel. Le côté LSP reçoit lsp: Normalize user config path to watch pattern (Sysix), qui corrige un bug de résolution de chemin LSP de longue date sur Windows.
La fonctionnalité Vue typeof define keys
La PR #23605 par Alexander Lichter ajoute transformer_plugins: Support typeof define keys. La PR ajoute le support des clés typeof à l'intérieur du pattern de macro define sur lequel le plugin compiler-macros de Vue s'aligne. Les macros Vue defineProps, defineEmits, defineModel, defineSlots, et autres acceptent une forme runtime (defineProps<typeof import('./foo').bar>()), et l'implémentation transformer_plugins précédente ne reconnaissait pas cette forme. Après v0.138, le crate transformer_plugins reconnaît les clés typeof comme sous-pattern du corps de macro, donc le code TypeScript résultant conserve ses imports de types à travers l'expansion de macro.
Le pattern est partagé par les macros de l'écosystème Vue qui reposent sur defineProps. defineI18nLocale et defineI18nRoute de vue-i18n, les macros d'auto-import de Nuxt (defineNuxtConfig, defineNuxtPlugin), et les patterns de macro des setup stores de pinia acceptent tous une référence typeof import(...) dans le corps de macro. Avant cette PR, le transformer soit échouait à matcher la macro (le chemin de repli générait la macro comme un appel no-op), soit, pire, traitait le token typeof comme une valeur et cassait le tracking d'imports de types.
La PR est aussi le premier changement côté Oxc du cycle v0.138 avec un contributeur de l'écosystème Vue dessus. Alexander Lichter est le mainteneur de vue-router et un contributeur fréquent de la conversation sur les compiler macros Vue ; le support typeof débloque un problème de longue date dans l'écosystème vue-i18n et constitue le signal le plus clair de ce cycle que la surface transformer_plugins se rapproche d'être utilisable sur des bases de code Vue réelles sans un passage vue-tsc en amont.
À surveiller
Trois signaux pour les deux à trois prochaines semaines. Premièrement, surveillez la ligne de patch v0.138.1 et tout signalement de problème de rétro-compatibilité sur la migration AstBuilder : les méthodes héritées sont marquées #[deprecated] dans ce cycle, mais les crates en aval qui construisent des AST personnalisés sur Oxc vont maintenant avoir des avertissements et des cassures au cycle suivant. Le cluster de PR autour de #23877 est l'endroit à surveiller ; si un crate en aval (rolldown, biome, le port Rolldown de Vite, parcel) ouvre un ticket sur la nouvelle forme d'AstBuilder, attendez-vous à un cycle v0.139 avec un guide de migration explicite. Deuxièmement, surveillez l'arrivée d'Oxfmt v0.58 avec une entrée de parité de compat graphql-ou-css. Les PR de parité avec Prettier (#23327, #23419) ont substantiellement réduit l'écart, mais les notes de version signalent que des diffs réels sont encore attendus ; une entrée v0.58 qui ramènerait le nombre de diffs à zéro sur une base de code CSS / GraphQL représentative confirmerait que les nouveaux formateurs sont prêts pour la migration en production. Troisièmement, surveillez l'arrivée de la mémoïsation value_type dans oxc_isolated_declarations ou oxc_transformer. La conception de la PR #23929 est explicite : le cache est opt-in via des hooks sur GlobalContext, et seul le minifier fournit un vrai cache dans ce cycle. Le prochain cycle est l'endroit naturel pour que le transformer et isolated-declarations opt-in ; si c'est le cas, les pipelines de strip-de-types obtiendront le même gain de perf sur les chaînes arithmétiques que le minifier vient d'obtenir.
La leçon plus large est celle que l'article Prettier 3.9 a faite il y a deux jours : la toolchain JavaScript est en train d'être reconstruite sur la stack Rust Oxc, une grammaire à la fois, et le cycle v0.138 ferme deux grammaires supplémentaires (CSS / LESS / SCSS et GraphQL côté oxfmt) et achève une migration d'API interne (AstBuilder + GetAllocator côté crates). Le même pattern apparaît dans la migration SDK de Cline, dans l'unification Vite+ de Vite (la bannière sur le site Oxc), et dans l'intégration Bun + Anthropic. La forme de 2026 à travers l'écosystème Oxc est une séquence de grandes réécritures d'architecture livrées par étapes, chaque cycle marquant un composant supplémentaire comme « terminé » et libérant le cycle suivant pour se concentrer sur les écarts restants.



