diff --git a/packages/client/app/assets/koishi-192x192.png b/packages/client/app/assets/koishi-192x192.png new file mode 100644 index 00000000..af26ea0b Binary files /dev/null and b/packages/client/app/assets/koishi-192x192.png differ diff --git a/packages/client/app/assets/koishi-512x512.png b/packages/client/app/assets/koishi-512x512.png new file mode 100644 index 00000000..557e9205 Binary files /dev/null and b/packages/client/app/assets/koishi-512x512.png differ diff --git a/packages/client/app/sw.ts b/packages/client/app/sw.ts new file mode 100644 index 00000000..51550236 --- /dev/null +++ b/packages/client/app/sw.ts @@ -0,0 +1,29 @@ +// https://vite-pwa-org.netlify.app/guide/inject-manifest.html +import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching' + +declare let self: ServiceWorkerGlobalScope + +self.addEventListener('install', () => { + self.skipWaiting() +}) + +self.addEventListener('activate', () => { + self.clients.claim() +}) + +self.addEventListener('fetch', (event) => { + if (/(.js|.mjs|.css)$/.test(event.request.url)) { + event.respondWith(fetch(event.request)) + } else { + event.respondWith(fetch(event.request, { cache: 'no-store' })) + } +}) + +// Cleanup Outdated Caches +cleanupOutdatedCaches() +precacheAndRoute(self.__WB_MANIFEST) + +// Prompt For Update Behavior +self.addEventListener('message', (event) => { + if (event.data && event.data.type === 'SKIP_WAITING') self.skipWaiting() +}) diff --git a/packages/client/app/tsconfig.json b/packages/client/app/tsconfig.json index 44f19c0b..629d7f6d 100644 --- a/packages/client/app/tsconfig.json +++ b/packages/client/app/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../tsconfig.client", "compilerOptions": { "rootDir": ".", + "lib": ["ESNext", "DOM", "WebWorker"] }, "include": [ ".", diff --git a/packages/client/build/client.ts b/packages/client/build/client.ts index e1d5e874..66313f21 100644 --- a/packages/client/build/client.ts +++ b/packages/client/build/client.ts @@ -4,6 +4,7 @@ import { resolve } from 'path' import * as vite from 'vite' import vue from '@vitejs/plugin-vue' import yaml from '@maikolib/vite-plugin-yaml' +import { VitePWA as pwa } from 'vite-plugin-pwa' function findModulePath(id: string) { const path = require.resolve(id).replace(/\\/g, '/') @@ -18,6 +19,7 @@ export async function build(root: string, config: vite.UserConfig = {}, isClient const { rollupOptions = {} } = config.build || {} return await vite.build({ root, + publicDir: 'assets', build: { outDir: cwd + '/plugins/console/dist', emptyOutDir: true, @@ -46,6 +48,7 @@ export async function build(root: string, config: vite.UserConfig = {}, isClient plugins: [ vue(), yaml(), + config.plugins, ], resolve: { alias: { @@ -62,7 +65,34 @@ export async function build(root: string, config: vite.UserConfig = {}, isClient export default async function () { // build for console main - const { output } = await build(cwd + '/packages/client/app') + const { output } = await build(cwd + '/packages/client/app', { + plugins: [ + pwa({ + strategies: 'injectManifest', + srcDir: '.', + filename: 'sw.ts', + injectRegister: 'inline', + manifest: { + name: 'Koishi', + short_name: 'Koishi', + description: 'Koishi 控制台', + theme_color: '#ffffff', + icons: [ + { + src: 'koishi-192x192.png', + sizes: '192x192', + type: 'image/png', + }, + { + src: 'koishi-512x512.png', + sizes: '512x512', + type: 'image/png', + }, + ], + }, + }), + ], + }) await Promise.all([ copyFile(findModulePath('vue') + '/dist/vue.runtime.esm-browser.prod.js', dist + '/vue.js'), diff --git a/packages/client/package.json b/packages/client/package.json index 6957f44d..fa41a541 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -47,6 +47,7 @@ "ns-require": "^1.1.4", "sass": "^1.62.1", "vite": "^4.3.5", + "vite-plugin-pwa": "^0.14.7", "vue": "^3.3.2", "vue-i18n": "^9.2.2", "vue-router": "^4.2.0"