diff --git a/index.html b/index.html
index a0cff56..30c90af 100644
--- a/index.html
+++ b/index.html
@@ -33,36 +33,16 @@
-
+
diff --git a/public/sw.js b/public/sw.js
index 29a62f6..e69de29 100644
--- a/public/sw.js
+++ b/public/sw.js
@@ -1,76 +0,0 @@
-// Service Worker pour mettre en cache les ressources statiques
-const CACHE_NAME = 'portfolio-v1';
-const STATIC_CACHE = 'portfolio-static-v1';
-
-// Ressources à mettre en cache immédiatement
-const STATIC_ASSETS = [
- '/',
- '/favicon.ico',
- '/favicon.svg',
- '/robots.txt',
- // GTM sera mis en cache lors de la première visite
-];
-
-// Installer le service worker
-self.addEventListener('install', (event) => {
- event.waitUntil(
- caches.open(STATIC_CACHE).then((cache) => {
- return cache.addAll(STATIC_ASSETS);
- })
- );
- // Forcer l'activation immédiate
- self.skipWaiting();
-});
-
-// Activer le service worker
-self.addEventListener('activate', (event) => {
- event.waitUntil(
- caches.keys().then((cacheNames) => {
- return Promise.all(
- cacheNames.map((cacheName) => {
- if (cacheName !== STATIC_CACHE && cacheName !== CACHE_NAME) {
- return caches.delete(cacheName);
- }
- })
- );
- })
- );
- self.clients.claim();
-});
-
-// Intercepter les requêtes
-self.addEventListener('fetch', (event) => {
- const url = new URL(event.request.url);
-
- // Stratégie Cache First pour les ressources statiques
- if (event.request.method === 'GET' &&
- (url.pathname.match(/\.(css|js|png|jpg|jpeg|webp|svg|woff|woff2|ttf|eot)$/i) ||
- url.hostname === 'www.googletagmanager.com' ||
- url.hostname === 'fonts.googleapis.com' ||
- url.hostname === 'fonts.gstatic.com')) {
-
- event.respondWith(
- caches.match(event.request).then((cachedResponse) => {
- if (cachedResponse) {
- return cachedResponse;
- }
-
- return fetch(event.request).then((response) => {
- // Ne mettre en cache que les réponses réussies
- if (response.status === 200 && response.type === 'basic') {
- const responseClone = response.clone();
- caches.open(CACHE_NAME).then((cache) => {
- cache.put(event.request, responseClone);
- });
- }
- return response;
- }).catch(() => {
- // Fallback pour les ressources critiques
- if (url.pathname.includes('gtm.js')) {
- return new Response('', { status: 404 });
- }
- });
- })
- );
- }
-});
diff --git a/src/App.tsx b/src/App.tsx
index 09fc00c..594f1a8 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -5,7 +5,6 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { lazy, Suspense } from "react";
import { ThemeProvider } from "./contexts/ThemeContext";
-import { useServiceWorker } from "./hooks/useServiceWorker";
// Lazy load pages and heavy components for better performance
const Index = lazy(() => import("./pages/Index"));
@@ -39,26 +38,21 @@ const router = createBrowserRouter([
},
]);
-const App = () => {
- // Enregistrer le service worker pour la mise en cache
- useServiceWorker();
-
- return (
-
-
-
-
-
-
-
-
- }>
-
-
-
-
-
- );
-};
+const App = () => (
+
+
+
+
+
+
+
+
+ }>
+
+
+
+
+
+);
export default App;
diff --git a/src/hooks/useServiceWorker.ts b/src/hooks/useServiceWorker.ts
index 47b8bfd..e69de29 100644
--- a/src/hooks/useServiceWorker.ts
+++ b/src/hooks/useServiceWorker.ts
@@ -1,40 +0,0 @@
-import { useEffect } from 'react';
-
-export const useServiceWorker = () => {
- useEffect(() => {
- if ('serviceWorker' in navigator && process.env.NODE_ENV === 'production') {
- // Enregistrer le service worker après un petit délai pour ne pas bloquer le rendu
- const registerSW = async () => {
- try {
- const registration = await navigator.serviceWorker.register('/sw.js', {
- scope: '/'
- });
-
- registration.addEventListener('updatefound', () => {
- const newWorker = registration.installing;
- if (newWorker) {
- newWorker.addEventListener('statechange', () => {
- if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
- // Nouvelle version disponible
- console.log('New service worker available, consider refreshing the page');
- }
- });
- }
- });
-
- console.log('Service Worker registered successfully');
- } catch (error) {
- console.log('Service Worker registration failed:', error);
- }
- };
-
- // Attendre que la page soit interactive avant d'enregistrer le SW
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', registerSW);
- } else {
- // Petit délai pour ne pas bloquer le rendu initial
- setTimeout(registerSW, 100);
- }
- }
- }, []);
-};
diff --git a/vite.config.ts b/vite.config.ts
index 1da9935..6fddb7a 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -24,30 +24,17 @@ export default defineConfig(({ mode }) => ({
},
build: {
// Optimisations pour la production
- minify: 'terser', // Utiliser Terser pour une meilleure compression que esbuild
+ minify: 'esbuild', // Utiliser esbuild au lieu de terser (plus rapide, déjà inclus)
target: 'esnext', // Code plus moderne et plus petit
- cssMinify: 'esbuild', // Garder esbuild pour CSS (plus rapide)
+ cssMinify: true,
// Chunking optimal pour de meilleures performances
rollupOptions: {
output: {
- // Split vendors pour améliorer le cache et réduire les tailles
- manualChunks: (id) => {
- // React et core
- if (id.includes('react') || id.includes('react-dom') || id.includes('react-router')) {
- return 'react-vendor';
- }
- // UI libraries
- if (id.includes('framer-motion') || id.includes('lucide-react') || id.includes('@radix-ui')) {
- return 'ui-vendor';
- }
- // Particles (lazy loaded anyway)
- if (id.includes('@tsparticles') || id.includes('particles')) {
- return 'particles';
- }
- // Autres node_modules dans un chunk séparé
- if (id.includes('node_modules')) {
- return 'vendor';
- }
+ // Split vendors pour améliorer le cache
+ manualChunks: {
+ 'react-vendor': ['react', 'react-dom', 'react-router-dom'],
+ 'ui-vendor': ['framer-motion', 'lucide-react'],
+ 'particles': ['@tsparticles/react', '@tsparticles/slim', '@tsparticles/engine'],
},
// Nommer les chunks de manière cohérente pour le cache
chunkFileNames: 'assets/js/[name]-[hash].js',
@@ -56,23 +43,12 @@ export default defineConfig(({ mode }) => ({
},
},
// Optimisation des assets
- assetsInlineLimit: 2048, // Réduire pour inliner moins d'assets
- chunkSizeWarningLimit: 300, // Limite encore plus stricte
+ assetsInlineLimit: 4096, // Images < 4kb seront inline en base64
+ chunkSizeWarningLimit: 500, // Limite plus stricte pour éviter les gros bundles
sourcemap: false, // Désactiver les sourcemaps en production
// Compression CSS supplémentaire
cssCodeSplit: true,
- // Minification supplémentaire avec Terser
- terserOptions: {
- compress: {
- drop_console: true, // Supprimer les console.log en production
- drop_debugger: true,
- pure_funcs: ['console.log', 'console.info', 'console.debug'],
- },
- mangle: {
- safari10: true,
- },
- },
- // Optimisations supplémentaires
+ // Minification supplémentaire
reportCompressedSize: true,
},
}));