import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { cpSync, mkdirSync } from 'node:fs' import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' const siteRoot = dirname(fileURLToPath(import.meta.url)) const safePublicFiles = [ '404.html', '.well-known/assetlinks.json', 'accept-invite.css', 'accept-invite.js', 'accept-invite/index.html', 'download.html', 'favicon.svg', 'legal.css', 'privacy/index.html', 'terms/index.html', 'delete-account/index.html', // 검색·공유용 자산 (scripts/render-brand-assets.mjs 가 만든다) 'site.webmanifest', // IndexNow 소유 확인 키(공개 값). scripts/ci/ping-indexnow.mjs 가 같은 파일을 쓴다. '5d886cca4138946b8488203724b2f53d.txt', 'icons', 'og', ] export default defineConfig({ // Installers ship only through the Forgejo feed, never from this site. Only this // non-binary allowlist can reach dist, so a stray local `public/releases` copy // (git-ignored) can never be deployed. publicDir: false, plugins: [ react(), (() => { // 서버용 빌드(`vite build --ssr`, dist-ssr)에서는 복사하지 않는다 — 브라우저 빌드가 이미 복사했다. let isSsrBuild = false return { name: 'copy-safe-public-files', configResolved(config: { build: { ssr: unknown } }) { isSsrBuild = Boolean(config.build.ssr) }, closeBundle() { if (isSsrBuild) return for (const relativePath of safePublicFiles) { const destination = join(siteRoot, 'dist', relativePath) mkdirSync(dirname(destination), { recursive: true }) cpSync(join(siteRoot, 'public', relativePath), destination, { errorOnExist: true, recursive: true }) } }, } })(), ], // 언어별 페이지(/en/ 등)에서도 자산을 찾도록 절대 경로를 쓴다. base: '/', })