Сделал возможной работу офлайн #5

This commit is contained in:
Ilia Miheev
2026-08-01 22:37:17 +03:00
parent fac7574433
commit 7a54ac0c18
6 changed files with 4776 additions and 9 deletions
+12
View File
@@ -32,3 +32,15 @@ npm run lint
### Customization ### Customization
Copy `.env.example` to `.env` and set branding / theme variables. Copy `.env.example` to `.env` and set branding / theme variables.
`npm run serve` / `npm run build` regenerates `public/config.js` automatically. `npm run serve` / `npm run build` regenerates `public/config.js` automatically.
### Offline (PWA)
Production build registers a service worker and caches the app shell.
After opening the site once online:
```
npm run build
npm run preview
```
you can reload without network — generators keep working.
`config.js` uses NetworkFirst (fresh when online, cached when offline).
+3
View File
@@ -4,7 +4,10 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" /> <meta name="viewport" content="width=device-width,initial-scale=1.0" />
<meta name="theme-color" content="#1a1815" />
<meta name="description" content="Random value generator" />
<link rel="icon" href="/logo.png" /> <link rel="icon" href="/logo.png" />
<link rel="apple-touch-icon" href="/logo.png" />
<title>irandom</title> <title>irandom</title>
<script src="/config.js"></script> <script src="/config.js"></script>
</head> </head>
+4697 -7
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -25,7 +25,8 @@
"eslint": "^8.57.1", "eslint": "^8.57.1",
"eslint-plugin-vue": "^9.32.0", "eslint-plugin-vue": "^9.32.0",
"sass": "^1.83.0", "sass": "^1.83.0",
"vite": "^6.0.7" "vite": "^6.0.7",
"vite-plugin-pwa": "^1.3.0"
}, },
"eslintConfig": { "eslintConfig": {
"root": true, "root": true,
+3
View File
@@ -7,6 +7,9 @@ import router from './router'
import i18n from './i18n' import i18n from './i18n'
import { getAppConfig } from './config/appConfig' import { getAppConfig } from './config/appConfig'
import { applyTheme } from './config/applyTheme' import { applyTheme } from './config/applyTheme'
import { registerSW } from 'virtual:pwa-register'
registerSW({ immediate: true })
const appConfig = getAppConfig() const appConfig = getAppConfig()
applyTheme(appConfig) applyTheme(appConfig)
+59 -1
View File
@@ -1,12 +1,70 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
import path from 'node:path' import path from 'node:path'
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url)) const __dirname = path.dirname(fileURLToPath(import.meta.url))
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [
vue(),
VitePWA({
registerType: 'autoUpdate',
includeAssets: ['logo.png', 'favicon.ico'],
manifest: {
name: 'irandom',
short_name: 'irandom',
description: 'Random value generator',
theme_color: '#1a1815',
background_color: '#1a1815',
display: 'standalone',
orientation: 'any',
start_url: '/',
scope: '/',
lang: 'ru',
icons: [
{
src: '/logo.png',
sizes: '192x192',
type: 'image/png',
purpose: 'any'
},
{
src: '/logo.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable'
}
]
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2,webmanifest}'],
navigateFallback: '/index.html',
navigateFallbackDenylist: [/^\/api/],
runtimeCaching: [
{
urlPattern: ({ url }) => url.pathname.endsWith('/config.js'),
handler: 'NetworkFirst',
options: {
cacheName: 'irandom-config',
networkTimeoutSeconds: 3,
expiration: {
maxEntries: 1,
maxAgeSeconds: 60 * 60 * 24 * 30
},
cacheableResponse: {
statuses: [0, 200]
}
}
}
]
},
devOptions: {
enabled: false
}
})
],
resolve: { resolve: {
alias: { alias: {
'@': path.resolve(__dirname, 'src') '@': path.resolve(__dirname, 'src')