vite-plugin-pwa 离线安装Vite应用

本篇文章首发于我的个人博客站,点击查看原文,在其基础上进行了部分细节的修改。

渐进式Web应用(PWA)通过结合 Web 和移动应用的特点,为用户带来更加流畅和快速的体验。且PWA支持离线访问能力(访问静态资源本地缓存),极大提高了用户交互的流畅性,降低非必要的网络依赖。尤其适合在手机端创建,本文推荐基于Vite的基础上使用vite-plugin-pwa实现A2HS(Add To Home Screen)workbox离线缓存功能。

插件安装

可以根据使用工具习惯选择适当的依赖库管理工具,安装命令如下:

ruby 复制代码
$ npm i vite-plugin-pwa -D #或
$ yarn add vite-plugin-pwa -D # 或
$ pnpm i vite-plugin-pwa -D 

插件配置

安装完成vite-plugin-pwa插件后,我们只需要在vite.config.ts文件中将其引入就完成基础的pwa配置了。

javascript 复制代码
/ 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/manifestFilenamepwa对应的应用配置
  • strategies:默认是generateSW然后去配置workbox; 如果想要更多自定义的设置,可以选择injectManifest,那就对应配置injectManifest
  • workbox:给generateSW的配置,配置的所有workbox,将交给workbox-build插件中的generateSW处理,生成最终sw.js中的配置代码
  • registerType:注册类型配置,用于指定 PWA 的注册方式。这里设置为 'autoUpdate',表示自动更新注册方式。

如下是VitePWAOptions 支持的所有配置项:

php 复制代码
/**
 * Plugin options.
 */
interface VitePWAOptions {
   
    mode?: 'development' | 'production';
    srcDir?: string; // 默认public
    outDir?: string; // 默认dist
    filename?: string; // 默认sw.js
    manifestFilename?: string; // 默认 manifest.webmanifest
    strategies?: 'generateSW' | 'injectManifest'; // 默认 generateSW
    scope?: string; // 注册 service worker范围
    injectRegister: 'inline' | 'script' | 'script-defer' | 'auto' | null | false; // 默认auto
    registerType?: 'prompt' | 'autoUpdate'; // 默认 prompt
    minify: boolean; // 默认 true
    manifest: Partial<ManifestOptions> | false; // manifest配置对象
    useCredentials?: boolean; // 是否添加crossorigin="use-credentials"到<link rel="manifest">,默认false
    workbox: Partial<GenerateSWOptions>; // google workbox配置对象,
    injectManifest: Partial<CustomInjectManifestOptions>;
    base?: string; // 覆盖vite的base配置,仅仅对于pwa
    includeAssets: string | string[] | undefined;
    includeManifestIcons: boolean;
    disable: boolean; // 是否在"生成"上禁用service worker注册和生成?默认false
    integration?: PWAIntegration; // Vite PWA集成
    devOptions?: DevOptions; // 开发环境配置
    selfDestroying?: boolean; // 是否销毁service worker,默认false
    buildBase?: string; // 构建配置,默认使用vite.config.ts中的配置
}

2、添加mainfest配置

manifest用于配置pwa应用的基础信息:如名称、图标、主题色等,也可以选择创建manifest文件来配置应用信息:

  • name : 应用名
  • icons: 应用图标
  • description:应用描述信息
  • short_name: 应用简称
  • theme_color: 样式主题色,默认#42b883
  • background_color:背景色,默认#fff
  • lang:语言,默认en
  • shortcuts:快捷方式的配置信息
php 复制代码
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配置即可按照规则对资源进行本地缓存、以及运行时缓存等操作。

typescript 复制代码
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中的完成配置信息。

php 复制代码
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、配置应用安装触发

希望安装应用到桌面需要我们预先配置应用安装触发,首先需要在入口处添加监听,然后通过我们的交互方式进行应用的安装操作(或者通过工具栏的图标主动安装)。

javascript 复制代码
// 在主入口监听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 = false
        localStorage.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、缓存

如下是测试环境下的缓存信息图示:

相关推荐
开心工作室_kaic42 分钟前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā42 分钟前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年2 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder2 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727572 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart3 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter
会发光的猪。3 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客3 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记3 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
前端李易安4 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js