Pourquoi import.meta.env est undefined après la compilation Vite, et comment corriger.
Vite recopie chaque valeur import.meta.env.VITE_* dans votre JavaScript au moment de vite build. Si la variable n’a pas le préfixe VITE_, si elle n’existe que dans un fichier .env non versionné ou si elle a été définie après la compilation, le paquet contient undefined. Renommez-la, définissez-la là où la compilation s’exécute, puis recompilez.
Faits vérifiés le
Trouvez votre symptôme
Presque tous les cas tombent dans l’une de ces lignes. Les trois premières valent chez n’importe quel hébergeur; les deux dernières tiennent à la façon dont Canner attribue une portée aux variables.
| Ce que vous voyez | Pourquoi | Correctif |
|---|---|---|
import.meta.env.API_URL est undefined partout, même avec vite dev † † | Vite n’expose au code navigateur que les variables qui commencent par VITE_ (ou par votre envPrefix) | Renommez-la VITE_API_URL. Ne mettez jamais envPrefix à une chaîne vide : Vite le refuse, car toutes les variables seraient exposées |
| Ça marche en local, undefined après le déploiement † | La valeur est dans .env.local ou dans un autre fichier exclu par .gitignore; le serveur de compilation ne l’a jamais reçue | Définissez-la dans les variables d’environnement de l’hébergeur. Une vraie variable d’environnement a aussi priorité sur tout fichier .env |
| Vous avez changé la valeur dans le tableau de bord, le site affiche l’ancienne † | vite build a remplacé l’expression par une chaîne. Le site en ligne ne lit plus rien | Recompilez. Sur Canner, redéployez |
| Undefined seulement dans les aperçus de demandes de tirage (Canner) | La variable a la portée production; les aperçus ne reçoivent que toutes et aperçu | Donnez-lui la portée toutes, ou ajoutez une copie aperçu avec la valeur de préproduction |
| Undefined à chaque déploiement alors qu’elle est définie (Canner) | Sa portée est exécution seulement, qui n’atteint jamais une compilation | Passez à production ou toutes, puis redéployez |
† Les détails sur les concurrents proviennent des pages publiées par chaque fournisseur aux dates indiquées; les prix et forfaits changent, vérifiez auprès du fournisseur avant de décider. `import.meta.env.API_URL` est undefined partout, même avec `vite dev` (2026-10-29) · `import.meta.env.API_URL` est undefined partout, même avec `vite dev` (2026-10-29) · Ça marche en local, undefined après le déploiement (2026-10-29) · Vous avez changé la valeur dans le tableau de bord, le site affiche l’ancienne (2026-10-29)
Ce que vite build fait de la valeur
La documentation de Vite le dit : les constantes sont remplacées statiquement à la compilation. Il n’existe pas d’objet import.meta.env dans le navigateur où chercher une valeur plus tard. La compilation lit la valeur une fois et l’écrit dans le résultat, en texte :
vite builds’exécute en modeproduction: il charge.env,.env.local,.env.productionet.env.production.local. Les variables déjà présentes dans l’environnement au démarrage de Vite passent avant tous ces fichiers.- Le même remplacement se fait dans
index.html:%VITE_API_URL%devient la valeur au moment de la compilation. - Tout ce qui porte le préfixe
VITE_aboutit dans du JavaScript public. La documentation de Vite déconseille d’y mettre des clés d’API. Gardez les secrets côté serveur.
// src/api.ts, what you write
const base = import.meta.env.VITE_API_URL;
// dist/assets/index-<hash>.js, what ships after
// VITE_API_URL=https://api.example.ca vite build
const base = "https://api.example.ca";
// Check what a build actually contains:
grep -r "api.example.ca" dist/assetsDéfinir les variables Vite sur Canner
Canner exécute votre script build avec les variables du projet dans l’environnement : Vite les lit comme n’importe quelle variable d’environnement. Le journal de compilation le confirme par une ligne comme [canner] wrote 6 env var(s) to .env.production (build phase). Définissez les valeurs dans l’onglet Variables d’environnement du projet, pas dans un .env.production versionné. La page Vite de la documentation couvre le reste du déploiement.
Une valeur modifiée s’applique au déploiement suivant, puisque l’ancien paquet contient l’ancienne chaîne. Deux points moins évidents tirés de la documentation sur les variables d’environnement :
- Sensible masque une valeur dans le tableau de bord. Pas aux visiteurs : une valeur
VITE_sensible est quand même écrite dans le paquet public. - Exécution seulement tient un secret à l’écart de la compilation. C’est justement pourquoi une variable
VITE_avec cette portée est toujours undefined.
Exposer une valeur de compilation sans le préfixe
L’option define de Vite remplace un nom global par une valeur JSON pendant la compilation. Servez-vous-en pour des valeurs choisies délibérément, comme un bandeau d’aperçu ou un numéro de version dans vos rapports d’erreur :
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// CANNER_ENV is "production" or "preview" during a Canner build.
// It has no VITE_ prefix, so pass it through define, by name.
export default defineConfig({
plugins: [react()],
define: {
__APP_ENV__: JSON.stringify(process.env.CANNER_ENV ?? "local"),
__COMMIT__: JSON.stringify(process.env.CANNER_COMMIT_SHA ?? "dev"),
},
});Une seule compilation pour plusieurs environnements
Des valeurs fixées à la compilation, c’est une compilation par environnement. Pour promouvoir en production le dist/ exact que vous avez testé en préproduction, les valeurs ne peuvent pas y être intégrées. Il faut les récupérer ou les injecter au chargement de la page.
| Approche | Où vit la valeur | Pour la changer | Attention |
|---|---|---|---|
Une compilation par environnement (VITE_*) † | Dans le paquet JavaScript | Une recompilation | Les secrets sont visibles par tous |
config.json récupéré | Un fichier à côté d’index.html | Remplacer un fichier | Un fichier absent renvoie index.html chez un hébergeur d’appli monopage, et res.json() échoue avec Unexpected token '<' |
window.__ENV écrit par un serveur | L’environnement du serveur au démarrage | Un redémarrage | Vous exploitez désormais un serveur; échappez < dans le JSON |
† Les détails sur les concurrents proviennent des pages publiées par chaque fournisseur aux dates indiquées; les prix et forfaits changent, vérifiez auprès du fournisseur avant de décider. Une compilation par environnement (`VITE_*`) (2026-10-29)
Méthode 1 : récupérer config.json avant le démarrage
Votre étape de déploiement écrit un config.json différent par environnement et ne touche pas au JavaScript. Vérifiez le type de contenu : un hébergeur d’appli monopage répond à tout chemin inconnu par index.html et un code 200, si bien qu’une configuration absente ressemble à une requête réussie.
// public/config.json is copied to dist/ untouched
{ "apiUrl": "https://api.staging.example.ca" }
// src/main.ts
const res = await fetch("/config.json", { cache: "no-store" });
const type = res.headers.get("content-type") ?? "";
if (!res.ok || !type.includes("json")) {
// An SPA host answers a missing file with index.html
throw new Error("config.json is missing from this deploy");
}
export const config: { apiUrl: string } = await res.json();Méthode 2 : injecter window.__ENV depuis un serveur
Placez <!--app-env--> dans le <head> d’index.html; un petit serveur le remplit à partir de son propre environnement au démarrage. N’y mettez que des valeurs publiques : chaque visiteur peut lire la balise script.
// server.mjs: serves dist/ and writes public values into index.html
import express from "express";
import { readFileSync } from "node:fs";
const env = { apiUrl: process.env.API_URL }; // public values only
const html = readFileSync("dist/index.html", "utf8").replace(
"<!--app-env-->",
"<script>window.__ENV=" + JSON.stringify(env).replace(/</g, "\\u003c") + "</script>",
);
const app = express();
app.use(express.static("dist", { index: false }));
app.use((_req, res) => res.type("html").send(html));
app.listen(process.env.PORT || 3000);Laquelle choisir sur Canner
Sur Canner, tout changement de variable s’applique au déploiement suivant, et chaque déploiement exécute la compilation. La configuration à l’exécution ne vous épargne donc pas de compilation ici. Elle vaut la peine si le même artefact est déployé ailleurs aussi, ou si votre appli a déjà un serveur Node.
Le plus simple : un projet Canner par environnement. Un projet de préproduction et un projet de production, qui peuvent être reliés au même dépôt, chacun avec ses valeurs VITE_. Le forfait Démarrage inclut des projets illimités. Un projet Démarrage se met en veille après trois heures d’inactivité, ce qui convient en général à la préproduction.
Si vous choisissez la méthode 2, Canner détecte un projet qui embarque son propre serveur Node avec le client compilé, et exécute le serveur au lieu de servir dist/ en statique. D’autres guides sont dans hébergement par cadriciel.
Questions
Pourquoi import.meta.env fonctionne-t-il en développement mais pas en production?
En développement, Vite lit les fichiers .env sur votre poste, .env.local compris. En production, la valeur doit exister là où vite build s’exécute. Un fichier exclu par Git n’y arrive jamais, et une variable sans préfixe VITE_ n’est jamais exposée au code navigateur.
Peut-on changer une variable d’environnement Vite sans recompiler?
Pas une variable VITE_ : sa valeur est écrite dans le JavaScript pendant la compilation. Si elle doit changer sans compilation, déplacez-la dans un config.json récupéré ou un window.__ENV injecté par un serveur.
Peut-on mettre une clé d’API dans une variable VITE_?
Non. Tout ce qui porte le préfixe VITE_ aboutit dans du JavaScript public, lisible par n’importe qui. Appelez l’API depuis un serveur que vous contrôlez et gardez-y la clé.
Faut-il redéployer sur Canner après avoir changé une variable VITE_?
Oui. Les changements de variables s’appliquent au déploiement suivant, et c’est la compilation de ce déploiement qui écrit la nouvelle valeur dans le paquet. Voir variables d’environnement.
À lire aussi
- GuideJavaScript heap out of memory à la compilation
- GuideOù exécuter les migrations lors d’un déploiement
- GuideDéploiement sans interruption et sondes d’état
- RubyHébergement Ruby on Rails au Canada
- PythonHébergement Django au Canada
- PHPHébergement Laravel au Canada
Déployez votre appli Vite depuis Montréal.
Définissez vos variables VITE_ dans le tableau de bord, poussez, et Canner compile et sert le paquet.