ASP.NET Progressive application of core blazer webassembly (PWA)

Keywords: JSON network Mobile Firefox

Blazor supports progressive application development, or PWA. Using PWA mode can make web application have the experience of native application.

What is PWA

PWA application refers to those web applications developed by using specified technology and standard pattern, which will give them the characteristics of web application and native application at the same time.
For example, web applications are easier to discover - it's obviously easier and faster to visit a website than to install applications, and you can share web applications through a link.
On the other hand, native applications and operating systems can be more perfectly integrated, and thus provide users with a seamless user experience. You can install the app to make it run offline, and users prefer to access their favorite apps by clicking on the icon on the home page rather than using a browser.
PWA gives us the ability to create applications with both of these advantages.
This is not a new concept - such an idea has appeared many times in the past on the web platform through many methods. Incremental enhancement and responsive design have enabled us to build mobile friendly websites. It has become possible to run and install web applications offline in the Firefox OS ecosystem many years ago.
PWAs, not only that, but also provides all or even more features to make the web better.




Reference from MDN

To put it mildly, PWA can make your web program run like a normal application, with desktop icon, offline, no browser address bar, and everything looks like a normal program / APP.

New Blazor PWA program

Use VS to create a new Blazor program, select web assembly mode, and check PWA support.

The Blazor program that supports PWA has several more things:

  1. manifest.json
  2. service-worker.js

manifest.json

manifest.json It is a list file. When the program is installed on the device, it will read the information, name, icon, language, etc.

{
  "name": "BlazorPWA",
  "short_name": "BlazorPWA",
  "start_url": "./",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#03173d",
  "icons": [
    {
      "src": "icon-512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ]
}

service-worker.js

Service worker is used to run some background tasks. It is isolated from the browser main process, that is to say, it is separate from the original JavaScript runtime, of course, it will not block the page. We can use it to complete some functions, such as filtering all fetch/xhr requests, which requests go to cache and which don't go to cache; for example, we can secretly pull some data for you to cache in the background.

// Caution! Be sure you understand the caveats before publishing an application with
// offline support. See https://aka.ms/blazor-offline-considerations

self.importScripts('./service-worker-assets.js');
self.addEventListener('install', event => event.waitUntil(onInstall(event)));
self.addEventListener('activate', event => event.waitUntil(onActivate(event)));
self.addEventListener('fetch', event => event.respondWith(onFetch(event)));

const cacheNamePrefix = 'offline-cache-';
const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/ ];
const offlineAssetsExclude = [ /^service-worker\.js$/ ];

async function onInstall(event) {
    console.info('Service worker: Install');

    // Fetch and cache all matching items from the assets manifest
    const assetsRequests = self.assetsManifest.assets
        .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
        .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
        .map(asset => new Request(asset.url, { integrity: asset.hash }));
    await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
}

async function onActivate(event) {
    console.info('Service worker: Activate');

    // Delete unused caches
    const cacheKeys = await caches.keys();
    await Promise.all(cacheKeys
        .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName)
        .map(key => caches.delete(key)));
}

async function onFetch(event) {
    let cachedResponse = null;
    if (event.request.method === 'GET') {
        // For all navigation requests, try to serve index.html from cache
        // If you need some URLs to be server-rendered, edit the following check to exclude those URLs
        const shouldServeIndexHtml = event.request.mode === 'navigate';

        const request = shouldServeIndexHtml ? 'index.html' : event.request;
        const cache = await caches.open(cacheName);
        cachedResponse = await cache.match(request);
    }

    return cachedResponse || fetch(event.request);
}

There are 2 services in the project- worker.js One is that there is no logic in development, and the other is that there are some cached logic in release.

Run it


If it is a PWA program, there is a + icon in the browser address bar. Click to install the program locally.

After installation, an icon will be generated on the desktop, and an interface without browser address bar will be opened.

Such a PWA program can already run.




Run offline

If it's just like this, there is no browser address bar, then PWA is too unattractive. I think the biggest charm of PWA is that it can run offline and can still run without network, so it is like a program written in the native.

Modify service worker

The offline principle is also very simple, that is, the requested data is cached, generally the Get request is cached, such as various page pictures, etc.

// In development, always fetch from the network and do not enable offline support.
// This is because caching would make development more difficult (changes would not
// be reflected on the first load after each change).

self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
self.addEventListener('install', event => event.waitUntil(onInstall(event)));

async function onInstall(event) {
    console.info('Service worker: Install');
}


async function onFetch(event) {
    let cachedResponse = null;
    const cache = await caches.open('blazor_pwa');
    if (event.request.method === 'GET') {
        const request = event.request;
        cachedResponse = await caches.match(request);
        if (cachedResponse) {
            return cachedResponse;
        }
        var resp = await fetch(event.request)
        cache.put(event.request, resp.clone());
        return resp;
    }

    return fetch(event.request);
}

Modify sevice-worker.js , cache all GET requests. For the convenience of the illustration, the situation is obviously not so simple and rough. In order to be able to cache pages, it is obvious that you must run it online once successfully.

Simulation offline

When we modify the above js, and then go online once, we can see that all the GET requests are cached.

We can use chrome to simulate offline situations:

Select offline mode and refresh our page. If it still works normally, it means it can run offline.



summary

Using Blazor can develop PWA application quickly. By using the features of PWA and Blazor Webassembly, a similar desktop can be developed. Or this is another solution of cross platform desktop application development besides electron.

Posted by bosco500 on Wed, 24 Jun 2020 19:55:24 -0700