Files
ogame-vue-ts/vite.config.ts
coolxitech 1aac97dfee perf(workbox): 优化资源缓存匹配模式
- 修改 globPatterns 配置以递归匹配所有静态资源
- 确保深层嵌套的文档目录资源被正确缓存
- 提升离线访问性能和资源加载速度
2025-12-15 22:02:56 +08:00

122 lines
4.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { VitePWA } from 'vite-plugin-pwa'
import pkg from './package.json'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
export default defineConfig(async () => {
const plugins = [
vue(),
tailwindcss(),
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: pkg.name,
short_name: pkg.title,
description: '一款现代化 OGame 太空策略游戏',
theme_color: '#000000',
background_color: '#000000',
display: 'fullscreen',
orientation: 'any',
icons: [
{
src: 'logo.svg',
sizes: 'any',
type: 'image/svg+xml',
purpose: 'any',
},
],
},
workbox: {
// 关键:确保缓存了 docs 目录下所有的 JS, CSS, HTML 和 媒体文件
globPatterns: ['**/*.{js,css,html,ico,png,svg,mp3,wav,json}'],
// 如果你的游戏资源(如音效或贴图)较大,请根据需要调大这个阈值(默认 2MB
// 这里设置为 5MB
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
// 离线策略优化:对于游戏,我们希望即使在离线状态下,
// 所有的资源都能立刻从缓存加载,而不是去请求网络
runtimeCaching: [
{
urlPattern: ({ request }) => request.destination === 'image' || request.destination === 'audio',
handler: 'CacheFirst', // 优先使用缓存
options: {
cacheName: 'game-assets',
expiration: {
maxEntries: 100,
maxAgeSeconds: 30 * 24 * 60 * 60, // 缓存 30 天
},
},
},
],
}
})
];
// 只在 ELECTRON_BUILD 环境变量存在时才加载 Electron 插件
if (process.env.ELECTRON_BUILD) {
// @ts-ignore - 动态导入 electron 插件
const { default: electron } = await import('vite-plugin-electron/simple')
const electronPlugins = await electron({
main: {
entry: 'electron/main.ts',
},
renderer: {},
})
plugins.push(...electronPlugins)
}
return {
base: './',
build: {
outDir: 'docs',
sourcemap: false,
cssCodeSplit: true,
chunkSizeWarningLimit: 1000,
rollupOptions: {
output: {
manualChunks(id: string) {
// Vue 核心框架
if (id.includes('node_modules/vue/') || id.includes('node_modules/@vue/')) return 'vendor-vue-core'
// Vue 生态
if (id.includes('node_modules/vue-router')) return 'vendor-vue-router'
if (id.includes('node_modules/pinia')) return 'vendor-pinia'
// UI 组件库
if (id.includes('node_modules/reka-ui')) return 'vendor-reka-ui'
if (id.includes('node_modules/@vueuse/core')) return 'vendor-vueuse'
if (id.includes('node_modules/lucide-vue-next')) return 'vendor-icons'
// 工具库
if (id.includes('node_modules/crypto-js')) return 'vendor-crypto'
if (id.includes('node_modules/file-saver')) return 'vendor-utils'
if (id.includes('node_modules/clsx') || id.includes('node_modules/tailwind-merge')) return 'vendor-utils'
// Tailwind CSS
if (id.includes('node_modules/@tailwindcss') || id.includes('node_modules/tailwindcss')) return 'vendor-tailwind'
// 游戏逻辑模块
if (id.includes('/src/logic/')) return 'game-logic'
// 配置和类型
if (id.includes('/src/config/') || id.includes('/src/types/')) return 'game-config'
// 本地化
if (id.includes('/src/locales/')) return 'game-i18n'
// 其他 node_modules 依赖
if (id.includes('node_modules/')) return 'vendor-others'
},
// 优化输出文件名
chunkFileNames: 'assets/[name]-[hash].js',
entryFileNames: 'assets/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash].[ext]'
}
}
},
plugins,
resolve: { alias: { '@': path.resolve(__dirname, './src') } },
// 优化依赖预构建
optimizeDeps: { include: ['vue', 'vue-router', 'pinia', 'reka-ui', '@vueuse/core', 'lucide-vue-next', 'crypto-js', 'file-saver'] }
}
})