Files

152 lines
4.9 KiB
TypeScript
Raw Permalink Normal View History

import { fileURLToPath, URL } from 'node:url'
import * as fs from 'fs'
import * as path from 'path'
import * as dotenv from 'dotenv'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import vueDevTools from 'vite-plugin-vue-devtools'
import { VitePWA } from 'vite-plugin-pwa'
import { THEME_COLORS } from './src/config/themeColors'
// https://vite.dev/config/
export default defineConfig(({ command, mode }) => {
// Load env file based on `mode` in the current working directory.
// When mode is 'prod' or 'dev', load .env.prod or .env.dev respectively
const envDir = process.cwd()
if (mode === 'prod' || mode === 'production') {
// Manually load .env.prod for production builds. Plain `vite build`
// (mode 'production', used by Dockerfile.frontend.prod) must see the
// VITE_FIREBASE_* values too: src/sw.ts inlines them at build time, and
// without them the service worker ships with push silently disabled.
const envPath = path.resolve(envDir, '.env.prod')
if (fs.existsSync(envPath)) {
const envConfig = dotenv.parse(fs.readFileSync(envPath))
// Merge with process.env
for (const key in envConfig) {
if (!process.env[key]) {
process.env[key] = envConfig[key]
}
}
}
} else if (mode === 'dev') {
// Manually load .env.dev for development builds
const envPath = path.resolve(envDir, '.env.dev')
if (fs.existsSync(envPath)) {
const envConfig = dotenv.parse(fs.readFileSync(envPath))
// Merge with process.env
for (const key in envConfig) {
if (!process.env[key]) {
process.env[key] = envConfig[key]
}
}
}
}
// Also load standard Vite env files
const env = loadEnv(mode, process.cwd(), '')
if (command === 'build' && !(process.env.VITE_FIREBASE_API_KEY || env.VITE_FIREBASE_API_KEY)) {
console.warn(
'\n[pwa] VITE_FIREBASE_API_KEY is not set for this build — the service worker ' +
'will ship WITHOUT background push support (foreground notifications still work ' +
'via runtime config.js). Provide .env/.env.prod with VITE_FIREBASE_* to enable it.\n'
)
}
return {
plugins: [
vue({
template: {
compilerOptions: {
// Treat all tags starting with 's-' as custom elements (Polaris web components)
isCustomElement: (tag) => tag.startsWith('s-')
}
}
}),
vueJsx(),
vueDevTools(),
// Plugin to inject environment variables into HTML
{
name: 'html-transform',
transformIndexHtml(html) {
return html.replace(
/<%= VITE_SHOPIFY_API_KEY %>/g,
process.env.VITE_SHOPIFY_API_KEY || env.VITE_SHOPIFY_API_KEY || ''
)
}
},
VitePWA({
strategies: 'injectManifest',
srcDir: 'src',
filename: 'sw.ts',
// Registration is manual (src/pwa/register.ts) so the Shopify App Bridge
// script stays the first script tag and embedded contexts never register.
injectRegister: false,
manifest: {
name: 'ReplyPier',
short_name: 'ReplyPier',
description: 'Agent console for ReplyPier — handle customer chats anywhere.',
start_url: '/',
scope: '/',
display: 'standalone',
background_color: THEME_COLORS.light,
theme_color: THEME_COLORS.light,
icons: [
{ src: '/pwa-192x192.png', sizes: '192x192', type: 'image/png' },
{ src: '/pwa-512x512.png', sizes: '512x512', type: 'image/png' },
{ src: '/pwa-maskable-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' },
],
},
injectManifest: {
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
// config.js is runtime-substituted per environment (docker-entrypoint)
// and must never be precached; webclient isn't the agent app.
globIgnores: ['config.js', 'config.dev.js', 'webclient/**'],
},
devOptions: {
enabled: false,
},
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
server: {
headers: {
'Service-Worker-Allowed': '/',
},
// Allow ngrok and other tunnel services for Shopify embedded app development
allowedHosts: [
'localhost',
'.ngrok.app',
'.ngrok.io',
'frontendchat.ngrok.app',
'.replypier.site',
],
},
publicDir: 'public',
build: {
outDir: 'dist',
assetsDir: 'assets',
chunkSizeWarningLimit: 600,
rollupOptions: {
input: {
main: './index.html',
},
output: {
manualChunks: {
'vendor-vue': ['vue', 'vue-router', 'pinia'],
'vendor-ui': ['vue3-apexcharts'],
'vendor-utils': ['axios', 'marked'],
'vendor-firebase': ['firebase/app', 'firebase/messaging', 'firebase/auth'],
},
},
},
},
}
})