Aller au contenu

Migrer depuis la 0.6

La version 1.0.0 est une version majeure. Cette page fait passer un projet de la 0.6.1 à la 1.0.0 : d'abord ce qui peut demander une action, chaque fois avec un extrait avant/après, puis les changements de comportement qui n'en demandent aucune mais peuvent surprendre. Le guide de migration du plugin sur GitLab couvre chaque cas particulier, et le journal des modifications sur GitLab (en anglais) liste chaque correction.

Dans les extraits, // 0.6.1 marque du code écrit pour la 0.6.1 et // 1.0.0 ce qui le remplace. Un bloc text montre ce qui est affiché, mot pour mot (le plugin écrit en anglais). MARS-TECH y est le prefix par défaut : le vôtre s'affiche à sa place.

En 30 secondes

  • Tout le monde : utilisez Node.js 20.19+ ou 22.12+ (24 recommandé). Chaque option renommée fonctionne encore jusqu'à la 2.0.0, avec un avertissement par groupe de clés. Seule stripInDeps a cessé de fonctionner.
  • Si un tsconfig inclut votre vite.config.ts (comme tsconfig.node.json sous vue-tsc -b), les anciens noms d'option sont des erreurs de type : renommez-les, comme l'indique Options renommées.
  • Si vous utilisiez stripInDeps, elle ne supprime plus rien : remplacez-la, comme le décrit stripInDeps.
  • Si vous importez MTPlugin, MTFormatContext, InstallStubOptions ou GlobalAccess, ces types ont disparu : voir Types supprimés et renommés.
  • Si un test ou un outil lit le texte des logs, les Map, Set, RegExp, Date, bigint et instances de classe s'affichent autrement, et un dernier argument qui n'est pas un objet d'options est désormais affiché : voir Sortie modifiée et Options en dernier argument.
  • Si vous utilisez redact, trois changements peuvent demander une action (voir Masquage) :
    • une entrée chaîne ne masque plus la console du navigateur : ajoutez une RegExp qui décrit la forme du secret ;
    • un groupe de capture ne garde plus son texte (la convention $1 de la 0.6.1) : utilisez une assertion arrière (lookbehind) ;
    • avec des entrées chaîne, $debug n'affiche rien, avec un avertissement, là où il ne peut pas les lire : un SSR dans un processus à part ou dans workerd, les pools forks de Vitest 3, et le mode navigateur de Vitest.

Le masquage est un filet de sécurité, pas un coffre-fort : il rattrape un secret journalisé par erreur. Ne journalisez jamais un secret volontairement.

Liste de vérification

  1. Vérifiez que node -v affiche 20.19+ ou 22.12+, en local et dans chaque image de CI.
  2. Installez la nouvelle version : npm install -D @mars-tech/vite-debug-plugin@^1.0.0.
  3. Lancez vite dev une fois et lisez les lignes qui commencent par votre préfixe ([MARS-TECH] par défaut) : chacune dit quoi changer. Rechargez chaque onglet du navigateur resté ouvert : un onglet qui tourne encore avec l'environnement d'exécution de la 0.6.1 ne transmet rien au terminal tant qu'il n'est pas rechargé.
  4. Remplacez stripInDeps, comme décrit dans stripInDeps.
  5. Mettez à jour les imports de types listés dans Types supprimés et renommés.
  6. Vérifiez que globalName est un identifiant JavaScript simple : mtDebug() lève désormais une erreur sinon.
  7. Cherchez les appels $debug qui passent une variable en dernier argument (voir Options en dernier argument).
  8. Mettez à jour les tests et instantanés qui vérifient le texte des logs (voir Sortie modifiée).
  9. Relisez redact : une RegExp à côté de chaque entrée chaîne que la console du navigateur doit masquer, une assertion arrière pour chaque groupe de capture, et chaque RegExp en temps linéaire (voir Masquage).
  10. Vue ou Nuxt : installez @vue/devtools-api si vous voulez le panneau Vue DevTools.
  11. Lancez vite build et lisez ses avertissements : chaque nouvel avertissement signale un appel qui lèverait une erreur en production (voir Builds de production).

Avant la mise à jour

Prérequis0.6.11.0.0
Node.js (engines)>=20.19.0^20.19.0 || >=22.12.0, testé sur 20.19, 22.12 et 24
Vite (dépendance pair)6, 7 ou 8inchangé
@vue/devtools-apinon utilisédépendance pair optionnelle, 6, 7 ou 8
ESLint, pour /eslint9 (configuration plate) et .eslintrc9 et 10 (configuration plate) ; .eslintrc sur ESLint 9 et antérieurs
Safari, avec redactDefaultsaucun minimum16.4 ou plus récent : les motifs par défaut utilisent des assertions arrière
  • Node.js 21 et 22.0 à 22.11 ne sont plus pris en charge. L'ancienne plage les admettait, mais Vite 7 et 8 les refusent ; la nouvelle plage est celle que déclarent Vite 7 et 8. Node.js 20.19+ fonctionne toujours, mais Node.js 20 ne reçoit plus de correctifs de sécurité depuis le 2026-04-30 : prévoyez de passer à 22.12+ ou 24. Sur un Node.js hors de la plage, npm affiche un avertissement EBADENGINE, refuse l'installation avec engine-strict, et Yarn 1 refuse par défaut. Voir Prérequis.
  • @vue/devtools-api ne sert qu'au panneau Vue DevTools (applications Vue et Nuxt). Sans lui, l'intégration est laissée de côté et rien d'autre ne change. Pinia ou Vue Router l'installent peut-être déjà, mais avec la disposition stricte de pnpm une copie transitive ne compte pas : installez-le vous-même (npm install -D @vue/devtools-api), puis redémarrez le serveur de développement.
  • ESLint 10 est pris en charge par la configuration plate. ESLint 10 a supprimé .eslintrc : voir TypeScript et ESLint.
  • Une nouvelle dépendance d'exécution, @jridgewell/trace-mapping, retrouve la localisation source de chaque appel.

Options renommées

Le plugin lit chaque ancienne clé, la reporte sur son nouveau nom quand mtDebug() s'exécute, et affiche un avertissement par groupe de clés. Les anciennes clés fonctionnent jusqu'à la 2.0.0.

0.6.11.0.0Remarques
browseroutput.consoleElle n'a jamais commandé que la console du navigateur.
terminaloutput.terminalfalse fait désormais aussi taire la sortie côté serveur.
showSourceLocationshowSourceMême nom que l'option par appel dont elle fixe la valeur par défaut.
allowDebugBuildlibrary.debugBuildPour les auteurs de bibliothèques.
libraryPrefixlibrary.brandPrefixSans debugBuild, elle avertit désormais au lieu de ne rien faire.
testStubtesttestStub: false devient test: false.
testLogtesttestLog: true devient test: 'log'.
ts
// 0.6.1
mtDebug({
  browser: false,
  showSourceLocation: false,
  allowDebugBuild: true,
  libraryPrefix: true,
  testLog: true,
});
text
[MARS-TECH] "allowDebugBuild" and "libraryPrefix" moved to "library" in 1.0.0. Use library: { debugBuild: true, brandPrefix?: true }. The old names still work until 2.0.0.
[MARS-TECH] "browser" moved to "output" in 1.0.0. Use output: { console, terminal, inspect, devtools }. The old name still works until 2.0.0.
[MARS-TECH] "showSourceLocation" moved to "showSource" in 1.0.0. It is the same switch as the per-call showSource option. The old name still works until 2.0.0.
[MARS-TECH] "testLog" moved to "test" in 1.0.0. Use test: 'stub' (default), test: 'log', or test: false. The old name still works until 2.0.0.
ts
// 1.0.0
mtDebug({
  output: { console: false },
  showSource: false,
  library: { debugBuild: true, brandPrefix: true },
  test: "log",
});

Remarques sur chaque clé

  • output porte un interrupteur par surface : console et terminal, et trois nouveaux en 1.0 : inspect (valeurs vivantes dans la console du navigateur), devtools (Vue DevTools) et file (un log NDJSON). Les quatre premiers valent true par défaut ; file est désactivé tant que vous ne le définissez pas. Avec console, terminal et devtools tous à false et file désactivé, la page reçoit un $debug sans effet : vos appels ne lèvent donc toujours pas d'erreur. Voir output.

  • terminal: false fait désormais aussi taire le côté serveur : le SSR et le processus Vite, là où la 0.6.1 affichait encore la sortie SSR. $debug reste aussi défini dans le processus Vite : en 0.6.1, un appel depuis vite.config.ts ou un autre plugin levait ReferenceError tant qu'aucun module SSR n'était chargé. Si vous comptiez sur la sortie SSR avec terminal: false, laissez output.terminal activé : le même interrupteur couvre aussi les lignes transmises par le navigateur.

  • library concerne les auteurs de bibliothèques : allowDebugBuild: true, libraryPrefix: true devient library: { debugBuild: true, brandPrefix: true }. libraryPrefix: true sans allowDebugBuild ne faisait rien en 0.6.1, en silence. Il ne fait toujours rien, et le dit désormais :

    text
    [MARS-TECH] library.brandPrefix has no effect without library.debugBuild — the prefix shadow is only prepended to the debug/ variant that debugBuild emits.

    Voir Création de bibliothèque.

  • showSource, l'option du plugin, porte désormais le même nom que l'option par appel showSource dont elle fixe la valeur par défaut.

  • test remplace deux booléens par une option à trois valeurs : 'stub' (par défaut, un $debug sans effet), 'log' (un vrai journaliseur de console) et false (ne rien enregistrer). Une combinaison change ce qui est installé : { testStub: false, testLog: true } n'installait rien en 0.6.1, et donne désormais 'log', car un testLog: true explicite est lu comme l'intention. Si vous vouliez vraiment ne rien enregistrer, écrivez test: false. Voir Tests.

Les builds de développement de la 1.0 avaient des clés plates inspect et devtools : elles sont reportées sur output avec le même avertissement.

Ancienne et nouvelle clé ensemble

Quand une configuration définit une ancienne clé et sa remplaçante, la remplaçante l'emporte là où elles se recouvrent, et le conflit a son propre avertissement :

js
// vite.config.js, migré à moitié
mtDebug({ browser: false, output: { console: true } });
text
[MARS-TECH] both "browser" and "output" are set; "output" wins where they overlap. Remove "browser".
[MARS-TECH] "browser" moved to "output" in 1.0.0. Use output: { console, terminal, inspect, devtools }. The old name still works until 2.0.0.

Les anciennes clés sont des erreurs de type

La correspondance se fait à l'exécution, pour les configurations que rien ne vérifie : Vite ne vérifie jamais lui-même les types de vite.config.ts. MTPluginOptions ne liste que les noms de la 1.0.0 : si un tsconfig inclut votre vite.config.ts, une ancienne clé fait échouer la vérification de types, même si elle fonctionne encore à l'exécution :

text
error TS2353: Object literal may only specify known properties, and 'browser' does not exist in type 'MTPluginOptions'.

Les anciens noms n'ont pas d'écriture typée : renommez les clés.

Supprimé

stripInDeps

stripInDeps permettait à une application consommatrice de supprimer les appels $debug qu'une dépendance livrait dans son bundle publié. L'option est supprimée. La passer déclenche un avertissement et ne supprime rien :

ts
// 0.6.1
mtDebug({ stripInDeps: ["@acme/cart-store"] });
text
[MARS-TECH] the "stripInDeps" option was removed in 1.0.0. A dependency shipping $debug calls should be built with library: { debugBuild: true }, which needs no configuration in the consuming app — ask its author. See MIGRATION.md for the migration.

MIGRATION.md est le guide de migration du plugin (en français : MIGRATION-fr.md), que cette page suit. Les dépendances ne sont plus jamais réécrites : les appels de la dépendance arrivent tels quels dans votre bundle de production, et y lèvent ReferenceError: $debug is not defined.

La correction revient à la bibliothèque. Demandez à son auteur de faire son build avec library: { debugBuild: true } (voir Création de bibliothèque) : ce build publie une variante dont les appels sont supprimés pour la production et une variante debug/ pour le développement, et l'application consommatrice n'a rien à configurer.

D'ici là, définissez un $debug sans effet avant que la dépendance s'exécute, depuis un script classique (sans type="module"), qui s'exécute avant tous les modules de la page, quelle que soit la façon dont le bundler découpe ou ordonne vos chunks :

html
<!-- index.html, dans <head>, avant tout script module -->
<script src="/debug-stub.js"></script>
js
// public/debug-stub.js — un script classique, donc exécuté avant tout module.
// Sous `vite dev`, l'environnement d'exécution du plugin se charge après lui et le remplace.
{
  const noop = () => {};
  globalThis.$debug ??= Object.assign(noop, {
    ns: () => noop,
    enable: noop,
    disable: noop,
    setLevel: noop,
    setPrefixFilter: noop,
    assert: noop,
    time: noop,
    timeEnd: noop,
    count: noop,
    group: noop,
    groupCollapsed: noop,
    groupEnd: noop,
    table: noop,
    dir: noop,
  });
}

Les fichiers de public/ sont copiés tels quels dans le build : le plugin ne traite donc jamais ce bouchon, et un <script src> externe ne déclenche aucun avertissement de build. N'importez pas plutôt le bouchon depuis votre module d'entrée : quand la dépendance atterrit dans un chunk partagé, le bundler place l'import de ce chunk en premier, et ses appels de premier niveau s'exécutent avant le bouchon. Contrairement à stripInDeps, le bouchon laisse les appels dans votre bundle et évalue toujours leurs arguments : il les rend seulement inoffensifs. Pour le rendu côté serveur, exécutez le même code en premier dans le serveur Node.js qui sert votre build de production.

Types supprimés et renommés

0.6.11.0.0
MTPlugin de /helpersPlugin de vite : MTPlugin en était un alias
MTFormatContext de /helpersaucun : il décrivait un point d'accroche format qui n'a jamais existé
InstallStubOptions de /testingMTInstallStubOptions, même forme
GlobalAccess de /eslintMTGlobalAccess, même forme
ts
// 1.0.0
import type { Plugin } from "vite";
import type { MTInstallStubOptions } from "@mars-tech/vite-debug-plugin/testing";
import type { MTGlobalAccess } from "@mars-tech/vite-debug-plugin/eslint";

TypeScript indique les nouveaux noms :

text
error TS2724: '"@mars-tech/vite-debug-plugin/testing"' has no exported member named 'InstallStubOptions'. Did you mean 'MTInstallStubOptions'?

Si votre code utilisait MTFormatContext comme forme, déclarez-la localement. Ce que le plugin produit réellement pour un appel est MTLogRecord, exporté par /helpers (voir Nouveautés de la 1.0).

Fichiers .map

Le package ne livre plus de fichiers .map : ils représentaient la moitié de sa taille. Le JavaScript de dist/ n'est pas minifié : les lignes de pile d'appels du plugin restent donc lisibles sans eux. Un build library.debugBuild n'écrit plus non plus de fichiers .map dans debug/ : la source map qu'il y copiait décrivait le chunk de production, dont les appels sont supprimés, et pointait donc vers les mauvaises lignes. Si le champ files de votre package.json cite dist/debug/*.map, retirez cette entrée.

Formes d'appel dépréciées

mtDebugGlobals, exporté par @mars-tech/vite-debug-plugin/eslint, prend désormais le même objet d'options que mtDebugFlatConfig :

js
// 0.6.1
mtDebugGlobals("$log", "readonly");

// 1.0.0
mtDebugGlobals({ globalName: "$log", access: "readonly" });

La forme positionnelle fonctionne encore jusqu'à la 2.0.0. Elle n'affiche aucun avertissement : son type est marqué @deprecated, si bien que les éditeurs la barrent. mtDebugGlobals() sans argument ne change pas.

L'option par appel { raw }, que seuls les builds de développement de la 1.0 avaient, est un alias déprécié de { inspect } : elle fonctionne encore, avec un avertissement unique, jusqu'à la 2.0.0.

API par appel

Options en dernier argument

$debug accepte désormais un nombre quelconque de charges utiles, comme console.log, et remplace les directives printf (%s, %d, %o…). Le dernier argument ne compte comme options que s'il est un objet simple dont chaque clé est un nom d'option (tag, showSource, showStack, prefix, inspect) ; en 0.6.1, le troisième argument l'était toujours. Les lignes de terminal ci-dessous omettent le (file:line:col) qui termine chaque ligne par défaut :

Appel0.6.11.0.0
$debug("info", "saved", { tag: "cart" })MARS-TECH Info [cart] - savedMARS-TECH Info [cart] - saved
$debug("info", "saved", undefined)MARS-TECH Info - savedMARS-TECH Info - saved undefined
$debug("info", "saved", {})MARS-TECH Info - savedMARS-TECH Info - saved {}
$debug("info", "saved", { tag: "cart", retry: 1 })MARS-TECH Info [cart] - savedMARS-TECH Info - saved {"tag":"cart","retry":1}
$debug("info", "user", { id: 1 })MARS-TECH Info - userMARS-TECH Info - user {"id":1}
$debug("info", "%s scored %d", "Ann", 42)MARS-TECH Info - %s scored %dMARS-TECH Info - Ann scored 42

La deuxième ligne est celle à chercher : une fonction qui relaie des options facultatives affiche désormais undefined chaque fois que son appelant n'en a passé aucune. Ne les passez que lorsque vous en avez :

ts
// 0.6.1
import type { MTCallOptions } from "@mars-tech/vite-debug-plugin/helpers";

export function logSaved(options?: MTCallOptions) {
  $debug("info", "saved", options);
}
ts
// 1.0.0
import type { MTCallOptions } from "@mars-tech/vite-debug-plugin/helpers";

export function logSaved(options?: MTCallOptions) {
  if (options) $debug("info", "saved", options);
  else $debug("info", "saved");
}

La forme à deux arguments ne change pas, et un objet d'options garde son autocomplétion. Une clé mal orthographiée ({ tagg: "x" }) n'est plus ignorée : elle est journalisée, ce qui vous montre la faute de frappe. Voir Valeurs multiples et printf.

$debug.enable(null)

enable accepte désormais null : il retire le filtre d'espaces de noms défini à l'exécution, y compris la copie enregistrée dans localStorage, et revient à la valeur par défaut filter du plugin (tous les espaces de noms, sauf si vous en avez défini un) :

ts
// 1.0.0
$debug.enable("cart*"); // seulement les espaces de noms cart, jusqu'à effacement
$debug.enable(null); // retour à la valeur par défaut configurée

En 0.6.1, enable(null) était une erreur de type, et depuis JavaScript il enregistrait le texte "null" comme filtre : après le rechargement suivant, seul un espace de noms nommé null s'affichait.

Masquage

redact et redactDefaults sont un filet de sécurité, pas un coffre-fort : ils rattrapent un secret qui arrive par erreur dans un appel à $debug. Ce que la 1.0.0 garantit, c'est que le plugin n'introduit jamais de fuite : chaque règle s'applique à chaque chaîne qu'un appel remet au plugin, exactement telle que votre code l'a passée, et à la ligne telle qu'elle est affichée ; chaque correspondance est masquée en entier ; et rien de ce que fait ensuite le plugin n'en fait réapparaître un caractère. Un secret que votre code a transformé avant de le journaliser (coupé, encodé, échappé) est une autre chaîne, hors de cette garantie. Voir Masquer les secrets.

Les entrées chaîne ne masquent que le côté serveur

Une entrée chaîne est en général le secret lui-même. La 0.6.1 écrivait chaque entrée dans l'environnement d'exécution qu'elle servait à la page, où tout script de l'origine de développement pouvait la lire, et dans l'environnement d'exécution SSR. La 1.0.0 n'écrit les entrées chaîne dans aucun module : elles restent dans la mémoire du processus qui charge votre configuration, et ne quittent jamais le serveur de développement. Elles masquent le terminal de développement, la sortie SSR, le fichier de log et test: 'log' hors d'un navigateur, jamais la console du navigateur ni Vue DevTools. Pour y masquer aussi une valeur, ajoutez une RegExp qui décrit sa forme : une RegExp est envoyée à la page telle qu'écrite, elle ne doit donc jamais contenir le secret.

ts
// 1.0.0
mtDebug({
  redact: [
    process.env.STRIPE_KEY ?? "", // la valeur : terminal, SSR, fichier de log, test: 'log'
    /sk_live_[A-Za-z0-9]+/, // sa forme : chaque surface, navigateur compris
  ],
});

Une chaîne vide ou non définie est ignorée, un nombre est recherché sous la forme littérale qu'il affiche, et toute autre valeur est ignorée avec un avertissement. En 0.6.1, une entrée non définie (undefined) ou un nombre levait une erreur au chargement de la configuration, et une chaîne vide masquait entre chaque caractère. Voir Entrées chaîne et entrées RegExp.

Le serveur de développement masque désormais chaque ligne qu'une page transmet avec chaque règle, là où la 0.6.1 l'affichait telle que la page l'envoyait. Vos entrées RegExp s'exécutent donc aussi dans le processus Vite, sur du texte que tout script de l'origine de développement peut envoyer : gardez-les en temps linéaire, comme l'explique Écrire une entrée RegExp.

Chaque correspondance est masquée en entier

La 0.6.1 réinsérait le premier groupe de capture d'un motif devant [redacted]. La 1.0.0 masque toute la correspondance : un groupe ne garde donc rien, et un motif qui commence par un groupe masque désormais aussi sa clé, soit plus qu'avant, jamais moins. Pour garder le texte qui précède un secret, décrivez-le avec une assertion arrière :

ts
// 0.6.1
mtDebug({
  redact: [/("password"\s*:\s*)"[^"]*"/], // $1 gardé : seule la valeur est masquée
});
ts
// 1.0.0
mtDebug({
  redact: [/(?<="password"\s*:\s*)"[^"]*"/], // une assertion arrière : seule la valeur est masquée
});

Pour $debug("info", { password: "hunter2" }), le motif de la 0.6.1 affiche désormais {[redacted]} ; l'assertion arrière affiche {"password":[redacted]}, comme la 0.6.1. Un groupe qui contenait le secret le gardait en 0.6.1 : /token=([0-9a-f]+)/ affichait ?deadbeef01[redacted] pour ?token=deadbeef01, là où la 1.0.0 affiche ?[redacted]. Les motifs de redactDefaults sont écrits avec des assertions arrière et affichent ce qu'ils affichaient. Le drapeau y (adhérent) d'une RegExp est retiré.

Là où $debug n'affiche rien

Avec des entrées chaîne configurées, chaque afficheur dans Node.js les lit dans le processus qui charge votre configuration. Là où un afficheur ne le peut pas, $debug n'affiche rien plutôt que de les afficher sans masque, et le signale une fois. La 0.6.1 y affichait, grâce aux entrées qu'elle écrivait dans l'environnement d'exécution.

Avec des entrées chaîne, $debug n'affiche rien dansPour y voir la sortie
Un SSR dans un processus à part, ou dans workerd (@cloudflare/vite-plugin)une RegExp pour la forme de chaque valeur
Les pools forks et vmForks de Vitest 3 (forks est son défaut)Vitest 4, ou pool: "threads"
Un projet Vitest qui s'exécute dans un navigateur, et la page navigateur de Vitestune RegExp pour la forme de chaque valeur
Un worker thread démarré avant le pluginredémarrer le worker

L'environnement d'exécution SSR, par exemple, affiche :

text
[MARS-TECH] $debug prints nothing in this process: the string entries of your redact option do not reach it, and it does not print what it cannot mask. They reach SSR in the Vite process and in a worker thread started after the plugin, and Vitest workers (the forks and vmForks pools from Vitest 4). Elsewhere - SSR in a process of its own, workerd - describe each such value with a RegExp for its shape instead.

Sans entrée chaîne, chaque afficheur affiche, masqué par vos entrées RegExp et les motifs par défaut. Les cas plus rares sont listés dans Là où les entrées chaîne n'arrivent pas.

Ce qui est masqué en plus

  • Chaque chaîne d'un appel, et la ligne. Chaque règle s'applique à chaque argument, à la chaîne de format, à chaque clé et chaîne d'un objet journalisé, à l'espace de noms et au tag, à un prefix par appel, aux libellés de count, time, timeEnd et group, au message et à la pile d'appels d'une Error, et au chemin source, puis à la ligne telle qu'elle est affichée. La 0.6.1 ne cherchait que dans le message affiché.
  • Une entrée chaîne est recherchée telle qu'écrite, et telle que JSON l'échappe : un secret qui contient un ", un \ ou un saut de ligne est masqué à l'intérieur d'un objet journalisé.
  • test: 'log' masque, avec vos redact et redactDefaults. La 0.6.1 y affichait chaque secret.
  • Les valeurs vivantes sont retenues dès qu'une entrée RegExp ou redactDefaults est configurée : la console du navigateur et Vue DevTools reçoivent le texte masqué au lieu de l'objet vivant, et table() et dir() affichent le résumé masqué. { inspect: true } rétablit l'objet pour un appel, dans la console seulement. Voir Valeurs vivantes dans le navigateur.
  • Un nombre %d, %i ou %f qui se lit autrement que son argument ("042917" affiche 42917) est masqué quand une règle correspond à l'argument. Sur une ligne venue du navigateur, avec des entrées chaîne configurées, le terminal et le fichier de log masquent un tel nombre quel que soit son argument.
  • redactDefaults couvre davantage : les identifiants Authorization: Basic ; la valeur de passphrase, x-api-key, private_key, credentials et cookie ; la valeur d'une clé secrète dans une paire [clé, valeur] (une Map, Object.entries()), et dans le JSON que contient une chaîne journalisée. Un cas masque moins : une adresse e-mail collée à la fin d'une autre sans séparateur (a@x.com%2Cb@y.org) laisse la seconde visible.
  • Sous Vite 8, dès qu'une règle de masquage est configurée et que server.forwardConsole n'est pas défini (Vite l'active quand il détecte un agent de programmation), vos propres appels console.error et console.warn n'atteignent plus le terminal par le transfert de console de Vite ; les erreurs non gérées, si. Un server.forwardConsole que vous définissez est conservé. Voir Transfert de la console par Vite 8.

Sortie modifiée

Rendu des charges utiles

Certaines charges utiles étaient rendues par JSON.stringify, qui perd ce qui les rend utiles à journaliser. Le résumé sur une ligne (le terminal de développement, le libellé de la console du navigateur, le fichier de log, test: 'log') change pour ces types :

Charge utile0.6.11.0.0
new Map([["sku-1", 2], ["sku-2", 1]]){"sku-1":2,"sku-2":1}Map(2) [["sku-1",2],["sku-2",1]]
new Set(["a", "b"])["a","b"]Set(2) ["a","b"]
/^tok_[a-z]+$/gi{}/^tok_[a-z]+$/gi
new Date("2026-10-14T08:00:00.000Z")"2026-10-14T08:00:00.000Z"2026-10-14T08:00:00.000Z
123n123123n
new Cart(), avec class Cart { items = 2 }{"items":2}Cart {"items":2}
{ a: shared, b: shared }, avec shared = { id: 1 }{"a":{"id":1},"b":"[Circular]"}{"a":{"id":1},"b":{"id":1}}

Un appel fait dans le processus Vite lui-même (depuis vite.config.ts, un autre plugin ou un SSR dans le même processus) affichait {} pour une Map et un Set en 0.6.1 ; il s'affiche désormais comme ci-dessus. Les chaînes, nombres, objets simples, tableaux et Error s'affichent comme avant. Un test qui vérifie l'ancien texte doit être mis à jour. Le tableau de rendu des charges utiles donne la forme de chaque type.

Dans la console du navigateur et le terminal

  • Valeurs vivantes. Chaque ligne du navigateur remet aussi la charge utile brute à la console : les objets, nœuds DOM et Error restent dépliables, comme avec console.log, sauf si une règle de masquage les retient. Pour retrouver l'affichage sur une ligne de la 0.6.1, définissez output: { inspect: false }. Voir Inspection d'objets vivante.
  • Les groupes sont de vrais groupes de console. $debug.group() ouvre un console.group repliable dans le navigateur au lieu d'indenter le texte. Le terminal et test: 'log' indentent toujours, et ne répètent plus le libellé comme tag : $debug.group("checkout") affiche MARS-TECH Debug - checkout, là où la 0.6.1 affichait MARS-TECH Debug [checkout] - checkout.
  • Les localisations source désignent votre source, dans un seul format. Sur chaque surface, le file:line:col est la position d'origine dans votre fichier .vue ou .ts, relative à la racine Vite et comptée à partir de 1 (src/Cart.vue:12:3), là où la 0.6.1 affichait une URL servie ou un chemin absolu. Pour un appel que la transformation de développement ne peut pas enregistrer, voir Le fichier:ligne de mon log est décalé de quelques lignes.
  • Vue DevTools. Avec @vue/devtools-api installé, un onglet MARS-TECH apparaît dans Vue DevTools. output: { devtools: false } le désactive. Voir Vue DevTools.

Autres changements de comportement

Aucun de ces changements ne demande de modifier le code.

Options et avertissements

  • enabled: true ne change rien, comme en 0.6.1, et n'affiche aucun avertissement. Non défini, il signifie déjà « actif sous vite dev, supprimé sous vite build » ; true n'a jamais forcé l'environnement d'exécution dans un build de production. Pour un build de debug, utilisez library: { debugBuild: true }.
  • enabled: false couvre désormais aussi test: 'log' : il revient au bouchon sans effet, là où la 0.6.1 installait encore le journaliseur de console sous Vitest.
  • globalName doit être un identifiant JavaScript simple qui n'est pas un mot réservé ($debug, myDebug). Tout le reste, comme un point, une espace ou un tiret, lève désormais une erreur quand mtDebug() s'exécute ; en 0.6.1, cela cassait en silence la suppression des appels et le bundledebug/ d'une bibliothèque.
  • Enregistrer le plugin deux fois ne garde que la première instance, avec un avertissement. Vite ne dédoublonne pas les plugins : un preset de framework qui ajoutait déjà mtDebug() affichait chaque log du navigateur deux fois. Voir Chaque log apparaît deux fois.
  • Enregistré hors de la liste plugins de premier niveau (sous build.rollupOptions.plugins, ou dans une configuration Rollup ou Rolldown), le plugin ne fait que supprimer les appels, sans avertissement. La 0.6.1 supposait vite dev dans ce cas et livrait du code de développement en production.
  • levels et minLevel ensemble déclenchent toujours un avertissement, mais seulement quand levels n'est pas vide : un levels: [] vide laisse la main à minLevel sans avertissement.
  • Le rendu côté serveur hors du processus Vite (le worker Nitro de Nuxt) applique désormais vos surcharges colors[level].ansi, là où la 0.6.1 affichait les couleurs intégrées.

Terminal et fichier de log

  • Les caractères de contrôle s'affichent échappés dans le terminal et le fichier de log : séquences d'échappement, \r isolé, contrôles C1, caractères de contrôle bidirectionnels. Une chaîne qui porte déjà des couleurs ANSI (de chalk, par exemple) affiche ses codes comme du texte. Les tabulations et les sauts de ligne sont conservés.
  • Les lignes transmises par le navigateur sont bornées : le message à 10 000 caractères, tag et prefix à 256, le fichier source à 1 024, la pile d'appels à 16 384 (au-delà, [stack omitted: N chars]). Une longue chaîne journalisée dans le navigateur est coupée dans le terminal.
  • Une page qui inonde le serveur de développement de logs voit son débit limité, y compris d'une connexion à l'autre : chaque connexion HMR peut transmettre une rafale de 10 000 lignes, puis 2 000 par seconde, et toutes les connexions ensemble une rafale de 20 000, puis 4 000 par seconde. Une ligne au-delà de l'une ou l'autre limite n'atteint ni le terminal ni le fichier de log, et une ligne toutes les 10 secondes indique combien ont été écartées. La console du navigateur affiche toujours chaque appel ; les lignes du SSR et du processus Vite ne sont pas limitées. Voir Ce qui atteint le terminal.
  • count() et time() retiennent jusqu'à 1 000 libellés chacun, en oubliant les moins récemment utilisés, et l'indentation des groupes cesse de croître à 32 niveaux.

Le fichier de log NDJSON est nouveau en 1.0 et a ses propres limites :

  • Il s'arrête à 100 Mio par session, dernière ligne comprise, avec une dernière ligne qui le signale et un avertissement unique dans le terminal. output.fileMaxBytes fixe une autre limite, en octets ; Infinity la lève. Voir Sessions et taille.
  • Il reste désactivé à côté des outils de développement qui lisent n'importe quel fichier pour la page : vite-plugin-vue-devtools, Nuxt DevTools, Vite DevTools, devframes et TanStack Devtools. Le terminal reçoit un avertissement unique qui nomme l'outil, et aucun réglage ne permet de passer outre. Un log laissé par une session précédente n'est alors pas vidé non plus : supprimez-le. Si vous avez besoin du log, lancez ces outils dans une session de développement séparée : dans Nuxt, devtools: { enabled: false } ; sous Vite 8, ni devtools: true ni plugins DevTools().
  • Le plugin écrit un .gitignore contenant * dans .mt-debug/, et dans tout dossier de log qu'il crée, jamais par-dessus un fichier existant. Cela garde le log hors de git, et hors de la détection automatique des sources de Tailwind CSS. À côté de @tailwindcss/vite, un log placé dans un dossier à vous dont le .gitignore ne contient pas * n'est pas ouvert, avec un avertissement unique. @tailwindcss/postcss n'est pas détecté : ajoutez ce fichier vous-même.

Builds de production

  • Les appels sont supprimés dans davantage de fichiers. La 0.6.1 ne les supprimait que dans les modules .js, .ts, .jsx, .tsx, .mjs, .mts et .vue. La 1.0.0 les supprime de chaque module de votre propre source qui nomme la globale (.cjs, un <script type="module"> en ligne, un module virtuel, des pages Svelte, Astro, MDX et VitePress), ainsi que des web workers et des scripts que Vite copie au lieu de les regrouper (un service worker, un worklet, un import ?url). Les appels qui s'y trouvaient étaient livrés et levaient une erreur.
  • De nouveaux avertissements de build pointent le code qui lève une erreur en production : une référence à $debug qui n'est pas un appel (const d = $debug), une méthode calculée ($debug['time']()), un appel dans un <script> classique en ligne ou un attribut on*, un script copié tel quel (un import ?raw, un fichier .ts), et un fichier que la suppression ne sait pas analyser. Corrigez chacun là où il pointe.
  • globalThis['$debug'](...) et window["$debug"] sont désormais supprimés comme les formes avec un point.
  • Une instruction $debug.ns('x') isolée est remplacée par void 0 ; un journaliseur stocké (const log = $debug.ns('x')) devient toujours une fonction vide qu'on peut appeler.
  • Les dépendances ne sont jamais réécrites : voir stripInDeps.

Voir Ce que couvre la suppression, Formes méthode et chaînée, Code exécuté dans un Worker et Scripts que Vite copie.

Tests

  • Le bouchon sans effet a ses 14 méthodes : setPrefixFilter, groupCollapsed, table et dir ne lèvent plus d'erreur sous Vitest.
  • test: 'log' donne à chaque projet Vitest sa propre configuration, affiche plusieurs charges utiles et printf, rend les charges utiles comme en développement, et masque.
  • Un projet que Vitest exécute dans un navigateur (--browser compris) reçoit ce que reçoit la page de développement : vos entrées RegExp et redactDefaults, jamais les entrées chaîne. Avec des entrées chaîne configurées, $debug n'y affiche rien.
  • @mars-tech/vite-debug-plugin/testing/log est retiré de setupFiles si vous l'y aviez listé avec test: 'log' : le plugin enregistre à la place un module généré à partir de votre configuration. Pour un journaliseur configuré sans le plugin, appelez installMtDebugConsole({ prefix, redact, … }) depuis /testing dans votre propre fichier de configuration des tests.

Voir Voir la sortie de $debug dans les tests.

Auteurs de bibliothèques

  • Les logs de bibliothèque marqués n'ont pas de localisation source. Avec library.brandPrefix, l'application consommatrice ne voit aucun file:line:col pour les appels de votre bibliothèque, sauf si un appel passe { showSource: true }. Voir Les logs de bibliothèque n'ont pas de localisation source.
  • Votre redact n'est pas livré dans debug/. La configuration de l'application consommatrice masque la sortie de votre bibliothèque, ou rien ne la masque. Ne passez jamais un secret à $debug dans le code d'une bibliothèque.
  • Les empreintes des fichiers changent. Les appels sont supprimés de la variante de production avant le calcul des empreintes : deux builds qui ne diffèrent que par une charge utile de $debug obtiennent les mêmes noms de fichiers.
  • Les builds umd et iife enveloppent dans un bloc la déclaration ajoutée par brandPrefix : elle ne déclare plus de $debug pour toute la page.
  • Les appels dans les templates Vue et les appels optionnels ($debug?.(…)) sont retirés de la variante de production quels que soient le minificateur et build.target, et les appels des templates dans debug/ atteignent le $debug global de l'application.

Nouveautés de la 1.0

Rien de ce qui suit n'exige de modification, mais tout mérite d'être adopté :

  • Un fichier de log NDJSON, pour les agents et les tests qui lisent les logs : mtDebug({ output: { file: true } }) écrit chaque appel, déjà masqué, dans .mt-debug/dev.ndjson sous la racine Vite. Pour des raisons de sécurité, ne l'utilisez pas quand votre code logue des secrets, même masqués : le log est un fichier sur le disque que tout outil qui lit des fichiers peut lire. Le tenir à l'écart de la page est un filet de sécurité, pas un coffre-fort : le plugin bloque chaque chemin connu d'une page vers le log, et un log que vous gardez est plus sûr hors du projet (hors de server.fs.allow, qui est la racine de l'espace de travail dans un monorepo), où Vite refuse tout fichier. Utilisez Vite 6.4.2, 7.3.2, 8.0.5 ou plus récent : les versions antérieures remettent n'importe quel fichier à un script de la page, votre .env compris. Voir Tenir le log à l'écart de la page.
  • Un filtre d'espaces de noms par défaut : mtDebug({ filter: "cart*" }), remplacé à l'exécution par ?mt-debug=, MT_DEBUG ou $debug.enable("auth*"). Voir filter.
  • Les piles d'appels par défaut : mtDebug({ showStack: true }) joint la pile masquée à chaque appel qui porte une Error. Voir showStack.
  • Plusieurs charges utiles et printf :$debug("info", "%s scored %d", name, score). Voir Valeurs multiples et printf.
  • D'autres fonctions utilitaires : $debug.groupCollapsed("checkout"), $debug.table(rows, ["name"]), $debug.dir(user). Voir Fonctions utilitaires.
  • L'inspection vivante dans la console du navigateur : $debug("info", document.body) donne un nœud que vous pouvez afficher dans le panneau Éléments. Voir Inspection d'objets vivante.
  • Vue DevTools : un inspecteur et une couche de chronologie MARS-TECH. Voir Vue DevTools.
  • Des enregistrements de log typés : MTLogRecord, exporté par /helpers, est un appel tel que le serveur de développement l'affiche et l'écrit dans le fichier de log ; MTLogLine, une ligne de ce fichier, y ajoute t, seq et origin.
  • Les types depuis l'entrée principale :import type { MTPluginOptions } from "@mars-tech/vite-debug-plugin". Voir Exports par sous-chemins.
  • Un journaliseur de test configuré sans le plugin :installMtDebugConsole({ prefix: "APP", redactDefaults: true }) depuis /testing. Voir Un journaliseur dans votre propre fichier de configuration des tests.
  • ./package.json est exporté, pour les outils qui lisent le manifeste d'une dépendance.

TypeScript et ESLint

  • Les projets CommonJS reçoivent des déclarations CommonJS. Sous module: node16 (ou nodenext avant TypeScript 5.8), un fichier CommonJS qui importait le plugin voyait TS1479. La condition require pointe désormais vers des fichiers .d.cts : retirez tout @ts-ignore ajouté pour cela.

  • La référence /client ne change pas. Gardez /// <reference types="@mars-tech/vite-debug-plugin/client" />. Elle type désormais l'appel à arguments variables, enable(null) et les nouvelles fonctions utilitaires, sous chaque moduleResolution.

  • Si vous implémentez MTDebug vous-même (un bouchon typé, une globale personnalisée), ajoutez groupCollapsed, table et dir, et acceptez null dans enable : un objet à la forme de la 0.6.1 ne satisfait plus le type. L'objet que construit le bouchon de stripInDeps est complet.

  • MTDebugFn est surchargé : la forme typée (level, payload, options?) et une forme à arguments variables (level, ...payloads). Une fonction que vous lui affectez doit accepter n'importe quelle valeur après le niveau : un troisième paramètre typé MTCallOptions échoue désormais avec TS2322 :

    ts
    // 1.0.0
    import type { MTDebugFn, MTLevel } from "@mars-tech/vite-debug-plugin/helpers";
    
    export const log: MTDebugFn = (level: MTLevel, ...rest: unknown[]) => {};
  • colors est typé MTColorOverrides : n'importe quel sous-ensemble de niveaux, chacun avec n'importe quel sous-ensemble de label, css et ansi. mtDebug({ colors: { warning: { label: "Warning" } } }), une erreur de type en 0.6.1, passe désormais la vérification.

  • MTCallOptions gagne inspect, qui force ou supprime la valeur vivante pour un appel.

  • ESLint 10 a supprimé .eslintrc. La configuration plate fonctionne sur ESLint 9 et 10. Si vous passez à la 10, remplacez mtDebugGlobals() dans .eslintrc par l'export par défaut :

    js
    // eslint.config.js
    import mtDebug from "@mars-tech/vite-debug-plugin/eslint";
    
    export default [mtDebug];

    Voir Déclarer la globale à ESLint.