Files
SearcjGal-frontend/vite.config.ts
AdingApkgg 92e0be566f refactor: update PWA registration and StatsCorner component for improved functionality
- Changed PWA registration type to 'autoUpdate' for immediate updates upon new version availability.
- Removed obsolete busuanzi elements and replaced the data fetching method with a new API call for site statistics.
- Simplified the UpdateToast component to trigger immediate updates without countdown, enhancing user experience.
2026-02-01 13:58:23 +08:00

225 lines
6.1 KiB
TypeScript
Raw 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 { fileURLToPath, URL } from 'node:url';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
server: {
host: "localhost",
port: 5500,
// 预热常用文件
warmup: {
clientFiles: [
'./src/App.vue',
'./src/components/*.vue',
'./src/stores/*.ts',
],
},
},
plugins: [
vue({
script: {
// 响应式语法糖(如需要可启用)
defineModel: true,
},
}),
tailwindcss(),
// PWA 配置
VitePWA({
registerType: 'autoUpdate', // 收到新版本立即更新
includeAssets: ['logo.svg', 'robots.txt'],
manifest: {
name: 'SearchGal - Galgame 聚合搜索',
short_name: 'SearchGal',
description: '多平台 Galgame 资源聚合搜索引擎',
start_url: '/',
display: 'standalone',
background_color: '#fff5fa',
theme_color: '#ff1493',
orientation: 'portrait-primary',
scope: '/',
lang: 'zh-CN',
dir: 'ltr',
icons: [
{
src: '/logo.svg',
sizes: 'any',
type: 'image/svg+xml',
purpose: 'any maskable',
},
],
categories: ['entertainment', 'games', 'utilities'],
shortcuts: [
{
name: '游戏模式搜索',
short_name: '游戏搜索',
description: '快速搜索游戏资源',
url: '/?mode=game',
icons: [{ src: '/logo.svg', sizes: 'any' }],
},
{
name: '补丁模式搜索',
short_name: '补丁搜索',
description: '搜索游戏补丁资源',
url: '/?mode=patch',
icons: [{ src: '/logo.svg', sizes: 'any' }],
},
],
},
workbox: {
// 预缓存所有构建产物
globPatterns: ['**/*.{js,css,html,svg,png,ico,woff2}'],
// 运行时缓存策略
runtimeCaching: [
{
// 字体文件 - 缓存优先
urlPattern: /^https:\/\/fonts\.(googleapis|gstatic)\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 年
},
},
},
{
// 图片 API - 网络优先
urlPattern: /^https:\/\/api\.illlights\.com\/.*/i,
handler: 'NetworkFirst',
options: {
cacheName: 'background-images',
expiration: {
maxEntries: 20,
maxAgeSeconds: 60 * 60 * 24, // 1 天
},
},
},
{
// VNDB API - 网络优先
urlPattern: /^https:\/\/api\.vndb\.org\/.*/i,
handler: 'NetworkFirst',
options: {
cacheName: 'vndb-api',
expiration: {
maxEntries: 50,
maxAgeSeconds: 60 * 30, // 30 分钟
},
},
},
],
// 离线时的导航回退
navigateFallback: null, // 不使用默认回退,由 offlineFallback 处理
},
// 开发环境启用 SW便于测试
devOptions: {
enabled: false, // 开发时禁用,避免干扰
},
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
// 构建优化
build: {
// 使用现代浏览器目标
target: 'esnext',
// 启用 CSS 代码分割
cssCodeSplit: true,
// 压缩选项
minify: 'esbuild',
// 源码映射(生产环境关闭)
sourcemap: false,
// Chunk 大小警告阈值 (KB)
chunkSizeWarningLimit: 600,
// Rollup 配置
rollupOptions: {
output: {
// 资源文件名
assetFileNames: (assetInfo) => {
const name = assetInfo.name || '';
// 字体文件
if (/\.(woff2?|eot|ttf|otf)$/i.test(name)) {
return 'fonts/[name]-[hash][extname]';
}
// 图片文件
if (/\.(png|jpe?g|gif|svg|webp|ico)$/i.test(name)) {
return 'images/[name]-[hash][extname]';
}
// CSS 文件
if (/\.css$/i.test(name)) {
return 'css/[name]-[hash][extname]';
}
return 'assets/[name]-[hash][extname]';
},
// JS 入口文件名
entryFileNames: 'js/[name]-[hash].js',
// JS Chunk 文件名
chunkFileNames: 'js/[name]-[hash].js',
// 手动分包
manualChunks: (id) => {
if (id.includes('node_modules')) {
// Vue 核心
if (id.includes('/vue/') || id.includes('/@vue/')) {
return 'vue-core';
}
// Pinia 状态管理
if (id.includes('/pinia/')) {
return 'pinia';
}
// UI 库
if (id.includes('/lucide-vue-next/')) {
return 'ui-libs';
}
// Artalk 评论
if (id.includes('/artalk/')) {
return 'artalk';
}
// 代码编辑器
if (id.includes('/prismjs/') || id.includes('/vue-prism-editor/')) {
return 'editor';
}
// Fancybox
if (id.includes('/@fancyapps/')) {
return 'fancybox';
}
// 其他第三方库
return 'vendor';
}
},
},
},
},
// 依赖优化
optimizeDeps: {
// 预构建的依赖
include: [
'vue',
'pinia',
'lucide-vue-next',
],
// 排除不需要预构建的
exclude: ['artalk'],
},
// esbuild 配置
esbuild: {
// 生产环境移除 console 和 debugger
drop: process.env.NODE_ENV === 'production' ? ['console', 'debugger'] : [],
// 压缩选项
legalComments: 'none',
},
// CSS 配置
css: {
devSourcemap: true,
},
});