+78
-1
@@ -3,9 +3,78 @@ 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()],
|
||||
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)),
|
||||
@@ -15,6 +84,14 @@ export default defineConfig({
|
||||
// 生产构建与 dev 依赖预构建(esbuild)都要提高 target,否则 dev 会报同一错误
|
||||
build: {
|
||||
target: 'es2022',
|
||||
// 现存最大懒块 office-pdf(pdfjs 全量)~2.8MB,均为按需加载不入首屏;
|
||||
// 阈值取其上放宽,只为「新失控块」鸣笛而不对既有三方整包常鸣
|
||||
chunkSizeWarningLimit: 2900,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: (id, { getModuleInfo }) => vendorChunk(id, getModuleInfo),
|
||||
},
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
esbuildOptions: {
|
||||
|
||||
Reference in New Issue
Block a user