119 lines
4.2 KiB
TypeScript
119 lines
4.2 KiB
TypeScript
import { fileURLToPath, URL } from 'node:url'
|
|
|
|
import vue from '@vitejs/plugin-vue'
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import { defineConfig } from 'vite'
|
|
import { VitePWA } from 'vite-plugin-pwa'
|
|
|
|
type GetModuleInfo = (id: string) => { importers: readonly string[] } | null
|
|
|
|
/** pako / jszip 等 office 深依赖路径无特征,沿 importer 链上溯:
|
|
* 任一条链经过 @vue-office 即视为 office 生态模块 */
|
|
function fromVueOffice(id: string, getModuleInfo: GetModuleInfo, seen = new Set<string>()): boolean {
|
|
if (seen.has(id)) return false
|
|
seen.add(id)
|
|
const importers = getModuleInfo(id)?.importers ?? []
|
|
return importers.some(
|
|
(imp) => imp.includes('@vue-office') || fromVueOffice(imp, getModuleInfo, seen),
|
|
)
|
|
}
|
|
|
|
/** 大体积三方库归入命名 chunk:主入口显著瘦身,命名亦供 PWA 预缓存排除
|
|
* (这些块全部只被懒加载路径引用,拆出不影响首屏)。 */
|
|
function vendorChunk(id: string, getModuleInfo: GetModuleInfo): string | undefined {
|
|
if (!id.includes('node_modules')) return undefined
|
|
if (id.includes('@vue-office/pdf') || id.includes('pdfjs')) return 'office-pdf'
|
|
if (id.includes('@vue-office/excel') || id.includes('exceljs') || id.includes('xlsx'))
|
|
return 'office-excel'
|
|
if (id.includes('@vue-office/docx') || id.includes('docx')) return 'office-docx'
|
|
if (id.includes('echarts') || id.includes('zrender')) return 'echarts'
|
|
if (id.includes('naive-ui')) return 'naive-ui'
|
|
if (id.includes('highlight.js')) return 'hljs'
|
|
if (fromVueOffice(id, getModuleInfo)) return 'office-shared'
|
|
return undefined
|
|
}
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
vue(),
|
|
tailwindcss(),
|
|
VitePWA({
|
|
registerType: 'autoUpdate',
|
|
manifest: {
|
|
name: 'OCI Portal',
|
|
short_name: 'OCI Portal',
|
|
description: '自托管 OCI 多租户管理面板',
|
|
lang: 'zh-CN',
|
|
display: 'standalone',
|
|
theme_color: '#F5F4ED',
|
|
background_color: '#F5F4ED',
|
|
icons: [
|
|
{ src: '/pwa-192.png', sizes: '192x192', type: 'image/png' },
|
|
{ src: '/pwa-512.png', sizes: '512x512', type: 'image/png' },
|
|
{ src: '/pwa-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' },
|
|
],
|
|
},
|
|
workbox: {
|
|
globPatterns: ['**/*.{js,css,html,svg,png,woff2}'],
|
|
// 预缓存只收应用壳(入口/naive-ui/echarts/路由块);office 全家
|
|
// (pdf/excel/docx/shared,合计 ~6MB)安装时不下载,首次使用再入缓存
|
|
globIgnores: ['**/office-*.js'],
|
|
navigateFallback: 'index.html',
|
|
// API 与 AI 网关直通不落 SPA 壳也不缓存:运维数据必须实时
|
|
navigateFallbackDenylist: [/^\/api\//, /^\/ai\//],
|
|
runtimeCaching: [
|
|
{
|
|
// 未进预缓存的大块兜底:assets 带内容 hash 不可变,CacheFirst 恒安全
|
|
urlPattern: /\/assets\/.+\.js$/,
|
|
handler: 'CacheFirst',
|
|
options: {
|
|
cacheName: 'lazy-vendor',
|
|
expiration: { maxEntries: 30, maxAgeSeconds: 30 * 24 * 3600 },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
resolve: {
|
|
alias: {
|
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
},
|
|
},
|
|
// noVNC 1.7 使用 top-level await,需较新的构建目标(现代浏览器均支持);
|
|
// 生产构建与 dev 依赖预构建(esbuild)都要提高 target,否则 dev 会报同一错误
|
|
build: {
|
|
target: 'es2022',
|
|
// 现存最大懒块 office-pdf(pdfjs 全量)~2.8MB,均为按需加载不入首屏;
|
|
// 阈值取其上放宽,只为「新失控块」鸣笛而不对既有三方整包常鸣
|
|
chunkSizeWarningLimit: 2900,
|
|
rollupOptions: {
|
|
output: {
|
|
manualChunks: (id, { getModuleInfo }) => vendorChunk(id, getModuleInfo),
|
|
},
|
|
},
|
|
},
|
|
optimizeDeps: {
|
|
esbuildOptions: {
|
|
target: 'es2022',
|
|
},
|
|
},
|
|
server: {
|
|
port: 5173,
|
|
host: '127.0.0.1',
|
|
proxy: {
|
|
'/api': {
|
|
target: 'http://localhost:8080',
|
|
changeOrigin: true,
|
|
ws: true,
|
|
},
|
|
// 只代理网关端点 /ai/*;裸 '/ai' 前缀会误拦 /ai-gateway 页面路由
|
|
'^/ai/': {
|
|
target: 'http://localhost:8080',
|
|
changeOrigin: true,
|
|
ws: true,
|
|
},
|
|
},
|
|
},
|
|
})
|