preface

In traditional Web applications, you can usually access the Web only by entering the corresponding URL in the browser’s address bar, or creating the Web address on the desktop by clicking and opening it in the browser.

In traditional mode, ICONS, splash screens, theme colors, view modes, screen orientation, and so on cannot be customized or controlled.

These functions can now be accomplished through features in the PWA standard that make the path to Web applications shorter and more visible, as described below.


The installation

Installing Web applications requires some preparation.

The installation conditions

Json file in the manifest.json file and add it to the page:

<link rel="manifest" href="./manifest.json" />
Copy the code

The following fields must be configured in the manifest.json file:

{
  "short_name": "Short app name"."name": "Long app name"."icons": [{"src": "icons/192.png"."sizes": "144x144"."type": "image/png"}]."start_url": "."."display": "standalone",}Copy the code

Requirements:

  • Run in HTTPS.
  • Serviceworker must be registered and running.
  • It must be in the manifesticonsAnd at least144x144PNGThe image.
  • In the manifestdisplaySet tostandaloneorfullscreen.
  • It must be in the manifestnameorshort_name.
  • It must be in the manifeststart_url.
  • In the manifestprefer_related_applicationsNot set or set tofalse.

For detailed setup information on manifest, refer to the MANIFEST feature article written earlier.

Display installation prompts

Once configured as required, open the web site in the browser.

Android Chrome side

After Chrome 68, when the conditions for installing an application are met, the Mini Info bar pops up at the bottom of the browser. When you click the info bar, the Add to home screen dialog box is displayed. Click Add to complete the installation, and the app icon appears on the page.

Note: For Chrome 68-75, you can’t control the display of the Mini message bar by code. Chrome 76 and later supports code control. When the user clicks the “X” on the Mini message bar, the browser will not be prompted by the Mini bar for at least three months, but the event layer is not affected, which can be achieved by code.

PC Chrome side

Chrome 73 now supports Web installation from PC to desktop

Customize installation timing

When the Web application is fit for installation, the beforeInstallPrompt event is triggered and a prompt to install to the screen pops up. Based on this event, we can control whether the installprompt is displayed and when to install.

Beforeinstallprompt event is triggered every time the page is entered if the application is not installed, not if it is installed. This event will continue to be triggered after the user uninstalls the application.

Install prompt event capture logic:

var installPromptEvent = null;

window.addEventListener('beforeinstallprompt', (event) => {
  event.preventDefault();  // Chrome <= 67 can block display
  installPromptEvent = event; // Get a reference to the event
  document.querySelector('#btn-install').disabled = false; // Update the installation UI to inform the user that the installation is available
});
Copy the code

The Prompt dialog box is displayed

A manual display of the installation dialog can be triggered by calling the prompt() method in the captured beforeInstallPrompt event reference.

Obtained through the outcome in the Promise result of the event userChoice property.

User clicks install logic:

document.querySelector('#btn-install').addEventListener('click', () = > {if( !installPromptEvent ) {
    return;
  }

  installPromptEvent.prompt();
  installPromptEvent.userChoice.then( choiceResult= > {
    if (choiceResult.outcome === 'accepted') {
      console.log('User has agreed to add to desktop')}else {
      console.log('User unadded to desktop')}})})Copy the code

Event handling has been installed

You can use AppInstalled to listen to whether the application is installed:

window.addEventListener('appinstalled', (evt) => {
  console.log('Installed to desktop screen');
});
Copy the code

Environmental judgment

You can use the display-mode attribute to determine whether the current application is opened by entering the URL in the browser or by using the desktop icon, and then set different interaction styles according to requirements.

Assume that the display set in the manifest is standalone

Js layer judgment:

if (window.matchMedia('(display-mode: standalone)').matches) {
  console.log('the display - mode is standalone');
}
Copy the code

CSS layer judgment:

@media all and (display-mode: standalone) {
  /** Custom style **/
}
Copy the code

Safari:

if (window.navigator.standalone === true) {
  console.log('the display - mode is standalone');
}
Copy the code

Updates to applications

After the Web application is installed on the desktop, the update problem after the manifest is modified is different for each platform.

The Android end

On Android, Chrome checks the currently installed MANIFEST against the live Manifest when launching a Web application. If an update is required, it will automatically enter the update queue in wifi environment.

Trigger update rule:

  • Update checking occurs only when the Web application is started. Launching Chrome directly does not trigger update checking for a given Web application.
  • Chrome checks for updates every other day or every 30 days. Daily checking for updates happens most of the time. In cases where the update server is unable to provide updates, it switches to a 30-day interval.
  • Clearing Chrome’s data (via “Clear All Data” in Android Settings) resets the update timer.
  • If the Web Manifest URL is not changed, Chrome will only update the Web application. If you modify the manifest path of a web page, such as from/manifest.jsonChange to/manifest2.json, the Web application will not be updated. (This is highly recommended)
  • Only Web applications created by the official Chrome (Stable/Beta/Dev/Canary) will be updated. It doesn’t work for Chromium (org.chromium.chrome).
  • Update checking may be delayed until the connection is available with wifi.

PC

Update is not supported on PC, but may be supported later.


Compatible with

The current compatibility of this feature across platforms is as follows:

IOS adaptation

IOS requires a separate feature Meta for desktop ICONS, splash screens, app text, and theme colors.

Apple-touch-icon: indicates the application icon

Need to add:

<link rel="apple-touch-icon" href="/custom_icon.png">
Copy the code

Adaptation with different resolutions:

<link rel="apple-touch-icon" href="touch-icon-iphone.png">
<link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad.png">
<link rel="apple-touch-icon" sizes="180x180" href="touch-icon-iphone-retina.png">
<link rel="apple-touch-icon" sizes="167x167" href="touch-icon-ipad-retina.png">
Copy the code

Apple-touch-startup-image: startup screen

Need to add:

<link rel="apple-touch-startup-image" href="/launch.png">
Copy the code

Apple-mobile-web-app-title: Title of the app icon

By default, the value in

is used. If you need to change it, you need to specify meta.

<meta name="apple-mobile-web-app-title" content="Application title">
Copy the code

Apple-mobile-web-app-status-bar-style: Specifies the appearance style of the application status bar

For example, set to black:

<meta name="apple-mobile-web-app-status-bar-style" content="black">
Copy the code

Compatible adaptation library

Normally, all features are subject to specification constraints, but Safari above is not, which increases the developer’s development costs.

So here’s an adaptation script, just write the manifest definitions in the specification, and leave the rest to the script.

(function(){function h(){var a=document.head.querySelector('link[rel="manifest"]'),b=a? a.href:"",d=A([b,window.location]);Promise.resolve().then(function(){if(! b)throw'can\'t find 
       \ ' ';var a={};"use-credentials"===b.crossOrigin&&(a.credentials="include");return window.fetch(b,a)}).then(function(a){return a.json()}).then(function(a){return B(a,d)}).catch(function(a){return console.warn("pwacompat.js error",a)})}function A(a){for(var b={},d=0; d<a.length; b={c:b.c},++d){b.c=
  a[d];try{return new URL("",b.c),function(a){return function(b){return(new URL(b,a.c)).toString()}}(b)}catch(n){}}return function(a){return a}}function t(a,b){a=document.createElement(a);for(var d in b)a.setAttribute(d,b[d]);document.head.appendChild(a);return a}function c(a,b){b&&(!0===b&&(b="yes"),t("meta", {name:a,content:b}))}function B(a,b){function d(b,d,f){var k=b.width,c=b.height,e=window.devicePixelRatio; b=u({width:k*e,height:c*e}); b.scale(e,e); b.fillStyle=a.background_color||"#f8f9fa"; b.fillRect(0.0,k,c); b.translate(k/2,(c- 32) /2); b.font="24px HelveticaNeue-CondensedBold"; b.fillStyle=r?"white":"black"; k=b.measureText(v).width; f&&(c=f.width/e,e=f.height/e,128<e&&(c/=e/128,e=128),48<=c&&48<=e&&(b.drawImage(f,c/2 -,e/2 -,c,e),b.translate(0,e/2+32))); b.fillText(v,k/2 -.0); f=document.createElement("link"); f.setAttribute("rel"."apple-touch-startup-image"); f.setAttribute("media"."(orientation: "+d+")"); f.setAttribute("href",b.canvas.toDataURL());return f}function n(a){var b=d(window.screen,"portrait", a); a=d({width:window.screen.height,height:window.screen.width},"landscape",a); w.forEach(function(a){return a.remove()});document.head.appendChild(b);document.head.appendChild(a); w.add(b); w.add(a)}varg=a.icons||[]; g.sort(function(a,b){return parseInt(b.sizes,10) -parseInt(a.sizes,10)});var x=g.map(function(a){a={rel:"icon".href:b(a.src),sizes:a.sizes}; t("link",a);if(p)return a.rel="apple-touch-icon",t("link",a)}),q=a.display; g=- 1! ==C.indexOf(q); c("mobile-web-app-capable",g); D(a.theme_color||"black");
  E&&(c("msapplication-starturl",a.start_url||"/"),c("msapplication-TileColor",a.theme_color));document.head.querySelector('[name="theme-color"]')||c("theme-color",a.theme_color);varh=F(a.orientation); c("x5-orientation",h); c("screen-orientation",h);"fullscreen"===q? (c("x5-fullscreen"."true"),c("full-screen"."yes")):g&&(c("x5-page-mode"."app"),c("browsermode"."application"));if(p){var r=y(a.background_color||"#f8f9fa"),v=a.name||a.short_name||document.title; (q=G(a.related_applications))&&c("apple-itunes-app"."app-id="+q); c("apple-mobile-web-app-capable",g); c("apple-mobile-web-app-title",v);var w=new Set; n(null);if(x.length){var m=x[0],l=newImage; l.crossOrigin="anonymous"; l.onload=function(){n(l);if(a.background_color){var b=z(l,a.background_color);null! ==b&&(m.href=b,x.slice(1).forEach(function(b){var d=newImage; d.crossOrigin="anonymous"; d.onload=function(){var c=z(d,a.background_color,!0); b.href=c}; d.src=b.href}))}}; l.src=m.href}}}function G(a){varb; (a||[]).filter(function(a){return"itunes"===a.platform}).forEach(function(a){a.id?
  b=a.id:(a=a.url.match(/id(\d+)/))&&(b=a[1])});return b}function F(a){a=String(a||""); a=a.substr(0.3);return"por"===a?"portrait":"lan"===a?"landscape":""}function D(a){if(p||H){var b=y(a);if(p)c("apple-mobile-web-app-status-bar-style",b?"black":"default");else{try{var d=Windows.UI.ViewManagement.ApplicationView.getForCurrentView().titleBar}catch(n){d=null}null===d?console.debug("UWP no titleBar"):(d.foregroundColor=r(b?"black":"white"),d.backgroundColor=r(a))}}}function r(a){a=m(a);return{r:a[0].g:a[1].b:a[2].a:a[3]}}function m(a){varb=u(); b.fillStyle=a; b.fillRect(0.0.1.1);return b.getImageData(0.0.1.1).data}function y(a){a=m(a).map(function(a){a/=255;return03928.>a? a/12.92:Math.pow((a+055.) /1.055.2.4)});return 3<Math.abs(1.05/ (2126.*a[0] +7152.*a[1] +0722.*a[2] +.05))}function z(a,b,d){d=void 0===d? !1:d;varc=u(a); c.drawImage(a,0.0);if(! d&&255==c.getImageData(0.0.1.1).data[3])return null; c.globalCompositeOperation="destination-over"; c.fillStyle=b; c.fillRect(0.0,a.width,a.height);return c.canvas.toDataURL()}
  function u(a){a=void 0===a? {width:1.height:1}:a;var b=a.height,c=document.createElement("canvas"); c.width=a.width; c.height=b;return c.getContext("2d")}if("fetch"in window) {var C=["standalone"."fullscreen"."minimal-ui"],p=navigator.vendor&&- 1! ==navigator.vendor.indexOf("Apple"),E=navigator.userAgent&&- 1! ==navigator.userAgent.indexOf("Edge"),H="undefined"! = =typeof Windows;"complete"= = =document.readyState? h():window.addEventListener("load",h)}})();
Copy the code

Invoke the address: http://unpkg.alipay.com/[email protected]/pwacompat.min.js.

Use:

<link rel="manifest" href="./manifest.json" />
<script src="http://unpkg.alipay.com/[email protected]/pwacompat.min.js" crossorigin="anonymous"></script>
Copy the code

Blog name: Wang Leping blog

CSDN blogs at blog.csdn.net/lecepin