import fs from "node:fs"; import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import { fileURLToPath } from "node:url"; import { dirname, resolve } from "node:path"; import Sitemap from "vite-plugin-sitemap"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); import tailwindcss from "@tailwindcss/vite"; import Components from "unplugin-vue-components/vite"; import { VitePWA } from "vite-plugin-pwa"; // Tip ve yardımcı okuma fonksiyonu type PostEntry = { slug: string }; function safeReadJSON(p: string): T | null { try { return JSON.parse(fs.readFileSync(p, "utf-8")); } catch (e) { console.warn(`[ssg] '${p}' okunamadı: ${(e as Error).message}`); return null; } } // Compute all static + menu routes (TR/EN) for SSG & sitemap function computeRoutes(): string[] { // Base routes (TR and EN) const routes = new Set([ "/", "/menu/", "/legal/", "/en/", "/en/menu/", "/en/legal/", ]); return Array.from(routes); } export default defineConfig({ plugins: [ vue(), Sitemap({ hostname: "https://www.mucomutfak.com", outDir: process.env.BUILD_OUT_DIR || "dist", // Include ALL prerendered routes (from SSG) explicitly dynamicRoutes: computeRoutes(), generateRobotsTxt: true, robots: [{ userAgent: "*", allow: "/" }], // Produce a clean, human-readable XML and drop extra namespaces readable: true, xmlns: { news: false, xhtml: false, image: false, video: false }, }), tailwindcss(), Components({ dirs: ["src/components"], extensions: ["vue"], directoryAsNamespace: true, collapseSamePrefixes: true, globalNamespaces: ["global"], dts: "./components.d.ts", }), VitePWA({ registerType: "autoUpdate", includeAssets: [ "favicon.ico", "apple-touch-icon.png", "pwa-192x192.png", "pwa-512x512.png", "pwa-512x512-maskable.png", ], manifest: { name: "Müco Mutfak ve Kahve", short_name: "Müco", start_url: "/", scope: "/", display: "standalone", background_color: "#ffffff", theme_color: "#3FA0C7", icons: [ { src: "pwa-192x192.png", sizes: "192x192", type: "image/png" }, { src: "pwa-512x512.png", sizes: "512x512", type: "image/png" }, { src: "pwa-512x512-maskable.png", sizes: "512x512", type: "image/png", purpose: "maskable", }, ], screenshots: [ { src: "home-wide-1280x720.jpg", sizes: "1280x720", type: "image/jpeg", form_factor: "wide", }, { src: "home-narrow-750x1334.jpg", sizes: "750x1334", type: "image/jpeg", form_factor: "narrow", }, ], }, workbox: { cleanupOutdatedCaches: true, skipWaiting: true, clientsClaim: true, globPatterns: [ "**/*.{html,js,txt,xml,webmanifest,css,gif,ico,png,svg,jpg,jpeg,webp,ttf,woff2}", ], navigateFallback: null, runtimeCaching: [ { urlPattern: ({ request }) => request.mode === "navigate", handler: "NetworkFirst", options: { cacheName: "pages", networkTimeoutSeconds: 3, expiration: { maxEntries: 20, maxAgeSeconds: 60, }, }, }, { urlPattern: ({ request }) => ["image", "font"].includes(request.destination), handler: "StaleWhileRevalidate", options: { cacheName: "assets-v2", }, }, ], }, devOptions: { enabled: false, }, }), ], build: { chunkSizeWarningLimit: 1600, // Publish pipeline builds into a staging dir, then swaps it into dist outDir: process.env.BUILD_OUT_DIR || "dist", }, server: { host: true, port: 5173, proxy: { "/api": "http://localhost:3001", }, }, resolve: { alias: { "@": resolve(__dirname, "src") } }, ssgOptions: { script: "async", dirStyle: "nested", formatting: "minify", includedRoutes: computeRoutes, }, });