vite-pwa: 网站静默更新

不需要弹出更新提示,使用 vite-pwa 完成静默更新,特别适合中后台场景

01 安装 vite-pwa

安装

# 添加 pwa 插件
yarn add --dev vite-plugin-pwa
# 添加 check-updater 组件
yarn add @jswork/react-sw-updater

02 添加 page-checker

page-checker.tsx 核心代码

/**
 * @email: aric.zheng@alo7.com
 * @description: A React component.
 * @updated_at: 2024-06-04 18:27:24
 */
import ReactSwUpdater from '@jswork/react-sw-updater';

const Anonymous = () => {
  return (
    <ReactSwUpdater
      disabled={!import.meta.env.PROD}
      interval={20 * 1000}
      onChange={({ update }) => {
        update().then((res) => {
          console.log('Success updated', res);
        });
      }}
    />
  );
};

export default Anonymous;

03 将 page-checker 添加到 app 中

_app.tsx 中添加 <PageChecker />

import PageChecker from '@/shared/components/page-checker';

const App = () => {
  nx.$nav = useNavigate();
  return (
    <QueryClientProvider client={nx.$client}>
      <StateProvider store={stores}>
        <ModalManager>
          <Outlet />
          <PageChecker />
        </ModalManager>
      </StateProvider>
    </QueryClientProvider>
  );
};

export default App;

04 pwa 配置

vite.config.ts 核心配置如下

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { VitePWA } from 'vite-plugin-pwa';
// import { RouteMatchCallbackOptions } from 'workbox-core/src/types';

export default defineConfig({

  plugins: [
    react(),
    VitePWA({
      injectRegister: 'inline',
      // registerType: 'prompt',
      workbox: {
        globPatterns: ['**/**/*.{js,css,html,ico,png,jpg,jpeg,gif,svg}'],
        globIgnores: ['**/index.html', '**/sw.js'],
        ignoreURLParametersMatching: [/^v$/, /^t$/, /^queryKey$/, /^hash$/],
        skipWaiting: false,
        clientsClaim: false,
        runtimeCaching: [
          {
            // 匹配 unpkg.com 和 cdn.jsdelivr.net 的所有子域名
            urlPattern: /^https:\/\/(?:\w+\.)?(unpkg\.com|cdn\.jsdelivr\.net)/,
            handler: 'CacheFirst',
            options: {
              cacheName: 'unpkg-jsdelivr-cache',
              cacheableResponse: {
                statuses: [0, 200]
              },
              expiration: {
                maxEntries: 50,
                maxAgeSeconds: 30 * 24 * 60 * 60 // 30 days
              }
            }
          }
        ]
      }
    })
  ],
});
vite pwa