preface


This recent year, as a front dog, has been optimizing performance on the road to never turning back. Vue, Nginx, Webpack, Redis, can do optimization of the place, have never let go, only for the last second of comfort! (Obscene smile).

I have been paying attention to PWA. I hope that PWA can make a one-time improvement to the current project. While there is still some time recently, I can make a transformation to the front-end structure used by the company.

This transformation is mainly divided into two parts:

  • Retrofit projects created based on Vue CLI3
  • Revamp projects based on webpack3.0 packaging

PWA and Service Work related knowledge, here is not more introduction, you can search for yourself

Retrofit projects created based on Vue CLI3


PWA can be enabled for a new project by selecting the PWA template directly in vue Create

1. Install the PWA plug-in

vue add pwa
Copy the code

Note that Vue CLI3 implements PWA based on workbox

2. Directory structure

After the plug-in is installed, the directory structure is as follows:

  • Registerserviceworker.js: Registers service work
  • Service-worker. js: user-defined service work configuration file

3. Modify registerServiceworker.js to perform compatibility processing

Currently, some browsers do not support Service work, so we need to make sure that they still work. Check whether the browser supports SW by using ‘serviceWorker’ in window.navigator:

/* eslint-disable no-console */

import {register} from 'register-service-worker';

if ('serviceWorker' in window.navigator && process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready() {
      console.log(
        'App is being served from cache by a service worker.\n' +
        'For more details, visit https://goo.gl/AFskqB'
      );
    },
    registered() {
      console.log('Service worker has been registered.');
    },
    cached() {
      console.log('Content has been cached for offline use.');
    },
    updatefound() {
      console.log('New content is downloading.');
    },
    updated() {
      console.log('New content is available; please refresh.');
    },
    offline() {
      console.log('No internet connection found. App is running in offline mode.');
    },
    error(error) {
      console.error('Error during service worker registration:', error); }}); }Copy the code

4. Write the service – work. Js

For complete service-work, please refer to service-work.js in our front-end template project. Here we introduce it step by step:

  • Set the prefix and suffix of the cache. We usually use the project name as the prefix and the version number as the suffix
workbox.core.setCacheNameDetails({
  prefix: 'easy-front-vue-cli3'.suffix: 'v1.0.0'
});
Copy the code
  • Configure an update activation policy for service Work
workbox.core.skipWaiting(); // Force the waiting Service Worker to be activated
workbox.core.clientsClaim(); // The Service Worker takes control of the page immediately after it is activated
Copy the code
  • Setting preloading
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
Copy the code
  • Setting resource Caching Policies Workbox provides the following cache policies:

Stale-while-revalidate: Use cached content (if available) to respond to the request as soon as possible, or network request if not cached. The network then requests the data to update the cache.

Cache First: If the request hits the Cache, the cached response is used to complete the request, not the network. If the cache is not hit, the data is fetched through a network request and cached so that it can be fetched directly from the cache the next time. This mode can provide a quick response for the front end while reducing the server pressure. However, the timeliness of the data requires the developer to update the cache file by setting the cache expiration time or changing the revision flag in service-work.js

Network First: obtains the latest data from the Network First. If successful, it puts the data into the cache. If the network cannot return a response, cached data is used.

Network Only: Requests data Only over the Network

Cache Only: Only Cache data is used

The specific strategy needs to be set according to actual business scenarios and requirements. The basic strategy I adopted is as follows:

// Cache web CSS resources
workbox.routing.registerRoute(
  // Cache CSS files
  /.*\.css/,
  // Use caching, but update in the background as soon as possible
  workbox.strategies.staleWhileRevalidate({
    // Use custom cache names
    cacheName: 'css-cache'}));// Cache web JS resources
workbox.routing.registerRoute(
  // Cache the JS file
  /.*\.js/,
  // Use caching, but update in the background as soon as possible
  workbox.strategies.staleWhileRevalidate({
    // Use custom cache names
    cacheName: 'js-cache'}));// Cache web image resources
workbox.routing.registerRoute(
  / \. (? :png|gif|jpg|jpeg|svg)$/,
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'images'.plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 60.maxAgeSeconds: 30 * 24 * 60 * 60 // Set the cache validity period to 30 days})]}));// Many of our resources are in other domain names, such as CDN, OSS, etc., here we do separate processing, need to support cross-domain
workbox.routing.registerRoute(
  /^https:\/\/cdn\.my\.com\/.*\.(jpe?g|png|gif|svg)/,
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'cdn-images'.plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 60.maxAgeSeconds: 5 * 24 * 60 * 60 // Set the cache validity period to 5 days})].fetchOptions: {
      credentials: 'include' // Cross-domain support}}));// Cache the data requested by the GET API
workbox.routing.registerRoute(
  new RegExp('https://m.my.com/api'),
  workbox.strategies.networkFirst({
    cacheName: 'api'}));// Cache the data requested by the POST API
// const bgSyncPlugin = new workbox.backgroundSync.Plugin('apiQueue', {
// maxRetentionTime: 1 * 60
// });

// workbox.routing.registerRoute(
// /.*\/api\/.*/,
// new workbox.strategies.NetworkOnly({
// plugins: [bgSyncPlugin]
/ /}),
// 'POST'
// );

Copy the code

5. Modify the main. Js

Add the following code

import './registerServiceWorker';
Copy the code

6. Modify the vue. Config. Js

Refer to vue.config.js.js in our front-end template project. The following lists the parts related to PWA:

pwa: {
    name: 'easy-front-vue-cli3'.themeColor: '#4DBA87'.msTileColor: '# 000000'.appleMobileWebAppCapable: 'yes'.appleMobileWebAppStatusBarStyle: 'black'.// configure the workbox plugin (GenerateSW or InjectManifest)
    workboxPluginMode: 'InjectManifest'.workboxOptions: {
      // swSrc is required in InjectManifest mode.
      swSrc: 'src/service-worker.js'.importWorkboxFrom: 'disabled'.importScripts: 'https://cdn.your.info/workbox-v4.3.1/workbox-sw.js'
      / /... other Workbox options...}}Copy the code
  • WorkboxPluginMode: The workbox mode, GenerateSW uses the default mode, InjectManifest uses the custom mode, I recommend InjectManifest for more freedom
  • Workboxoptions. swSrc: specifies the location of service-worker.js
  • WorkboxOptions. ImportWorkboxFrom: introducing workbox rely on libraries, the default dependent libraries in Google CDN, everybody knows domestic situation, it is recommended that will rely on library in you own CDN, so I set up heredisabled
  • WorkboxOptions. ImportScripts: specify your own library of CDN urls

7. To configure the manifest. Json

PWA supports the creation of shortcuts, and manifest.json contains shortcut names, ICONS, entry paths, and other configurations. If you do not need a shortcut, you do not need to create one

{
  "name": "easy-front-vue-cli3"."short_name": "easy-front-vue-cli3"."icons": [{"src": "/img/icons/android-chrome-192x192.png"."sizes": "192x192"."type": "image/png"
    },
    {
      "src": "/img/icons/android-chrome-512x512.png"."sizes": "512x512"."type": "image/png"}]."start_url": "/"."display": "standalone"."background_color": "# 000000"."theme_color": "#4DBA87"
}
Copy the code

Revamp projects based on webpack3.0 packaging

We only introduce the parts that are different from Vue cli3, registerServiceworker.js, service-work.js, and manifest.json.

1. Install dependency packages

npm install workbox-webpack-plugin -D
npm install register-service-worker -S
Copy the code

2. Modify the webpack. Prod. Conf. Js

// Add the workbox plugin to webPack and configure it
const {InjectManifest} = require('workbox-webpack-plugin');
  webpackConfig.plugins.push(new InjectManifest({
    swSrc: 'src/service-worker.js'.importWorkboxFrom: 'disabled'.importScripts: 'https://cdn.your.info/workbox-v4.3.1/workbox-sw.js'
  }));
Copy the code

3. Modify the main. Js

Add the following code

import './registerServiceWorker';
Copy the code

reference


My template project: Easy-front-vuE-CLI3

Workbox Warehouse address: Workbox

PWA learning materials: PWA application actual combat