Files
apparel-designer/client/vite.config.js
Khalid A 66bd69efe7 Consolidate to single server with unified package.json
- Merge client and server dependencies into root package.json
- Remove separate client/package.json and server/package.json
- Update server/index.js to serve built client static files
- Simplify Dockerfile to single build + production stage
- Update dev scripts for unified development workflow
- SPA routing serves index.html for non-API routes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 22:24:20 -05:00

161 lines
4.3 KiB
JavaScript

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
react(),
VitePWA({
registerType: 'prompt',
includeAssets: ['favicon.ico', 'pwa-192x192.svg', 'pwa-512x512.svg'],
manifest: {
name: 'Apparel Designer',
short_name: 'ApparelDesigner',
description: 'T-shirt customization editor',
theme_color: '#38bdf8',
background_color: '#ffffff',
display: 'standalone',
orientation: 'any',
scope: '/',
start_url: '/',
icons: [
{
src: 'pwa-192x192.svg',
sizes: '192x192',
type: 'image/svg+xml',
},
{
src: 'pwa-512x512.svg',
sizes: '512x512',
type: 'image/svg+xml',
},
{
src: 'pwa-512x512.svg',
sizes: '512x512',
type: 'image/svg+xml',
purpose: 'any maskable',
},
],
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
runtimeCaching: [
{
urlPattern: /^https:\/\/cdn\.huggingface\.co\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'transformers-models',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 30,
},
cacheableResponse: {
statuses: [0, 200],
},
},
},
// HuggingFace LFS (Large File Storage) for model weights
{
urlPattern: /^https:\/\/cdn-lfs\.huggingface\.co\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'transformers-lfs',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 30,
},
cacheableResponse: {
statuses: [0, 200],
},
},
},
{
urlPattern: /^\/api\/uploads\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'uploaded-images',
expiration: {
maxEntries: 50,
maxAgeSeconds: 60 * 60 * 24 * 7,
},
},
},
// Template data caching
{
urlPattern: /^\/api\/templates\/.*/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'template-data',
expiration: {
maxEntries: 20,
maxAgeSeconds: 60 * 60 * 24 * 7,
},
cacheableResponse: {
statuses: [0, 200],
},
},
},
// API responses caching
{
urlPattern: /^\/api\/.*/i,
handler: 'NetworkFirst',
options: {
cacheName: 'api-responses',
expiration: {
maxEntries: 50,
maxAgeSeconds: 300,
},
cacheableResponse: {
statuses: [0, 200],
},
networkTimeoutSeconds: 3,
},
},
{
urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'google-fonts',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365,
},
},
},
{
urlPattern: /^https:\/\/fonts\.gstatic\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'gstatic-fonts',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365,
},
},
},
],
},
}),
],
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:3001',
changeOrigin: true,
},
'/uploads': {
target: 'http://localhost:3001',
changeOrigin: true,
},
'/exports': {
target: 'http://localhost:3001',
changeOrigin: true,
},
},
},
build: {
outDir: 'dist',
},
});