Essayez sans attendre l'hébergement proposé par WordPress
-15% sur le premier mois avec le code 2025PRESS15AFF

Essayer maintenant

Créer un thème WordPress enfant avec Vite.js : Workflow moderne de compilation d’assets en 2026

On a tous connu ce moment frustrant : modifier un thème WordPress parent et se retrouver à perdre tous ses changements à la prochaine mise à jour. Le thème enfant est la solution évidente, mais couplé à un workflow de compilation moderne, il devient vraiment puissant. Et c’est exactement là que Vite.js change la donne : fini les configurations interminables de Webpack, place à un outil rapide, simple et taillé pour le développement en 2026.

Pourquoi utiliser Vite.js pour un thème WordPress enfant en 2026

Bon, soyons honnêtes : pendant longtemps, le workflow de développement WordPress ressemblait à un chantier permanent. Webpack par-ci, Gulp par-là, des fichiers de config qui s’accumulent… Et à la fin, on passait plus de temps à maintenir l’outillage qu’à vraiment coder. En 2026, il existe une bien meilleure option : Vite.js. Voilà pourquoi ça change vraiment la donne.

Les limites des anciens outils (Webpack, Gulp, Grunt)

Qui n’a jamais pesté devant un webpack.config.js de 200 lignes pour compiler du SCSS et du JS ? Webpack, Gulp et Grunt ont rendu de grands services — c’est indéniable — mais ils traînent un sérieux boulet : la configuration verbeuse. Chaque projet nécessitait son lot de loaders, plugins et scripts npm à assembler soigneusement… sous peine de casser quelque chose.

Et ce n’est pas tout. Les temps de build pouvaient devenir franchement pénibles dès que le projet grossissait. Le Hot Module Replacement (HMR) de Webpack, bien que fonctionnel, n’a jamais vraiment été rapide. On attendait parfois plusieurs secondes à chaque modification de fichier. Sur une journée de dev, ça finit par coûter cher en concentration.

Grunt, de son côté, est aujourd’hui quasi abandonné. Gulp reste utilisé dans des projets legacy, mais difficile de recommander de repartir dessus en 2026 pour un nouveau projet.

Ce que Vite.js change concrètement pour le dev WordPress

Vite.js repose sur une philosophie radicalement différente : exploiter les ES modules natifs du navigateur en mode développement. Résultat ? Pas de bundle à reconstruire à chaque modification. Le serveur de dev ne recompile que le fichier modifié, et le HMR est quasi-instantané (on parle de quelques dizaines de millisecondes).

Pour la transpilation, Vite utilise esbuild sous le capot. Et là, les chiffres parlent d’eux-mêmes : esbuild est 10 à 100 fois plus rapide que Webpack selon les benchmarks. En pratique, un build de production qui prenait 30 secondes avec Webpack peut descendre à 2 ou 3 secondes avec Vite.

La configuration, elle, tient en quelques lignes. Pas de loaders à déclarer manuellement, pas de resolver alambiqué. On définit les entrées, on précise quelques options, et c’est parti. C’est cette simplicité structurelle qui rend Vite particulièrement adapté au contexte WordPress, où on veut se concentrer sur le thème, pas sur l’outillage.

Thème enfant ou thème sur-mesure : quel cas d’usage ?

La question revient souvent : pourquoi créer un thème enfant plutôt qu’un thème entièrement sur-mesure ? La réponse dépend vraiment du contexte du projet.

Si vous partez d’un thème parent robuste comme GeneratePress, Astra ou Blocksy, le thème enfant vous permet de surcharger uniquement ce dont vous avez besoin — templates, styles, scripts — sans toucher au code source du parent. Les mises à jour du thème parent restent donc sans risque pour vos personnalisations. C’est une approche pragmatique, surtout pour des projets avec des délais serrés.

Et en 2026, avec l’essor des thèmes Full Site Editing (FSE), la séparation parent/enfant garde tout son sens côté assets JS/CSS. Même si une grande partie du design est gérée via l’éditeur de blocs, vous aurez souvent besoin d’injecter du JavaScript custom ou des styles spécifiques qui n’ont pas leur place dans theme.json. C’est exactement là qu’un thème enfant couplé à Vite.js prend tout son intérêt.

Mise en place du projet : structure et configuration Vite.js

On entre dans le vif du sujet. Cette section, c’est vraiment le cœur du tutoriel : on va tout mettre en place, de l’installation de Node.js jusqu’à l’injection des assets dans WordPress. Suivez bien chaque étape dans l’ordre.

Prérequis et installation (Node.js, npm/pnpm, structure de fichiers)

Avant de toucher à quoi que ce soit, vérifiez votre environnement. Il vous faut Node.js 20+ LTS (obligatoire — Vite.js ne supporte plus les versions antérieures depuis la v5). Pour vérifier votre version :

node -v

Pour le gestionnaire de paquets, je recommande pnpm plutôt que npm. C’est plus rapide, plus économe en espace disque, et franchement une fois qu’on y passe on n’y revient pas. Installation globale :

npm install -g pnpm

Ensuite, voici la structure type de votre thème enfant :

mon-theme-enfant/
├── dist/               # Assets compilés (généré par Vite)
├── src/
│   ├── js/
│   │   └── main.js
│   └── scss/
│       └── main.scss
├── functions.php
├── style.css           # En-tête du thème enfant (obligatoire)
├── vite.config.js
└── package.json

Pour initialiser le projet dans le dossier du thème :

pnpm init
pnpm add -D vite sass

Ou si vous préférez partir d’un template Vite : pnpm create vite puis adapter la structure manuellement. La deuxième option est plus rapide, mais je trouve qu’on comprend mieux ce qu’on fait en initialisant à la main.

Configuration du fichier vite.config.js pour WordPress

C’est là que ça devient intéressant. La configuration Vite pour un contexte WordPress a quelques particularités importantes. Voici un fichier vite.config.js fonctionnel et commenté :

import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  // Base URL : chemin public vers le dossier du thème
  base: '/wp-content/themes/mon-theme-enfant/',

  build: {
    outDir: 'dist',
    // CRUCIAL : génère le manifest.json pour WordPress
    manifest: true,
    rollupOptions: {
      input: {
        main: path.resolve(__dirname, 'src/js/main.js'),
        style: path.resolve(__dirname, 'src/scss/main.scss'),
      },
    },
  },

  server: {
    // Proxy vers votre serveur local WordPress
    proxy: {
      '/': {
        target: 'http://mon-site.local', // Local by Flywheel, Laragon, MAMP...
        changeOrigin: true,
      },
    },
  },
});

Le point vraiment critique ici, c’est build.manifest: true. Sans ça, impossible de récupérer les noms de fichiers hashés côté PHP. Et c’est précisément ce hash qui garantit le cache-busting automatique à chaque build. Les entrées multiples (input) permettent de gérer JS et CSS séparément, ce qui est souvent préférable pour les performances (chargement différé, etc.).

Si vous devez supporter des navigateurs anciens (IE11, vieux Safari…), ajoutez le plugin legacy :

pnpm add -D @vitejs/plugin-legacy

Et dans vite.config.js :

import legacy from '@vitejs/plugin-legacy';
// ...
plugins: [legacy({ targets: ['defaults', 'not IE 11'] })]

Intégration des assets compilés dans functions.php

C’est la partie PHP du puzzle. Après un pnpm run build, Vite génère un fichier dist/.vite/manifest.json (depuis Vite 5, le manifest est dans un sous-dossier .vite/). Ce fichier ressemble à ça :

{
  "src/js/main.js": {
    "file": "assets/main-BxRJlY3k.js",
    "isEntry": true
  },
  "src/scss/main.scss": {
    "file": "assets/main-Dn9kZpRt.css",
    "isEntry": true
  }
}

L’idée : lire ce fichier depuis PHP pour enqueue les bons assets avec leur hash. Voici une fonction functions.php complète :

<?php
function mon_theme_enqueue_assets() {
    $theme_uri  = get_stylesheet_directory_uri();
    $theme_path = get_stylesheet_directory();
    $manifest   = $theme_path . '/dist/.vite/manifest.json';

    if ( ! file_exists( $manifest ) ) {
        return; // Pas de build, on n'enqueue rien
    }

    $assets = json_decode( file_get_contents( $manifest ), true );

    // Enqueue le CSS compilé
    if ( isset( $assets['src/scss/main.scss'] ) ) {
        $css_file = $assets['src/scss/main.scss']['file'];
        wp_enqueue_style(
            'mon-theme-style',
            $theme_uri . '/dist/' . $css_file,
            [],
            null // Le hash dans le nom de fichier fait office de version
        );
    }

    // Enqueue le JS compilé
    if ( isset( $assets['src/js/main.js'] ) ) {
        $js_file = $assets['src/js/main.js']['file'];
        wp_enqueue_script(
            'mon-theme-script',
            $theme_uri . '/dist/' . $js_file,
            [],
            null,
            true // Dans le footer
        );
    }
}
add_action( 'wp_enqueue_scripts', 'mon_theme_enqueue_assets' );

On passe null comme version dans wp_enqueue_style et wp_enqueue_script parce que le hash dans le nom de fichier suffit amplement pour le cache-busting. Pas besoin de doubler l’info.

Gérer le Hot Module Replacement (HMR) en développement local

En développement, on ne veut pas recompiler à chaque changement. Le HMR de Vite recharge instantanément les modules modifiés — CSS, JS, tout. Mais il faut que WordPress sache quand injecter le client Vite (le serveur de dev) plutôt que les assets buildés.

La solution : une condition sur la constante WP_DEBUG dans functions.php :

function mon_theme_enqueue_assets() {
    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
        // Mode développement : on charge le client Vite
        wp_enqueue_script(
            'vite-client',
            'http://localhost:5173/@vite/client',
            [],
            null,
            false
        );
        wp_enqueue_script(
            'mon-theme-dev',
            'http://localhost:5173/src/js/main.js',
            [],
            null,
            true
        );
    } else {
        // Mode production : on lit le manifest
        // ... (code précédent)
    }
}

Assurez-vous que WP_DEBUG est à true dans votre wp-config.php en local. Pour les environnements type Local by Flywheel ou Laragon, le port 5173 est celui par défaut de Vite — vérifiez qu’il n’est pas bloqué par votre firewall ou autre service.

Bon, et n’oubliez pas : ce code de dev ne doit jamais se retrouver en production. La condition WP_DEBUG est là exactement pour ça.

Déploiement et bonnes pratiques pour la production

On a mis en place le workflow de développement, le HMR fonctionne, les assets se compilent à la volée. Maintenant, il faut penser à ce qui se passe quand on déploie en production. Et là, Vite fait vraiment un excellent travail — à condition de savoir ce qu’il produit et comment en tirer le meilleur.

Optimiser le build final (minification, tree-shaking, chunking)

La commande de base, c’est simplement :

pnpm run build

Vite (via Rollup en interne) va compiler l’ensemble de vos assets et les déposer dans le dossier dist/. Ce que vous obtenez : des fichiers JS et CSS minifiés, avec un hash dans le nom de fichier, par exemple main.a3f2b1c.js ou style.9d4e2a1.css. Ce hash change à chaque build dès que le contenu du fichier est modifié. C’est le cache-busting automatique, et c’est précieux.

Le tree-shaking, c’est l’une des grandes forces de Vite/Rollup. Tout code importé mais non utilisé dans votre bundle sera automatiquement supprimé. Si vous importez une librairie entière mais n’utilisez que deux fonctions, seules ces deux fonctions se retrouveront dans le build final. Ça peut faire une différence significative sur le poids de vos assets.

Le code-splitting fonctionne via les imports dynamiques. Par exemple :

// Chargement conditionnel d'un module lourd
const { initSlider } = await import('./modules/slider.js');
initSlider();

Vite va automatiquement créer un chunk séparé pour slider.js, qui ne sera chargé que si ce code est exécuté.

Enfin, pour séparer proprement les dépendances externes de votre code métier, vous pouvez configurer le chunking manuel dans vite.config.js :

build: {
  rollupOptions: {
    output: {
      manualChunks: {
        vendor: ['alpinejs', 'gsap'], // vos librairies tierces
      },
    },
  },
},

Ça permet d’avoir un chunk vendor stable (qui ne change pas si vous modifiez seulement votre CSS), et donc un meilleur hit de cache navigateur en production. C’est une pratique recommandée dès que vous intégrez des librairies un peu lourdes dans votre thème.

Versioning, cache-busting et compatibilité avec les CDN

Bonne nouvelle : si vous avez correctement mis en place la fonction PHP de parsing du manifest.json vue en section 2, vous n’avez rien de plus à faire pour le cache-busting. Vite génère automatiquement un fichier dist/.vite/manifest.json qui contient les mappings entre le nom original et le nom hashé :

{
  "src/main.js": {
    "file": "assets/main.a3f2b1c.js",
    "css": ["assets/style.9d4e2a1.css"]
  }
}

Votre fonction PHP lit ce fichier, récupère le bon nom de fichier hashé, et l’enqueue dans WordPress. Le navigateur reçoit toujours le bon asset, sans avoir à vider le cache manuellement. Simple et efficace.

Côté CDN, si vous utilisez BunnyCDN, Cloudflare ou n’importe quel autre service, il suffit d’ajuster la propriété base dans votre vite.config.js selon l’environnement :

base: process.env.NODE_ENV === 'production'
  ? 'https://cdn.monsite.com/wp-content/themes/mon-theme-enfant/dist/'
  : '/',

Tous les chemins générés dans le manifest pointeront alors vers votre CDN en production. Côté PHP, pensez à filtrer wp_get_attachment_url ou à adapter votre fonction d’enqueue pour remplacer l’URL locale par l’URL CDN si vous ne la gérez pas directement depuis Vite.

Deux hooks WordPress méritent d’être mentionnés ici. D’abord, SCRIPT_DEBUG : si cette constante est définie à true dans wp-config.php, vous pouvez conditionner le chargement d’une version non minifiée pour le debug. Ensuite, wp_script_is() permet de vérifier si un script est déjà enregistré avant de l’enqueuer, ce qui évite les conflits (notamment si un plugin chargé une version de AlpineJS ou de GSAP en parallèle).

Une mise en garde importante, cependant. Si vous travaillez avec un thème FSE (Full Site Editing) basé sur theme.json, Vite ne compilera pas les styles déclarés dans ce fichier. theme.json est géré entièrement par WordPress via son propre système de génération CSS. Vite n’a pas accès à ce pipeline. Donc pour les thèmes FSE purs, ce workflow reste pertinent pour les assets JS et les styles additionnels, mais il ne remplace pas theme.json. C’est une limitation à bien intégrer avant de se lancer.