渐进式Web
应用(PWA)
通过结合 Web
和移动应用的特点,为用户带来更加流畅和快速的体验。且PWA
支持离线访问能力(访问静态资源本地缓存),极大提高了用户交互的流畅性,降低非必要的网络依赖。尤其适合在手机端创建,本文推荐基于Vite
的基础上使用vite-plugin-pwa
实现A2HS(Add To Home Screen)
和workbox
离线缓存功能。
插件安装
$ npm i vite-plugin-pwa -D
配置
1、添加VitePWA插件
安装完成vite-plugin-pwa
插件后,我们只需要在vite.config.ts
文件中将其引入就完成基础的pwa
配置了。
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import { VitePWA } from 'vite-plugin-pwa'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),vueJsx(),VitePWA({registerType:"autoUpdate",devOptions: {enable: true,}}), // 添加vite-plugin-pwa插件支持],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}}
})
我当前安装的vite-plugin-pwa
版本为0.18.1
,具体支持的插件配置请参考对照版本。其比较重要的支持配置项如下:
mode
: 开发环境manifest/manifestFilename
:pwa
对应的应用配置strategies
:默认是generateSW
然后去配置workbox
; 如果想要更多自定义的设置,可以选择injectManifest
,那就对应配置injectManifest
workbox
:给generateSW
的配置,配置的所有workbox
,将交给workbox-build
插件中的generateSW
处理,生成最终sw.js
中的配置代码registerType
:注册类型配置,用于指定 PWA 的注册方式。这里设置为'autoUpdate'
,表示自动更新注册方式。
如下是VitePWAOptions
支持的所有配置项:
/*** Plugin options.*/
interface VitePWAOptions {mode?: 'development' | 'production';srcDir?: string; // 默认publicoutDir?: string; // 默认distfilename?: string; // 默认sw.jsmanifestFilename?: string; // 默认 manifest.webmanifeststrategies?: 'generateSW' | 'injectManifest'; // 默认 generateSWscope?: string; // 注册 service worker范围injectRegister: 'inline' | 'script' | 'script-defer' | 'auto' | null | false; // 默认autoregisterType?: 'prompt' | 'autoUpdate'; // 默认 promptminify: boolean; // 默认 truemanifest: Partial<ManifestOptions> | false; // manifest配置对象useCredentials?: boolean; // 是否添加crossorigin="use-credentials"到<link rel="manifest">,默认falseworkbox: Partial<GenerateSWOptions>; // google workbox配置对象,injectManifest: Partial<CustomInjectManifestOptions>;base?: string; // 覆盖vite的base配置,仅仅对于pwaincludeAssets: string | string[] | undefined;includeManifestIcons: boolean;disable: boolean; // 是否在“生成”上禁用service worker注册和生成?默认falseintegration?: PWAIntegration; // Vite PWA集成devOptions?: DevOptions; // 开发环境配置selfDestroying?: boolean; // 是否销毁service worker,默认falsebuildBase?: string; // 构建配置,默认使用vite.config.ts中的配置
}
其支持的
2、添加mainfest配置
manifest
用于配置pwa应用的基础信息:如名称、图标、主题色等,也可以选择创建manifest
文件来配置应用信息:
name
: 应用名icons
: 应用图标description
:应用描述信息short_name
: 应用简称theme_color
: 样式主题色,默认#42b883background_color
:背景色,默认#ffflang
:语言,默认enshortcuts
:快捷方式的配置信息
import { defineConfig } from 'vite'
...
import { VitePWA } from 'vite-plugin-pwa'// https://vitejs.dev/config/
export default defineConfig({plugins: [
......VitePWA({manifest: {name: 'Vite PWA App',short_name: 'v-pwa',description: '一个Vite PWA测试APP',theme_color: '#fafafa',icons: [{src: '/icons/icon-192x192.png',sizes: '192x192',type:'image/png',},{src: '/icons/icon-512x512.png',sizes: '512x512',type: 'image/png',}],shortcuts: [ // 配置快捷方式,指定打开页面地址{name: "打开首页", // 快捷方式名称short_name: "首页", // 快捷方式简称description: "打开首页", // 快捷方式描述url: "/", // 快捷方式链接地址icons: [{ src: "/favicon.ico", sizes: "36x36" }], // 快捷方式图标配置},]},})],
......
})
3、配置workbox
workbox
用于帮助我们处理资源的缓存更新,我们只需要配置一个workbox
配置即可按照规则对资源进行本地缓存、以及运行时缓存等操作。
import { defineConfig } from 'vite'
...
import { VitePWA } from 'vite-plugin-pwa'const getCache = ({ name, pattern }: any) => ({urlPattern: pattern,handler: 'CacheFirst' as const,options: {cacheName: name,expiration: {maxEntries: 500,maxAgeSeconds: 60 * 60 * 24 * 365 * 2 // 2 years},cacheableResponse: {statuses: [200]}}
})// https://vitejs.dev/config/
export default defineConfig({plugins: [
......VitePWA({workbox: {globPatterns: ['**/*.{js,css,html,ico,png,jpg,svg}'], //缓存相关静态资源runtimeCaching: [// 配置自定义运行时缓存getCache({pattern: /^https:\/\/enjoytoday.cn\/wp-uploads/, name: 'local-upload'}),getCache({pattern: /^https:\/\/app.enjoytoday.cn/,name: 'webapp'})]}})],
......
})
4、完整配置
如下,给出有关VitePWA
插件在vite.config.ts
中的完成配置信息。
import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import { VitePWA } from 'vite-plugin-pwa'const getCache = ({ name, pattern }: any) => ({urlPattern: pattern,handler: 'CacheFirst' as const,options: {cacheName: name,expiration: {maxEntries: 500,maxAgeSeconds: 60 * 60 * 24 * 365 * 2 // 2 years},cacheableResponse: {statuses: [200]}}
})// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),vueJsx(),VitePWA({manifest: {name: 'Vite PWA App',short_name: 'v-pwa',description: '一个Vite PWA测试APP',theme_color: '#fafafa',icons: [{src: '/icons/icon.png',sizes: '192x192',type: 'image/png'},{src: '/icons/icon.png',sizes: '512x512',type: 'image/png'}],shortcuts: [{name: '打开首页', // 快捷方式名称short_name: '首页', // 快捷方式简称description: '打开首页', // 快捷方式描述url: '/', // 快捷方式链接地址icons: [{ src: '/favicon.ico', sizes: '36x36' }] // 快捷方式图标配置}]},registerType: "autoUpdate", // 注册类型配置devOptions: {enabled: true, // 开发选项配置,启用插件},workbox: {globPatterns: ['**/*.{js,css,html,ico,png,jpg,svg}'], //缓存相关静态资源runtimeCaching: [// 配置自定义运行时缓存getCache({pattern: /^https:\/\/enjoytoday.cn\/wp-uploads/, name: 'local-upload'}),getCache({pattern: /^https:\/\/app.enjoytoday.cn/,name: 'webapp'})]}})],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}}
})
应用安装
通过上述配置我们添加了一个离线引用,当浏览器支持A2HS
的情况下,我们可以通过代码对其进行一个安装并添加桌面上,以便于我们能过快速抵达应用。如下介绍如何安装应用。
1、配置应用安装触发
希望安装应用到桌面需要我们预先配置应用安装触发,首先需要在入口处添加监听,然后通过我们的交互方式进行应用的安装操作(或者通过工具栏的图标主动安装)。
// 在主入口监听PWA注册事件,如main.ts
window.addEventListener('beforeinstallprompt', (e) => {e.preventDefault()window.deferredPrompt = e
})// 在具体页面添加安装,如App.vue
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'// 若浏览器支持,则这里会出发安装操作
const openAddFlow = () => {try {window.deferredPrompt.prompt()window.deferredPrompt.userChoice.then((choiceResult) => {if (choiceResult.outcome === 'accepted') {// showAddToDesktop.value = falselocalStorage.setItem('addDesktop', true)} else {console.log('User dismissed the A2HS prompt')}window.deferredPrompt = null})} catch {//}
}
</script><template><header><img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" @click="openAddFlow"/><div class="wrapper"><HelloWorld msg="You did it!" /><nav><RouterLink to="/">Home</RouterLink><RouterLink to="/about">About</RouterLink></nav></div></header><RouterView />
</template>
2、应用安装
3、缓存
我并未将其部署线上地址,也没有添加配置的运行时请求数据,所以这里不会展示配置的运行时缓存信息。