///
import { defineConfig, type Plugin } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
import { visualizer } from 'rollup-plugin-visualizer'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
const isProduction = mode === 'production'
return {
plugins: [
react(),
// Plugin pour générer des nonces CSP
{
name: 'csp-nonce',
generateBundle(_options: any, bundle: any) {
// Générer un nonce pour chaque build
const nonce = Buffer.from(Math.random().toString()).toString('base64')
// Injecter le nonce dans les scripts inline
for (const fileName in bundle) {
const chunk = bundle[fileName]
if (chunk.type === 'chunk' && chunk.code) {
chunk.code = chunk.code.replace(
/__CSP_NONCE__/g,
nonce
)
}
}
}
} as Plugin,
// Bundle analyzer for production builds
(isProduction && visualizer({
filename: 'dist/bundle-analysis.html',
open: false,
gzipSize: true,
brotliSize: true,
})) as Plugin,
// CRITICAL FIX: Plugin pour forcer l'export de React depuis vendor-react-core
// Le problème: vendor-react-core ne contient pas d'export $ pour React
// Solution: Forcer l'export de React depuis vendor-react-core
{
name: 'force-react-export',
generateBundle(_options: any, bundle: any) {
// Trouver le chunk vendor-react-core
for (const fileName in bundle) {
const chunk = bundle[fileName]
if (chunk.type === 'chunk' && chunk.fileName && chunk.fileName.includes('vendor-react-core')) {
if (chunk.code) {
// Trouver la variable React qui a createContext
// React est généralement défini comme: var g = Za() et ensuite g.createContext existe
// On cherche toutes les variables = Za() et on trouve celle qui a createContext
const allZaMatches = chunk.code.match(/(\w+)\s*=\s*Za\(\)/g);
let reactVar = null;
if (allZaMatches) {
for (const match of allZaMatches) {
const varMatch = match.match(/(\w+)\s*=\s*Za\(\)/);
if (varMatch) {
const varName = varMatch[1];
// Vérifier si cette variable a createContext
if (chunk.code.includes(`${varName}.createContext`)) {
reactVar = varName;
break;
}
}
}
}
// Si on n'a pas trouvé, chercher directement la variable qui a createContext
if (!reactVar) {
const createContextMatch = chunk.code.match(/(\w+)\.createContext/);
if (createContextMatch) {
reactVar = createContextMatch[1];
}
}
if (reactVar) {
// Vérifier si React est déjà exporté avec le nom $
const hasDollarExport = chunk.code.match(/export\s+\{[^}]*\$[^}]*\}/);
if (!hasDollarExport) {
// Ajouter l'export de React avec le nom $ pour que react-hook-form puisse l'importer
const exportStatement = `export{${reactVar}as $}`;
// Vérifier si le chunk se termine par un point-virgule ou une nouvelle ligne
if (!chunk.code.trim().endsWith(';') && !chunk.code.trim().endsWith('}')) {
chunk.code += ';';
}
chunk.code += `\n${exportStatement};`;
// #region agent log
const logData = {
location: 'vite.config.ts:force-react-export',
message: 'Added React export to vendor-react-core',
data: {
reactVar,
fileName: chunk.fileName,
exportStatement,
},
timestamp: Date.now(),
sessionId: 'debug-session',
runId: 'build-analysis',
hypothesisId: 'H',
};
fetch('http://127.0.0.1:7242/ingest/09c5ea5e-2380-4cc3-92aa-d26f3b3d26f6',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(logData)}).catch(()=>{});
// #endregion
}
}
}
}
}
}
} as Plugin,
// CRITICAL FIX: Plugin pour réorganiser les modulepreload links dans le HTML
// Le problème: vendor-react-hook-form est préchargé avant vendor-react-core
// Solution: Réorganiser les modulepreload links pour que vendor-react-core soit en premier
{
name: 'fix-react-load-order',
transformIndexHtml(html: string) {
// Extraire tous les modulepreload links
const modulepreloadRegex = /]*>/g;
const modulepreloadLinks = html.match(modulepreloadRegex) || [];
// Séparer les links React des autres
const reactCoreLink = modulepreloadLinks.find(link => link.includes('vendor-react-core'));
const reactHookFormLink = modulepreloadLinks.find(link => link.includes('vendor-react-hook-form'));
const otherLinks = modulepreloadLinks.filter(link =>
!link.includes('vendor-react-core') && !link.includes('vendor-react-hook-form')
);
// Si on a trouvé les deux chunks React, réorganiser
if (reactCoreLink && reactHookFormLink) {
// Retirer tous les modulepreload links existants
let newHtml = html.replace(modulepreloadRegex, '');
// Réinsérer dans le bon ordre : React core d'abord, puis react-hook-form, puis les autres
const orderedLinks = [
reactCoreLink,
reactHookFormLink,
...otherLinks
].join('\n ');
// Insérer après le script module principal
newHtml = newHtml.replace(
/(