vite-plugin-pwa配置详解
前提:前端域名和后端服务域名相同时,用window.open新开页面下载或者导出文件,项目中导出和下载功能失效,原因是,域名相同走缓存
实现service worker
离线缓存以前需要自己编写sw.js
文件内容,比较复杂。 谷歌提供了workbox-*
库来协助写配置。
vite-plugin-pwa就是帮你使用workbox
结合一些模板代码自动生成sw.js
,实现0配置
一:vite-plugin-pwa的简单使用
- 默认缓存所有的js.css.html
// vite.config.ts/js
import { VitePWA } from "vite-plugin-pwa";
export default {plugins: [VitePWA()]
}
二:先看VitePWAOptions的配置
function VitePWA(userOptions?: Partial<VitePWAOptions>): Plugin[];
interface VitePWAOptions {// @default process.env.NODE_ENV or "production"mode?: 'development' | 'production';// @default 'public'srcDir?: string;// @default 'dist'outDir?: string;// @default 'sw.js'filename?: string;// @default 'manifest.webmanifest'manifestFilename?: string;// @default 'generateSW'strategies?: 'generateSW' | 'injectManifest';// @default same as `base` of Vite's configscope?: string;//`inline` - inject a simple register, inlined with the generated html//`script` - inject <script/> in <head>, with the `sr` to a generated simple register//`null` - do nothing, you will need to register the sw you self, or imports from `virtual:pwa-register`// @default 'auto'injectRegister: 'inline' | 'script' | 'auto' | null | false;// `prompt` - you will need to show a popup/dialog to the user to confirm the reload.// `autoUpdate` - when new content is available, the new service worker will update caches and reload all browser// @default 'prompt'registerType?: 'prompt' | 'autoUpdate';// @default trueminify: boolean;manifest: Partial<ManifestOptions> | false;// @default falseuseCredentials?: boolean;workbox: Partial<GenerateSWOptions>;injectManifest: Partial<CustomInjectManifestOptions>;// @default "base" options from Vitebase?: string;includeAssets: string | string[] | undefined;// @default trueincludeManifestIcons: boolean;// @default falsedisable: boolean;devOptions?: DevOptions;// @default falseselfDestroying?: boolean;
}
这里只重点介绍几个配置,其他感兴趣的自行查阅文档:
- .
strategies
: 默认是generateSW
然后去配置workbox
;,如果你需要更多自定义的设置,可以选择injectManifest
,那就对应配置injectManifest
- .
workbox
: 是对应generateSW
的配置,所有的workbox
配置,最终将生成`sw.js文件
三:再看workbox的类型----GenerateSWOptions
type GenerateSWOptions = BasePartial & GlobPartial & GeneratePartial & RequiredSWDestPartial & OptionalGlobDirectoryPartial;
export interface GlobPartial {/*** A set of patterns matching files to always exclude when generating the* precache manifest. For more information, see the definition of `ignore` in* the `glob` [documentation](https://github.com/isaacs/node-glob#options).* @default ["**\/node_modules\/**\/*"]*/globIgnores?: Array<string>;/*** Files matching any of these patterns will be included in the precache* manifest. For more information, see the* [`glob` primer](https://github.com/isaacs/node-glob#glob-primer).* @default ["**\/*.{js,css,html}"]*/globPatterns?: Array<string>;
}
重点关注:
globPatterns
: 最开始我们说配置会默认缓存所有的js.css.html,我是就是通过globPatterns
实现的。如果想增加图片缓存可以在里面添加globIgnores
: 忽略不想缓存的资源
export interface GeneratePartial {/*** Any search parameter names that match against one of the RegExp in this* array will be removed before looking for a precache match. This is useful* if your users might request URLs that contain, for example, URL parameters* used to track the source of the traffic. If not provided, the default value* is `[/^utm_/, /^fbclid$/]`.**/ignoreURLParametersMatching?: Array<RegExp>;/*** When using Workbox's build tools to generate your service worker, you can* specify one or more runtime caching configurations. These are then* translated to {@link workbox-routing.registerRoute} calls using the match* and handler configuration you define.** For all of the options, see the {@link workbox-build.RuntimeCaching}* documentation. The example below shows a typical configuration, with two* runtime routes defined:** @example* runtimeCaching: [{* urlPattern: ({url}) => url.origin === 'https://api.example.com',* handler: 'NetworkFirst',* options: {* cacheName: 'api-cache',* },* }, {* urlPattern: ({request}) => request.destination === 'image',* handler: 'StaleWhileRevalidate',* options: {* cacheName: 'images-cache',* expiration: {* maxEntries: 10,* },* },* }]*/runtimeCaching?: Array<RuntimeCaching>;/*** Whether to create a sourcemap for the generated service worker files.* @default true*/sourcemap?: boolean;
}
重点关注:
ignoreURLParametersMatching
:默认无法缓存html后面带参数的页面,加上它忽略参数就可以缓存了runtimeCaching
: 运行时缓存,可以自定义配置各种类型的缓存,最后我们会详细介绍sourcemap
: 是否生成sourcemap
,它记录了转换压缩后的代码所对应的转换前的源代码位置,方便定位问题
四:将上面的配置,应用到vite.config.ts/js文件
// vite.config.ts/js
import { VitePWA } from 'vite-plugin-pwa'
export default {plugins: [VitePWA({workbox:{globIgnores: ['static/js/**'],globPatterns: ["**/*.{js,css,html,ico,jpg,png,svg}"],ignoreURLParametersMatching: [/.*/],sourcemap:true,}})]
}
五:自定义配置缓存
随着项目越来越庞大或者需求越来越复杂,有时候我们需要,缓存某些特定的路径文件,或者请求类型,以及单独设置js或者html的缓存时间和个数,这个时候我们就需要用到runtimeCaching
配置
export interface RuntimeCaching {/*** This determines how the runtime route will generate a response.* To use one of the built-in {@link workbox-strategies}, provide its name,* like `'NetworkFirst'`.* Alternatively, this can be a {@link workbox-core.RouteHandler} callback* function with custom response logic.*/handler: RouteHandler | StrategyName;/*** The HTTP method to match against. The default value of `'GET'` is normally* sufficient, unless you explicitly need to match `'POST'`, `'PUT'`, or* another type of request.* @default "GET"*/method?: HTTPMethod;/*** This match criteria determines whether the configured handler will* generate a response for any requests that don't match one of the precached* URLs. If multiple `RuntimeCaching` routes are defined, then the first one* whose `urlPattern` matches will be the one that responds.** This value directly maps to the first parameter passed to* {@link workbox-routing.registerRoute}. It's recommended to use a* {@link workbox-core.RouteMatchCallback} function for greatest flexibility.*/urlPattern: RegExp | string | RouteMatchCallback;options?: {/*** Configuring this will add a* {@link workbox-cacheable-response.CacheableResponsePlugin} instance to* the {@link workbox-strategies} configured in `handler`.*/cacheableResponse?: CacheableResponseOptions;/*** If provided, this will set the `cacheName` property of the* {@link workbox-strategies} configured in `handler`.*/cacheName?: string | null;/*** Configuring this will add a* {@link workbox-expiration.ExpirationPlugin} instance to* the {@link workbox-strategies} configured in `handler`.*/expiration?: ExpirationPluginOptions;};
}
重点关注:
-
handler
: 取缓存的策略,有五种type StrategyName = 'CacheFirst' | 'CacheOnly' | 'NetworkFirst' | 'NetworkOnly' | 'StaleWhileRevalidate';
CacheFirst
:缓存优先CacheOnly
:仅使用缓存中的资源NetworkFirst
:网络优先NetworkOnly
:仅使用正常的网络请求StaleWhileRevalidate
:从缓存中读取资源的同时发送网络请求更新本地缓存
-
method
: 默认是缓存get请求的资源,想缓存post的可以配置 -
urlPattern
: 通过正则,字符或者函数形式匹配要缓存的资源类型 -
options
自定义配置项cacheableResponse
: 缓存状态码正确的资源,比如200的cacheName
: 自定义缓存的类型名称expiration
: 设置缓存的时间,数量。超过数量就删除之前的
想解决我最开始抛出的,前后端域名相同,导致的下载或者导出失败问题,可以做如下配置:
// vite.config.ts/js
import { VitePWA } from 'vite-plugin-pwa'
export default {plugins: [VitePWA({workbox: {maximumFileSizeToCacheInBytes: 50000000,globPatterns: [],runtimeCaching: [{// 路径url中包含ai-synergy或者auth,handler设置成NetworkOnlyurlPattern: /.*\/(ai-synergy|auth).*/,handler: 'NetworkOnly',options: {cacheName: 'ai-synergy|auth',cacheableResponse: {statuses: [200]}}}]}})]
}
最后是更加完善的自定义配置方案:
VitePWA({workbox: {globPatterns: [],runtimeCaching: [mode !== 'production'? {urlPattern: ({ url }) => url.origin === 'https://xxx.list.com',handler: 'NetworkFirst',options: {cacheName: 'list',cacheableResponse: {statuses: [200]}}}: {urlPattern: ({ url }) => url.origin === 'https://xxx.detail.com',handler: 'NetworkFirst',options: {cacheName: 'detail',cacheableResponse: {statuses: [200]}}},{urlPattern: /.*\/(ai-synergy|auth).*/,handler: 'NetworkOnly',options: {cacheName: 'ai-synergy|auth',cacheableResponse: {statuses: [200]}}},{urlPattern: /\.(?:png|jpg|jpeg|svg)$/,handler: 'CacheFirst',options: {cacheName: 'images',expiration: {// 最多20个图maxEntries: 20}}},{urlPattern: /.*\.js.*/,handler: 'StaleWhileRevalidate',options: {cacheName: 'js',expiration: {maxEntries: 30, // 最多缓存30个,超过的按照LRU原则删除maxAgeSeconds: 30 * 24 * 60 * 60},cacheableResponse: {statuses: [200]}}},{urlPattern: /.*\.css.*/,handler: 'StaleWhileRevalidate',options: {cacheName: 'css',expiration: {maxEntries: 20,maxAgeSeconds: 30 * 24 * 60 * 60},cacheableResponse: {statuses: [200]}}},{urlPattern: /.*\.html.*/,handler: 'StaleWhileRevalidate',options: {cacheName: 'html',expiration: {maxEntries: 20,maxAgeSeconds: 30 * 24 * 60 * 60},cacheableResponse: {statuses: [200]}}}]},})