Up to now, maybe vite users are still not many, so there are few articles about plug-ins, such as the protagonist of today’s introduction of Vite-plugin-pwa. Just a period of time before the relevant use of experience, to still looking for a document of the students a simple introduction.

Pwa is introduced

When it comes to PWA applications, many people associate the following concepts:

PWA (Progressive Web App), a Progressive Web application that Google introduced in 2015 and launched in June 2016, has some notable features:

  • Reliable: When a user boots from the phone’s home screen, the PWA is immediately loaded, regardless of the state of the network.
  • Fast: This point should be familiar with it, from the user’s point of view, if a page load speed is a little long, then we will give up browsing the site, so PWA does a good job in this point, his load speed is very Fast.
  • Engaging: PWA can be added to the user’s home screen, instead of being downloaded from the APP store, they provide an app-like experience through the web APP Manifest file (full screen on Android, due to Safari support issues). So not on IOS), and push notifications.

It can be understood as turning a traditional Web page into an app-type page. Similarly, some functions needed by an app must also be available. One of the most important functions is loading offline data.

When a web page is loaded normally, the resources in the page can only be displayed if the network request is successful every time, but this is obviously not true in the app. An application that is disconnected from the Internet for a short time also needs to be able to load and render content so that users will not be unable to use it. One of the technologies needed is service worker.

service worker

In fact, there are many articles about service worker. I will just give a brief introduction here. You can think of it as the middleman role between server and browser. Judgment (need to write the corresponding judgment procedures), if the need to initiate a request to the server to the server, if you can directly use the cache will be directly returned to the cache no longer to the server. In this way, the problem of offline data pulling can be easily solved, and the scenario where interface data changes infrequently and interface data pulling is slow can be greatly optimized. Here are some details

  • Based on web workers (a separate thread from the main thread of JavaScript, where resource-intensive operations can be performed without blocking the main thread)
  • Add the ability of offline cache on the basis of Web worker
  • Essentially acts as a proxy server between the Web application (server) and the browser (intercepts site-wide requests and acts accordingly -> actions specified by the developer)
  • Create an effective offline experience (cache infrequently updated content in the browser to improve the experience)
  • Event-driven and has a life cycle
  • Access to cache and indexDB
  • Support to push
  • It also allows developers to manage the content and version of the cache themselves

For more details about how to register a service worker, you can check out the article Service Worker — it should be a pretty comprehensive arrangement. Personally, I think it is more detailed. Basically, you can implement related functions by following the instructions.

vite-plugin-pwa

Vite-plugin-pwa is an official plugin for Vite. Its function is to turn your Vite project into a PWA application through simple configuration. The implementation of service worker directly adopts Google open source library Workbox. Workbox does a lot of caching logic internally, supports a lot of different caching strategies, encapsulates the update strategy for sw.js files, and is very simple to configure. Sometimes it’s better to stand on the shoulders of giants.

workbox

There’s not much to say about workBox’s use, but it’s basically just as documented. Here are the four cache strategies that workBox currently encapsulates

  • Stale-While-Revalidate
  • Cache First
  • Network First
  • Network Only
  • Cache Only

Note that the following source code has been simplified to facilitate analysis of the strategy

Stale-While-Revalidate

This cache policy is almost identical to the original HTTP policy of the same name, which preferentially selects the local cache, then requests and updates the cache, in other words, does not update properly until the next request.

Let’s combine source code analysis:

const fetchAndCacheResponse = this.requestWrapper.fetchAndCache({
  request: event.request,
  waitOnCache: this.waitOnCache,
  cacheResponsePlugin: this._cacheablePlugin,
}).catch(() = > Response.error());

const cachedResponse = await this.requestWrapper.match({
  request: event.request,
});

return cachedResponse || await fetchAndCacheResponse;
Copy the code

The cache strategy is to first match the cache through the service worker and still fetch the interface once at a time and update the cache with the results of the request. If there is no match in the cache, the fecth is returned directly.

CACHE FIRST

Cache first, as the name implies, gives priority to access to the cache if a request is made using the network if the cache is not available

const cachedResponse = await this.requestWrapper.match({
  request: event.request,
});

return cachedResponse || await this.requestWrapper.fetchAndCache({
  request: event.request,
  waitOnCache: this.waitOnCache,
});
Copy the code

It can be seen from the code that the cache will be matched first each time, and the cache will be fetched and cached again only when the cache fails to match. Therefore, this method is not suitable for the case of frequent data updates. It is more suitable for some static resources cache.

NETWORK FIRST

Network-first is a complex policy that accepts networkTimeoutSeconds. If this parameter is not passed, the request will be issued and the result will be added to the cache on success, or immediately cached on failure. This network fallback to cache approach is good for frequently updated resources, but in poor network conditions (where no network directly returns to the cache), the wait is longer, where networkTimeoutSeconds provides the benefit. If set, a setTimeout is generated, called by the resolve cache, and dropped into a promise.race with the request, which is returned to the cache when the request times out.

NETWORK FIRST, Cache FIRST

NETWORK FIRST:

Cache FIRST:

These two are relatively simple, one is to use only the FETCH interface data, and the other is to use only the cache, neither of which is generally applicable.

Vite plugin – use pwa

The workbox cache policy is very simple to configure

First installation

yarn add vite-plugin-pwa --dev
Copy the code

Then configure it in viet-config.js

import { VitePWA } from 'vite-plugin-pwa'
export const defineConfig({
  plugins: [
    VitePWA({})
  ]    
})
Copy the code

Below I list the common configuration items, here I directly copy the source code part for translation and analysis

/** * Plugin options. */
export interface VitePWAOptions {
  /**
   * Build mode
   *
   * @default Process.env.node_env or "production" development environment selection generally does not need to set */mode? :'development' | 'production'
  / * * *@default 'public' 
   */srcDir? :string 
  / * * *@default 'dist' sw.js output directory defaults to dist */outDir? :string 
  / * * *@default The file name generated by the 'sw.js' service worker defaults to sw.js */filename? :string
  / * * *@default The 'generateSW' workbox generates the service worker schema. The default is that the generateSW * generateWS method will be abstracted from using the service worker API when building the service worker. You can configure this method using a plug-in rather than writing your own service worker code (' generateWS 'will generate the code for you). GenerateSW can be used in cases where you don't need to highly customize the service worker. * The injectManifest method takes your custom service worker and builds/compiles it, which means you need to write more specific service worker policy code. InjectManifest is generally suitable for more complex cache policies */strategies? :'generateSW' | 'injectManifest'
  /**
   * The scope to register the Service Worker
   *
   * @default Same as' base 'of Vite's config * service worker scope Equivalent to a subdirectory that can be used to specify what you want the service worker to control https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers */scope? :string
  /**
   * Inject the service worker register inlined in the index.html 
   *
   * With `auto` set, depends on whether you used the `import { registerSW } from 'virtual:pwa-register'`
   * it will do nothing or use the `script` mode
   *
   * `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' * Service worker injection method, this can be ignored for no special needs */
  injectRegister: 'inline' | 'script' | 'auto' | null | false
  /** * Mode for the virtual register. * Does NOT available for `injectRegister` set to `inline` or `script` * * `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 * windows/tabs with the application open automatically,  it must take the control for the application to work * properly. * *@default 'Prompt' * This is an important sw.js update strategy. AutoUpdate automatically updates sw.js in the event of changes. Allows you to select update manually This example can directly see the website https://github1s.com/antfu/vite-plugin-pwa/blob/HEAD/examples/vue-router/src/ReloadPrompt.vue * /registerType? :'prompt' | 'autoUpdate'
  /**
   * Minify the generated manifest
   *
   * @default True Whether to compress the manifest file */
  minify: boolean
  /** * The manifest object /** * The manifest object Concrete can be directly see https://github1s.com/antfu/vite-plugin-pwa/blob/HEAD/src/types.ts#L117 * /
  manifest: Partial<ManifestOptions> | false 
  /**
   * Whether to add the `crossorigin="use-credentials"` attribute to `<link rel="manifest">`
   * @default false* /useCredentials? :boolean
  /** * The workbox object for 'generateSW' */
  workbox: Partial<GenerateSWOptions>
  /** * The workbox object for `injectManifest` */
  injectManifest: Partial<InjectManifestOptions>
  /**
   * Override Vite's base options only for PWA
   *
   * @default "base" options from Vite
   */base? :string
  /** * `public` resources to be added to the PWA manifest. * * You don't need to add `manifest` icons here, it will be auto included. * * The `public` directory will be resolved from Vite's `publicDir` option directory. */
  includeAssets: string | string[] | undefined
  /** * By default the icons listed on `manifest` option will be included * on the service worker *precache* if present under Vite's `publicDir` * option directory. */
  includeManifestIcons: true
}
Copy the code

Then register in the main.js file to enjoy the fast load experience of the service worker

import { createApp } from 'vue';
import App from '@/App.vue';
import { useRegisterSW } from 'virtual:pwa-register/vue';

useRegisterSW();

const app = createApp(App);
app.mount('#app'.true);
Copy the code

Below I present some common workbox configurations

VitePWA({
      includeAssets: ['favicon.svg'].manifest: false.registerType: 'autoUpdate'.workbox: {
        runtimeCaching: [{urlPattern: /someInterface/i.// Interface cache This is where you want to cache interface re matches
            handler: 'CacheFirst'.options: {
              cacheName: 'interface-cache',}}, {urlPattern: / (. *?) \.(js|css|ts)/.// js/CSS /ts static resource cache
            handler: 'CacheFirst'.options: {
              cacheName: 'js-css-cache',}}, {urlPattern: / (. *?) \.(png|jpe? g|svg|gif|bmp|psd|tiff|tga|eps)/.// Image cache
            handler: 'CacheFirst'.options: {
              cacheName: 'image-cache',},},],},}),Copy the code

The above is a brief summary of the usage documents of viet-plugin-PWA and some knowledge about service workers and workbox. I hope to help more students work less overtime.