Partial understanding and basic demo of front-end PWA application

1. What is a PWA application?

1. Introduction to PWA

​ Progressive Web App (Progressive Web App), referred to as PWA , is an application built using web platform technology proposed by Google in 2015. The official believes that its core lies in Reliable(reliable), Fast(fast), Engaging(participable ), combining the advantages of both web site programs and native applications, can bring users a better experience.

​ PWA can run on multiple platforms through a set of codes like a website, and can be accessed through a browser and shared through Url links. Like a native app, it can be installed on the device through an app store or a web page. After installation, it can be accessed through an icon and launched as an independent app; and even if it is disconnected from the network, some pages and data can be accessed through the app cache.

​ But it should be noted that when the PWA application is opened through the icon installed on the device, although it looks like a native application in appearance, it still belongs to the website category from a technical point of view, so it still needs A browser engine to parse and run, providing it with a normal operating environment. So the principle is similar to opening a separate browser window with custom window content.

​ PWA is not only a technology, but also represents a development concept of a Web site. If a website program implements various specific functions such as installable and offline, we can regard it as a PWA application. At present, domestic websites that support PWA include: Weibo , Yuque and so on.

insert image description here

2. PWA features

​ Native apps represent the best features because they are deeply integrated with the operating system, easy to access, offline, and integrated with the operating system. Web site programs represent the widest range, because they are browser-based and have the advantages of cross-platform, no need to download, and easy to update and deploy. PWA, on the other hand, is at the intersection of native application functions and the range of Web site programs. It is a combination of the two and mainly has the following characteristics:

​① Cross-platform: PWA applications can run on different operating platforms only by writing a set of codes, and PWA applications adopt the concept of progressive enhancement, its core functions can run normally on any browser, and the rest of the powerful The function needs to rely on the browser's support for PWA features, and gradually upgrade the experience according to the browser's support.

​② Installable: PWA applications can be added to the home screen or application menu to achieve an icon entry similar to a native application. Click the icon to be launched as an independent application, allowing users to access the application more conveniently. The program can also be packaged and uploaded to various application stores, allowing users to install website applications through the application stores.

​③ Offline access: PWA applications have the ability to access offline, they can cache the core resources of the application, so that users can continue to access the application without a network connection, view some pages and data, provide basic functions, and Update cache on resume.

​④ Push notifications: PWA applications can actively send push notifications to users, so that the application can promptly notify users of important updates, new news or other key information, similar to the notification function of native applications.

​⑤ Fast loading: PWA applications use Service Workers to cache resources and provide an offline experience, which also allows the application to load faster and respond to user operations.

Searchable: PWA applications can be found through search engines, and can be shared through url links.

​⑦ Hot update: When some content in the PWA application is updated, it can automatically perform local hot update after networking to ensure that users can use the latest application without re-downloading and installing the client like native applications.

​Combining the official three cores of Reliable(reliable), Fast(fast), and Engaging(participatory), I think cross-platform and offline access embodies Reliable(reliable), whether it is in a low-version browser or without a network Under normal circumstances, PWA can display basic functions; fast loading and hot update reflect Fast(fast), use cache and automatic update, reduce repeated data loading, and improve response speed; installable and push notifications reflect Engaging(participating) , which can be installed on the device and push notifications to the user.

3. Applicable scenarios

​ Map navigation, information documents, blog notes, etc.

2. What is the core technology of PWA?

​ The realization of PWA depends on a variety of technologies, among which the core technologies are Service Worker, Web App Manifestand Push Notification.

1、Service Worker

​ Service Worker is a script independent of the web thread and has no right to access the DOM structure of the page. It acts as a proxy server between the website and the browser. Each PWA application can only register one Service Worker, which is mainly used in PWA To achieve offline access, cache resources, push notifications and other functions, of course, it also has many other functions, which we will not describe here.

​ When the network is normal, when the PWA application requests resources within the scope of the Service Worker, the Service Worker will intercept the request and act as a network proxy, and then it can decide whether to obtain data from the cache or from the server. If the data is obtained from the server, the Service Worker will cache the requested data, and return the cached data when it is accessed offline, so that the PWA application can run offline, and the cache can be used to improve the loading speed of the application.

​ Since Service Worker has too much power, it can directly intercept and return user requests. For security reasons, it currently only supports use in HTTPS or local environment security environments.

​ The browser compatibility of Service Worker is as follows:
insert image description here

How to register Service Worker for PWA?

Before the Service Worker controls the page, the Service Worker service must be registered in the PWA application. This means that when the user accesses the PWA application for the first time, the page has not been controlled by the Service Worker, and functions such as offline access cannot be realized.

​ When registering a Service Worker, we only need to first determine whether the browser supports the relevant API, and if so, navigator.serviceWorker.register(url)register directly through it. The parameter urlindicates the path of the specific Service Worker logic code file.

// 这是页面中唯一与Service Worker有关的代码
if ('serviceWorker' in navigator) {
    
    
  navigator.serviceWorker.register('/service-worker.js')
   .then(registration => {
    
    
     console.log('Service Worker 注册成功!', registration);
   })
   .catch(error => {
    
    
     console.log('Service Worker 注册失败:', error);
  });
}

​ If you want to check whether the Service Worker has been registered and is running normally, take the Chrome browser as an example, we can go to the Application in the F12 developer tool, and then select the Service Workers on the left, if it is displayed in the information displayed on the Statusright activityIt means that it has been registered and is running normally.

insert image description here

​ If you want to check whether it has been registered and is running normally on the mobile page, you can only check it by connecting to a computer for debugging. For details, see this document: tools- and-debug .

How to determine the scope of service worker?

​ The folder where the specific logic file introduced by Service Worker during registration determines its scope of action, for example:

navigator.serviceWorker.register("example.com/my-pwa/serviceworker.js");

​ Then the scope of the Service Worker is my-pwaany file under the folder, such as: example.com/my-pwa/index.htmletc.

​ In order to maximize the role of Service Worker in PWA applications, it is recommended to set specific logic files in the root directory of PWA applications, because this can intercept all requests in PWA applications.

What are the stages of the service worker life cycle?

register()​ The life cycle of a Service Worker begins with the registration of the Service Worker, which is the method mentioned above . When this method is called, the registration behavior will occur. There is no corresponding event in this life cycle phase, and then we can use register()the method .then()to determine whether the registration is successful.

① Registration

if ('serviceWorker' in navigator) {
    
    
  navigator.serviceWorker.register('/service-worker.js')
   .then(registration => {
    
    
     console.log('Service Worker 注册成功!', registration);
   })
   .catch(error => {
    
    
     console.log('Service Worker 注册失败:', error);
  });
}

​ Then the browser starts to download and install the Service Worker file. After the installation is successful, an event will be triggered install. In the entire life cycle, installthe event will only be triggered once. Developers usually initialize in this event and cache some static resources for offline access.

② Installation

// 安装阶段
self.addEventListener('install', function(event) {
    
    
  event.waitUntil(
    // 向缓存中存储基本数据
    caches.open('cache-name').then(function(cache) {
    
    
      return cache.addAll([
        '/path/to/resource1',
        '/path/to/resource2',
        // ...
      ]);
    })
  );
});

​ In Service Worker, we need selfto listen to each life cycle event through the global object. Before waitUntil()the execution of the method ends, the Service Worker will not end the installation state, and must wait for the execution of its internal code to complete before entering the next life cycle. cachesObjects are special objects that are restricted to use during the Service Worker life cycle and are used to implement data caching.

③ Activation

​ After the Service Worker is installed, it will not enter the activation state immediately. In order not to affect the currently visited page, the Service Worker does not control the current page at this time. So wait until the current page is closed and the page is loaded again, the Service Worker will enter the activation state, trigger activatean event, and start to control the request and cache of the web page. At this stage, developers usually perform operations such as cleaning up old caches and processing update logic, because the browser's cache space is limited.

// Service Worker激活成功后 
self.addEventListener('activate', function(event) {
    
    
  event.waitUntil(
    // 对缓存中的数据进行处理
    caches.keys().then(function(cacheNames) {
    
    
      return Promise.all(
        // 只保留符合要求的数据 删除不需要的旧数据
        cacheNames.filter(function(cacheName) {
    
    
          return cacheName !== 'cache-name';
        }).map(function(cacheName) {
    
    
          return caches.delete(cacheName);
        })
      );
    })
  );
});

​ Before waitUntil()the execution of the method ends, the Service Worker will not enter the next state, and then cachesthe cached data can be operated on through the object.

Another thing to note is that after a Service Worker enters the active state, it will remain active unless it is manually logged out or replaced by a new Service Worker script.

④ Update

​ The browser will periodically check whether the Service Worker of the current application is updated. When it detects that the Server Worker script file is updated, it will download the new script in the background and trigger the update process. The update process is similar to the installation process and needs to go through three stages: download, install, and activate. After the download is complete, it will be installed immediately, but after the installation is complete, it will not be activated immediately by default, and it will enter a waiting state. Because only one version of Service Worker can be in the state at the same time Activation. Only when all pages controlled by the old version of the service worker are closed, and then the user revisits these pages, the new service worker will be activated and take over control of all the pages of the old version.

​ We can also use skipWaiting()methods to force the activation of the waiting Service Worker to replace the old Service Worker and gain control of the page. This method is only meaningful to call when there is a waiting service worker, so it is usually installcalled in an event.

// 新版Service Worker的install事件
self.addEventListener("install", (event) => {
    
    
  // 安装好后 调用skipWaiting() 使其立即激活
  // skipWaiting() 返回一个 promise,但完全可以忽略它
  self.skipWaiting();
  // 然后执行 service worker 安装所需的缓存数据等其他操作
  e.waitUntil(
    (async () => {
    
    
      const cache = await caches.open(cacheName);
      await cache.addAll(contentToCache);
    })(),
  );
});

⑤ Termination

​ When the Service Worker is manually logged out or replaced by a new version of the Service Worker, it will enter the termination phase, and it will no longer control the page request and release the corresponding resources. Even if it is not canceled or replaced, the Service Worker will not survive indefinitely. The processing logic of major browsers is different, but after a period of activation, the Service Worker will be terminated. After termination, you need to re-register to continue running.

if ('serviceWorker' in navigator) {
    
    
  navigator.serviceWorker.register('/service-worker.js')
   .then(registration => {
    
    
     console.log('Service Worker 注册成功!', registration);
     // 手动注销Service Worker
     registration.unregister().then(function (boolean) {
    
    
        if(boolean) {
    
    
          console.log('Service Worker 注销成功!')
        }
      });
   })
   .catch(error => {
    
    
     console.log('Service Worker 注册失败:', error);
  });
}

⑥ Fetch (request)

​ Service Worker also provides an fetchevent, which is triggered whenever a request or resource request such as html, css, js, etc. is made in the page controlled by the Service Worker fetch. We can intercept the request at this stage and use a custom response in combination with caching to respond to the request. Note: ajaxRequests do not trigger this event.

​ Usually when the requested resource exists in the cache, we will get the resource from the cache instead of from the server. If there is not in the cache, then we will use another request to get the resource from the server and store the resource in the cache for the next request or offline request.

self.addEventListener("fetch", (e) => {
    
    
  e.respondWith(
    (async () => {
    
    
      // 从缓存中获取资源
      const r = await caches.match(e.request);
      console.log(`Service Worker正在请求资源: ${
      
      e.request.url}`);
      if (r) {
    
    
        // 如果缓存中存在资源 则直接返回缓存中的资源
        return r;
      }
      // 如果缓存中没有 则去服务器请求资源
      const response = await fetch(e.request);
      const cache = await caches.open(cacheName);
      console.log(`Service Worker 缓存新资源: ${
      
      e.request.url}`);
      // 将请求的资源存储到缓存中 
      cache.put(e.request, response.clone());
      // 将请求结果缓存
      return response;
    })(),
  );
});

fetch​ The event object of this event eventcontains a respondWith()method that prevents the browser's default fetchrequest operation and allows custom requests. responseFor more information, please refer to: FetchEvent.respondWith() .

2、Web App Manifest

​ Web App Manifest (Web Application Manifest) is a JSON file that complies with the W3C specification. It is used to define how the PWA installed client should be displayed and run on the device, such as the name, icon, startup method, etc. of the application. is required to implement a PWA. Through this file, users can install the PWA application on the user's home screen, making it more like a client of a native application.

​ There are a lot of application information that can be defined in this file, the more commonly used ones are as follows:

① name

​ This field defines the full name of the PWA application and is a required basic field in Web App Manifes. This name is typically displayed as the app name in the app store and also in the title bar when the app launches.

"name": "学科网PWA示例"
② short_name

​ This field defines the abbreviation of the PWA application, and try to control it within 12 characters. When the application is installed on the desktop, due to limited space, the abbreviation is usually displayed, but the specific display may vary depending on the device, browser or nameoperation short_name. Different systems, for example: in the macos system, namethe fields are displayed uniformly.

"short_name": "PWA示例"
③ icons

​ This field defines the icon installed by the application on the desktop. The attribute value is an array, and the array element is an object. The object contains three attributes, src, sizesand type, which respectively represent the icon address, icon size, and icon MIME type.

  • src: specifies the location of the icon file, and the field value can be a manifestrelative URL relative to the file, or an absolute network URL.
  • sizes: Indicates the size of the icon. 宽×高The width and height of the icon are specified in the form of px. The default unit is 512×512.
  • type: Indicates MIMEthe media type of the icon to help the browser select the appropriate icon file, for example: image/png, image/jpegetc.

​ The field attribute value array needs to define at least one icon element, and can also define multiple icon elements in different formats, so as to provide users with the best icon effect. Each browser chooses whichever icon is closest to the specification it needs, depending on its needs and the operating system it has installed. There are many rules for icon selection, mainly including size matching, type matching, device type matching and other rules.

"icons": [
   {
    
    
      "src": "icons/512.png",
      "type": "image/png",
      "sizes": "512x512"
   },
   {
    
    
      "src": "icons/1024.png",
      "type": "image/png",
      "sizes": "1024x1024"
   }
]
④ start_url

​ This field defines the starting URL of the PWA application. When the user clicks the icon to open the program, the page corresponding to this URL will be loaded. It can be a relative path relative to the manifest file, or an absolute path. It is recommended to use an absolute path. If the homepage of the PWA application is the root directory of the website, then set this field to /. If this field is not set, the URL when the PWA application is installed will be used as the value of this field by default.

"start_url": "./index.html"
⑤ display

​ This field defines how to open the PWA application. There are four types of field values:

  • standalone(Recommended): The application will open in an independent window, similar to a native application, without browser features such as a navigation bar.

insert image description here

  • fullscreen: The app will open in full screen mode, hiding the browser's address bar and toolbar. Due to the limitations of the computer operating system, the performance of this field value is standaloneconsistent with .

  • minimal-ui: The application opens an independent window, but retains some browser navigation functions, such as back and refresh functions.

insert image description here

  • browser: The app will open as a regular browser webpage, similar to setting a shortcut to a webpage. However, due to the limitation of the computer operating system, the performance of this field value is standaloneconsistent with .

    "display": "standalone"
    
⑥ id

​ This field is used as the unique identifier of the PWA application. If not set, the default start_urlvalue is the field value.

"id": "xkw-pwa"
⑦ background_color

​ This field defines the background color of the window after the PWA application window is opened and before the style sheet is loaded. The field value supports keywords (red, green, etc.), hexadecimal color values ​​(#FFFFFF, #CCCCC, etc.) and RGB colors Values ​​(rgb(255,255,255), etc.), but it is not recommended to use rgba()colors with transparency, because the display effect of each browser may be quite different. However, Safari on iOS and iPadOS and some desktop browsers currently ignore this field.

"background_color": "#000000",
⑧ theme_color

​ This field defines the theme color of the window of the PWA application, which will affect the color of the window toolbar, header title bar and other areas. The segment value supports keywords (red, green, etc.), hexadecimal color values ​​(#FFFFFF, #CCCCC, etc.) and RGB color values ​​(255, 255, 255, etc.). But this attribute will be <meta name="theme-color" content="#ccc">overridden by the theme color set by the label.

"theme_color": "#3880FF"
⑨ Other properties

​ 。。。

3、Push Notification

Push​and Notificationare two independent APIs, Pushused to receive information pushed by the server and Notificationused to push information to users. Both need to be called to run inside the Service Worker.

​ For details, see: Push Notification

3. How to develop a PWA application Demo?

1. Create a demo folder to store related files

insert image description here

2. Create manifest.json file and set PWA application information
{
    
    
  "name": "猪猪侠的PWA示例", 
  "short_name": "PWA示例",
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "red",
  "theme_color": "#ccc",
  "icons": [
    {
    
    
      "src": "/icons/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
    
    
      "src": "/icons/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

3. Create icons folder to store PWA application icon files

​ store the following two icon files:

insert image description here
insert image description here

4. Create the main.css file and set the page style
h3 {
    
    
  color: red;
}
5. Create sw.js file and set Service Worker related logic

​ Here we only need to directly write the processing logic of Service Worker:

// 缓存的key值,用于区别新旧版本缓存
var cacheStorageKey = 'minimal-pwa-2'
// 设置初始需要缓存的文件
var cacheList = [
  '/',
  'index.html',
  'main.css',
  '/icons/android-chrome-512x512.png'
]
// 监听安装事件 并在此阶段 缓存基本资源
self.addEventListener('install', e => {
    
    
  e.waitUntil(
    caches.open(cacheStorageKey)
      .then(
        // 缓存基本资源
        cache => cache.addAll(cacheList)
      )
      .then(() =>
        // 当脚本更新时 使新版Service Worker强制进入activate状态
        self.skipWaiting()
      )
  )
})
// 监听fetch请求事件
self.addEventListener('fetch', function (e) {
    
    
  // 拦截相关请求
  e.respondWith(
    // 如果缓存中已经有请求的数据就终止请求 直接返回缓存数据
    caches.match(e.request).then(async function (response) {
    
    
      if (response != null) {
    
    
        return response
      }
      // 否则就重新向服务端请求
      const res = await fetch(e.request)
      // 这块需要结合具体业务具体分析 我这里的示例逻辑是无脑全部缓存
      // 请求成功后将请求的资源缓存起来 后续请求直接走缓存
      const cache = await caches.open(cacheStorageKey)
      cache.put(e.request, res.clone())
      // 将请求的资源返回给页面。
      return res;
    })
  )
})
// 监听激活事件
self.addEventListener('activate', function (e) {
    
    
  e.waitUntil(
    //获取所有cache名称
    caches.keys().then(cacheNames => {
    
    
      return Promise.all(
        // 获取缓存中所有不属于当前版本cachekey下的内容
        cacheNames.filter(cacheNames => {
    
    
          return cacheNames !== cacheStorageKey
        }).map(cacheNames => {
    
    
          // 删除不属于当前版本的cache缓存数据
          return caches.delete(cacheNames)
        })
      )
    }).then(() => {
    
    
      // 无须刷新页面 即可使新版server worker接管当前页面
      return self.clients.claim()
    })
  )
})
6. Create the main file index.html, set the page DOM, and reference various resources
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Hello PWA</title>
  <meta name="viewport"
    content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <link rel="stylesheet" href="main.css">
  <link rel="manifest" href="manifest.json">
</head>

<body>
  <h3>Hello 猪猪侠的PWA</h3>
</body>
<script>
  // 检测浏览器是否支持SW
  if ('serviceWorker' in navigator) {
      
      
    // 为当前页面注册Service Worker
    navigator.serviceWorker.register('./sw.js')
      .then(function (registartion) {
      
      
        console.log('当前浏览器支持sw:', registartion.scope);
        console.log('Service Worker注册成功', registartion);
      })
  }
</script>
</html>
7. Deploy to the server (https) or use it in the local environment

Take the local environment as an example, using VSCode as an auxiliary tool:

① In VSCode, right-click the index.html file, select Open with live Serverthe option, and run the page:

insert image description here

② F12 console, check whether the Service Worker is registered successfully:
insert image description here

③ Then click Application, select Service Workers on the left, and check whether the sw script is running normally:
insert image description here

④ Click Cache Storage on the left, select the cacheStorageKey we defined - the current domain name address, and check whether the initial resources (resources in the cacheList array defined in the sw.js file) are cached:
insert image description here

⑤ Click Network, select All, refresh the page, and check the requested resources:
insert image description here

⑥ After the last refresh, all relevant resources have been cached. Refresh the page again, and all resources will be obtained from the cache after passing through the Service Worker:
insert image description here

⑦ Cut off the network by selecting the Offline option in NetWork, and check whether the page can be displayed normally by using the cache when there is no network:
insert image description here

⑧ Other operations. . .

4. Relevant information

PWA Google Docs

MDN documentation for PWAs

Service Worker

Service Worker Lifecycle

Web App Manifes

Guess you like

Origin blog.csdn.net/weixin_45092437/article/details/132385204