天天看點

PWA技術及其使用者體驗設計

實驗室最近多了一個實驗産品MAX:群控手機的項目。主要包括:後端服務、web前端用戶端、安卓app用戶端。涉及到的程式設計語言:Java、Nodejs。技術上主要涉及安卓的MediaProjection API、配合websocket來實作。

MediaProjection 提供了錄屏功能;websocket主要是傳輸友善,可以做到實時。

PWA技術及其使用者體驗設計

今天主要介紹下web前端用戶端的實作,主要使用了PWA技術。

- 什麼是PWA?

PWA技術及其使用者體驗設計

PWA全稱Progressive Web Apps,漸進增強 Web 應用程式,它可以離線運作,并且可以在運作的系統中選擇性安裝,它從外觀還是執行效果來看,與一般應用程式無異。

不知大家體驗過微軟的郵件服務沒?Outlook.com已經完成了PWA版本,可以在浏覽器裡面像本地應用一樣直接打開即用。

比如我使用的mac,添加了一個PWA應用之後,底部菜單欄多了一個應用的icon,效果如下:

PWA技術及其使用者體驗設計

就是mixlab那個logo

PWA是一系列技術的集合,裡面最核心的是一個叫“app shell”的概念。

- 什麼是App shell?

我們先了解下,渲染網站主要有兩種方法:在伺服器上或在用戶端上。

-伺服器端渲染(SSR)

意味着網站每次都是在伺服器上渲染,是以它提供了更快的首次加載,但是在頁面之間跳轉需要每次都下載下傳所有内容,因而它的加載速度往往會比較慢。

-用戶端渲染(CSR)

頁面是在用戶端(浏覽器)渲染的,因而加載速度往往取決于浏覽器的性能,通路速度會比較快,但是在開始時需要更多的初始下載下傳(首次通路時網站速度較慢),以保證整個網站其他頁面實作用戶端渲染所需要的資料。

兩種方式各有利弊,而PWA使用的方法是“app shell”,它混合了SSR和CSR的方式。

App shell,可以了解為程式的外殼。App shell意圖盡快加載最小的使用者界面,然後緩存它,以便在後續通路時可以離線使用,然後加載應用程式的所有内容。這樣,下次有人從裝置通路應用程式時,UI立即從緩存加載,并從伺服器請求新内容(如果它已在緩存中不可用)。

一個App shell的代碼結構如下:

<!DOCTYPE html>
<html lang="zh">
<head>
        <meta charset="utf-8">
  <title>Max</title>
  <meta name="description" content="app的介紹">
  <meta name="author" content="作者">
  <meta name="theme-color" content="#B12A34">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta property="og:image" content="icons/icon-512.png">
  <link rel="shortcut icon" href="favicon.ico">
  <link rel="stylesheet" href="style.css">
  <link rel="manifest" href="manifest.json">
  <script src="app.js" defer></script>
</head>
<body>
<header>
  <p>MAX-demo</p>
</header>
<main>
  <h1>HELLO WORLD</h1>
  <button id="notifications">Request notifications</button>
  <section id="content">
    // Content inserted in here
  </section>
</main>
<footer>
  <p>© max 2012-2018, created and maintained by shadow.</p>
</footer>
</body>
</html>           

複制

複制

為了配合app shell,需要一個叫Service Worker API的支援。

- Service Worker

Service Worker API可以完成2種任務,一種是緩存App shell所需的資料,另一種是如果你有比較耗時的計算,你可以把它們從主線程中抽離出來,在Service Worker中進行計算,最後在它們計算完畢的時候從Service Worker中取得計算結果。

Service Worker主要由3項技術構成:

  • 緩存機制是依賴 Cache API 實作的
  • 依賴 HTML5 fetch API 發起網絡請求
  • 依賴 Promise 實作異步

service worker是需要注冊的,我們在app.js中,輸入:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/serviceWorker.js', { scope: '/' })
            .then(function(registration) {
                // 注冊成功
                console.log('ServiceWorker registration successful with scope: ', registration.scope);
            })
            .catch(function(err) {
                // 注冊失敗
                console.log('ServiceWorker registration failed: ', err);
            });
    });

};           

複制

即可,使用上我們編寫好的serviceWorker.js檔案。

serviceWorker.js主要對有install跟fetch事件進行監聽,對cache進行操作,達到緩存的目的。

let cacheName = 'max-v1';
let contentToCache = [
    '/',
    '/index.html',
    '/style.css',
    '/app.js'
];

// 對app shell和主體内容(content)裡面的資料建立緩存
self.addEventListener('install', function(e) {
    console.log('[Service Worker] Install');
    e.waitUntil(
        // 安裝成功後操作 CacheStorage 緩存,使用之前需要先通過 caches.open() 打開對應緩存空間。
        caches.open(cacheName).then(function(cache) {
            console.log('[Service Worker] Caching all: app shell and content');
            // 通過 cache 緩存對象的 addAll 方法添加 緩存
            return cache.addAll(contentToCache);
        })
    );
});


//如果條件允許,service worker将從緩存中請求content中所需的資料,進而提供離線應用功能
self.addEventListener('fetch', function(e) {
    e.respondWith(
        caches.match(e.request).then(function(r) {
            console.log('[Service Worker] Fetching resource: ' + e.request.url);
            return r || fetch(e.request).then(function(response) {
                return caches.open(cacheName).then(function(cache) {
                    console.log('[Service Worker] Caching new resource: ' + e.request.url);
                    cache.put(e.request, response.clone());
                    return response;
                });
            });
        })
    );
});           

複制

兩種方式可以比較一下:

- install

優點是第二次通路即可離線,缺點是需要将需要緩存的 URL 在編譯時插入到腳本中,增加代碼量和降低可維護性;

- fetch

優點是無需更改編譯過程,也不會産生額外的流量,缺點是需要通路過一次才能離線使用。

是以,在設計技術架構的時候,需要考慮到2種方式的優缺點。

除了配置serviceWorker.js之外,我們還需要配置manifest.json檔案。

- 添加至桌面功能

serviceWorker使得網頁在速度跟體驗上接近原生app,除此之外,還需要引導使用者添加pwa應用到桌面,以友善下次使用。

實作 PWA 應用添加至桌面的功能,除了要求站點支援 HTTPS 之外,需要準備 manifest.json 檔案去配置應用的圖示、名稱等資訊。一個基本的 manifest.json 應包含如下資訊:

{
    "name": "max-demo-v1",
    "short_name": "max",
    "description": "demo",
    "icons": [{
        "src": "icons/mix-logo.png",
        "sizes": "72x72 96x96 128x128 256x256",
        "type": "image/png"
    }],
    "start_url": "/index.html",
    "display": "fullscreen",
    "theme_color": "#4a4a4a",
    "background_color": "#eeeeee"
}           

複制

運作之後,在浏覽器位址欄右側,可以看到一個+号,點選安裝。

PWA技術及其使用者體驗設計

另外,調試可以在chrome的Application面闆中進行檢視。

由于PWA的api不是所有浏覽器都支援,因而,你還需要注意使用caniuse.com 來檢視主流浏覽器的支援情況。

- 如何告知普通使用者什麼是離線模式?或者什麼是PWA?

PWA技術及其使用者體驗設計

這是體驗設計上需要注意的地方,我們應該認識到并不是每個使用者都是技術出身,都對PWA的概念了解得很清楚。因而,使用者體驗設計需要為使用者提供指導,以便他們可以了解什麼是PWA(或者離線模式)。

确實,離線模式比PWA(漸進式)更為容易了解,但是離線模式對每個人來說都是一個全新的心智模式。通俗來講,您需要告訴使用者當他們無法連接配接上網絡時會發生什麼變化。比如:

哪些功能無法使用;

或者是頁面上的資料是什麼時間更新的;

目前的網絡連接配接情況;

等等。

除此之外,設計上要考慮首次加載的問題,如首次加載時間過長,需要設計動畫提示,可以把加載的檔案内容簡要告知使用者,讓使用者知道網頁正在加載,而不是“當機了”。

下一步,拟內建TensorFlowJS,探索下可能性。