import {reactRouter} from '@react-router/dev/vite'; import tailwindcss from '@tailwindcss/vite'; import path from 'path'; import {defineConfig} from 'vite'; export default defineConfig({ // @vitejs/plugin-react 를 따로 넣지 않는다 — reactRouter() 가 안에서 켠다. plugins: [reactRouter(), tailwindcss()], resolve: { alias: { '@': path.resolve(__dirname, 'src'), // css 는 더 구체적인 별칭이 먼저 와야 한다 — 아래 '@o2o/shared' 접두어 규칙이 먼저 걸리면 shared/src/tokens.css(없는 경로)로 떨어진다. '@o2o/shared/tokens.css': path.resolve(__dirname, '../shared/src/styles/tokens.css'), '@o2o/shared/base.css': path.resolve(__dirname, '../shared/src/styles/base.css'), // 워크스페이스 심볼릭 링크를 타지 않고 소스를 직접 가리킨다 — shared 를 고치면 빌드 없이 HMR 이 바로 돈다. '@o2o/shared': path.resolve(__dirname, '../shared/src'), // 발행본 렌더러를 **그대로** 쓴다. '@site': path.resolve(__dirname, '../site/src'), }, }, // 산출물이 `dist/` 가 아니라 `build/client/` 로 나간다(프레임워크 모드 기본값). build: { // 발행본과 **같은 오리진**을 쓰므로 `/assets/` 를 서로 뺏는다. assetsDir: 'builder-assets', }, server: { // Vite 6 는 모르는 Host 헤더를 403 "Blocked request" 로 막는다(DNS rebinding 방어). allowedHosts: [process.env.VITE_PUBLISH_HOST ?? 'web4ai.o2osolution.ai'], // 발행 사이트는 별도 정적 서버(:3001)가 만들고 서빙하지만, 사용자는 admin 과 같은 origin(:3000)의 `/s/` 로 접근한다. proxy: { // `'/s'`로 두면 Vite의 `/src/app/main.tsx`까지 매칭되어 에디터가 흰 화면이 된다. '^/s(?:/|$)': { target: 'http://127.0.0.1:3001', changeOrigin: true, }, /** 발행본의 JS·CSS 번들. */ '^/assets/': { target: 'http://127.0.0.1:3001', changeOrigin: true, }, }, // 도커(Mac) 바인드마운트는 네이티브 inotify 가 컨테이너로 전파되지 않아 파일 감시를 polling 으로 해야 호스트 변경이 감지된다. watch: {usePolling: true, interval: 300}, }, });