日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

如何把網站改成PWA,首先我們要了解知道什么是PWA

1. PWA是什么

Progressive Web Apps (下文以“PWAs”代指) 是一個令人興奮的前端技術的革新。PWAs綜合了一系列技術使你的 web app表現得就像是 native mobile app。相比于純 web 解決方案和純 native 解決方案,PWAs對于開發者和用戶有以下優點:

  • 你只需要基于開放的 W3C 標準的 web 開發技術來開發一個app。不需要多客戶端開發。
  • 用戶可以在安裝前就體驗你的 app。
  • 不需要通過 AppStore 下載 app。app 會自動升級不需要用戶升級。
  • 用戶會受到‘安裝’的提示,點擊安裝會增加一個圖標到用戶首屏。
  • 被打開時,PWA 會展示一個有吸引力的閃屏。
  • chrome 提供了可選選項,可以使 PWA 得到全屏體驗。
  • 必要的文件會被本地緩存,因此會比標準的web app 響應更快(也許也會比native app響應快)
  • 安裝及其輕量 -- 或許會有幾百 kb 的緩存數據。
  • 網站的數據傳輸必須是 https 連接。
  • PWAs 可以離線工作,并且在網絡恢復時可以同步最新數據。

雖然PWA不是所有瀏覽器都支持,但是我們不需要擔心, 因為pwa是漸進增強的, 你的app仍然可以運行在不支持 PWA 技術的瀏覽器里。用戶不能離線訪問,不過其他功能都像原來一樣沒有影響。綜合利弊得失,沒有理由不把你的 app 改進為 PWA。

2. 步驟

將你的網站改進為一個 Progressive Web App 總共有三個必要步驟:

2.1 第一步:開啟 HTTPS

由于一些顯而易見的原因,PWAs 需要 HTTPS 連接。HTTPS 在示例代碼中并不是必須的,因為 Chrome 允許使用 localhost 或者任何 127.x.x.x 的地址來測試。你也可以在 HTTP 連接下測試你的 PWA,你需要使用 Chrome ,并且輸入以下命令行參數:

  • --user-data-dir
  • --unsafety-treat-insecure-origin-as-secure

2.2 第二步:創建一個 Web App Manifest

manifest 文件提供了一些我們網站的信息,例如 name,description 和需要在主屏使用的圖標的圖片,啟動屏的圖片等。

manifest文件是一個 JSON 格式的文件,位于你項目的根目錄。它必須用Content-Type: application/manifest+json 或者 Content-Type: application/json這樣的 HTTP 頭來請求。這個文件可以被命名為任何名字,在示例代碼中他被命名為 /manifest.json:

{
  "name"              : "PWA Website",
  "short_name"        : "PWA",
  "description"       : "An example PWA website",
  "start_url"         : "/",
  "display"           : "standalone",
  "orientation"       : "any",
  "background_color"  : "#ACE",
  "theme_color"       : "#ACE",
  "icons": [
    {
      "src"           : "/images/logo/logo072.png",
      "sizes"         : "72x72",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo152.png",
      "sizes"         : "152x152",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo192.png",
      "sizes"         : "192x192",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo256.png",
      "sizes"         : "256x256",
      "type"          : "image/png"
    },
    {
      "src"           : "/images/logo/logo512.png",
      "sizes"         : "512x512",
      "type"          : "image/png"
    }
  ]
}

在頁面的<head>中引入:

<link rel="manifest" href="/manifest.json">

manifest 中主要屬性有:

  • name —— 網頁顯示給用戶的完整名稱
  • short_name —— 當空間不足以顯示全名時的網站縮寫名稱
  • description —— 關于網站的詳細描述
  • start_url —— 網頁的初始 相對 URL(比如 /)
  • scope —— 導航范圍。比如,/app/的scope就限制 app 在這個文件夾里。
  • background-color —— 啟動屏和瀏覽器的背景顏色
  • theme_color —— 網站的主題顏色,一般都與背景顏色相同,它可以影響網站的顯示
  • orientation —— 首選的顯示方向:any, natural, landscape, landscape-primary, landscape-secondary, portrait, portrait-primary, 和 portrait-secondary。
  • display —— 首選的顯示方式:fullscreen, standalone(看起來像是native app),minimal-ui(有簡化的瀏覽器控制選項) 和 browser(常規的瀏覽器 tab)
  • icons —— 定義了 src URL, sizes和type的圖片對象數組。

MDN提供了完整的manifest屬性列表:Web App Manifest properties

在開發者工具中的 Application tab 左邊有 Manifest 選項,你可以驗證你的 manifest JSON 文件,并提供了 “Add to homescreen”。

如何把網站改成PWA

 


2020042301.png

 

2.3 第三步:創建一個 Service Worker

Service Worker 是攔截和響應你的網絡請求的編程接口。這是一個位于你根目錄的一個單獨的 JAVAscript 文件。

你的 js 文件(在示例代碼中是 /js/main.js)可以檢查是否支持 Service Worker,并且注冊:

if ('serviceWorker' in navigator) {

  // register service worker
  navigator.serviceWorker.register('/service-worker.js');

}

如果你不需要離線功能,可以簡單的創建一個空的 /service-worker.js文件 —— 用戶會被提示安裝你的 app。

Service Worker 很復雜,你可以修改示例代碼來達到自己的目的。這是一個標準的 web worker,瀏覽器用一個單獨的線程來下載和執行它。它沒有調用 DOM 和其他頁面 api 的能力,但他可以攔截網絡請求,包括頁面切換,靜態資源下載,ajax請求所引起的網絡請求。

這就是需要 HTTPS 的最主要的原因。想象一下第三方代碼可以攔截來自其他網站的 service worker, 將是一個災難。

service worker 主要有三個事件: install,activate 和 fetch。

Install 事件

這個事件在app被安裝時觸發。它經常用來緩存必要的文件。緩存通過 Cache API來實現。

首先,我們來構造幾個變量:

  1. 緩存名稱(CACHE)和版本號(version)。你的應用可以有多個緩存但是只能引用一個。我們設置了版本號,這樣當我們有重大更新時,我們可以更新緩存,而忽略舊的緩存。
  2. 一個離線頁面的URL(offlineURL)。當離線時用戶試圖訪問之前未緩存的頁面時,這個頁面會呈現給用戶。
  3. 一個擁有離線功能的頁面必要文件的數組(installFilesEssential)。這個數組應該包含靜態資源,比如 css 和 JavaScript 文件,但我也把主頁面(/)和圖標文件寫進去了。如果主頁面可以多個URL訪問,你應該把他們都寫進去,比如/和/index.html。注意,offlineURL也要被寫入這個數組。
  4. 可選的,描述文件數組(installFilesDesirable)。這些文件都很會被下載,但如果下載失敗不會中止安裝。
// configuration
const
  version = '1.0.0',
  CACHE = version + '::PWAsite',
  offlineURL = '/offline/',
  installFilesEssential = [
    '/',
    '/manifest.json',
    '/css/styles.css',
    '/js/main.js',
    '/js/offlinepage.js',
    '/images/logo/logo152.png'
  ].concat(offlineURL),
  installFilesDesirable = [
    '/favicon.ico',
    '/images/logo/logo016.png',
    '/images/hero/power-pv.jpg',
    '/images/hero/power-lo.jpg',
    '/images/hero/power-hi.jpg'
  ];

installStaticFiles()方法添加文件到緩存,這個方法用到了基于 promise的 Cache API。當必要的文件都被緩存后才會生成返回值。

// install static assets
function installStaticFiles() {

  return caches.open(CACHE)
    .then(cache => {

      // cache desirable files
      cache.addAll(installFilesDesirable);

      // cache essential files
      return cache.addAll(installFilesEssential);

    });

}

最后,我們添加install的事件監聽函數。 waitUntil方法確保所有代碼執行完畢后,service worker 才會執行 install。執行 installStaticFiles()方法,然后執行 self.skipWaiting()方法使service worker進入 active狀態。

// application installation
self.addEventListener('install', event => {

  console.log('service worker: install');

  // cache core files
  event.waitUntil(
    installStaticFiles()
    .then(() => self.skipWaiting())
  );

});

Activate 事件

當 install完成后, service worker 進入active狀態,這個事件立刻執行。你可能不需要實現這個事件監聽,但是示例代碼在這里刪除老舊的無用緩存文件:

// clear old caches
function clearOldCaches() {

  return caches.keys()
    .then(keylist => {

      return Promise.all(
        keylist
          .filter(key => key !== CACHE)
          .map(key => caches.delete(key))
      );

    });

}

// application activated
self.addEventListener('activate', event => {

  console.log('service worker: activate');

    // delete old caches
  event.waitUntil(
    clearOldCaches()
    .then(() => self.clients.claim())
    );

});

注意,最后的self.clients.claim()方法設置本身為active的service worker。

Fetch 事件

當有網絡請求時這個事件被觸發。它調用respondWith()方法來劫持 GET 請求并返回:

  1. 緩存中的一個靜態資源。
  2. 如果 #1 失敗了,就用 Fetch API(這與 service worker 的fetch 事件沒關系)去網絡請求這個資源。然后將這個資源加入緩存。
  3. 如果 #1 和 #2 都失敗了,那就返回一個適當的值。
// application fetch network data
self.addEventListener('fetch', event => {

  // abandon non-GET requests
  if (event.request.method !== 'GET') return;

  let url = event.request.url;

  event.respondWith(

    caches.open(CACHE)
      .then(cache => {

        return cache.match(event.request)
          .then(response => {

            if (response) {
              // return cached file
              console.log('cache fetch: ' + url);
              return response;
            }

            // make network request
            return fetch(event.request)
              .then(newreq => {

                console.log('network fetch: ' + url);
                if (newreq.ok) cache.put(event.request, newreq.clone());
                return newreq;

              })
              // app is offline
              .catch(() => offlineAsset(url));

          });

      })

  );

});

最后這個offlineAsset(url)方法通過幾個輔助函數返回一個適當的值:

// is image URL?
let iExt = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp'].map(f => '.' + f);
function isImage(url) {

  return iExt.reduce((ret, ext) => ret || url.endsWith(ext), false);

}


// return offline asset
function offlineAsset(url) {

  if (isImage(url)) {

    // return image
    return new Response(
      '<svg role="img" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title>offline</title><path d="M0 0h400v300H0z" fill="#eee" /><text x="200" y="150" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="50" fill="#ccc">offline</text></svg>',
      { headers: {
        'Content-Type': 'image/svg+xml',
        'Cache-Control': 'no-store'
      }}
    );

  }
  else {

    // return page
    return caches.match(offlineURL);

  }

}

offlineAsset()方法檢查是否是一個圖片請求,如果是,那么返回一個帶有 “offline” 字樣的 SVG。如果不是,返回 offlineURL 頁面。

開發者工具提供了查看 Service Worker 相關信息的選項:

 

如何把網站改成PWA

 


2020042302.png

在開發者工具的 Cache Storage 選項列出了所有當前域內的緩存和所包含的靜態文件。當緩存更新的時候,你可以點擊左下角的刷新按鈕來更新緩存:

 

如何把網站改成PWA

 


2020042303.png

 

不出意料, Clear storage 選項可以刪除你的 service worker 和緩存:

 

如何把網站改成PWA

 


2020042304.png

2.4 第四步:創建一個可用的離線頁面

離線頁面可以是一個靜態頁面,來說明當前用戶請求不可用。然而,我們也可以在這個頁面上列出可以訪問的頁面鏈接。

在main.js中我們可以使用 Cache API 。然而API 使用promises,在不支持的瀏覽器中會引起所有javascript運行阻塞。為了避免這種情況,我們在加載另一個 /js/offlinepage.js 文件之前必須檢查離線文件列表和是否支持 Cache API 。

// load script to populate offline page list
if (document.getElementById('cachedpagelist') && 'caches' in window) {
  var scr = document.createElement('script');
  scr.src = '/js/offlinepage.js';
  scr.async = 1;
  document.head.appendChild(scr);
}

/js/offlinepage.js locates the most recent cache by version name, 取到所有 URL的key的列表,移除所有無用 URL,排序所有的列表并且把他們加到 ID 為cachedpagelist的 DOM 節點中:

// cache name
const
  CACHE = '::PWAsite',
  offlineURL = '/offline/',
  list = document.getElementById('cachedpagelist');

// fetch all caches
window.caches.keys()
  .then(cacheList => {

    // find caches by and order by most recent
    cacheList = cacheList
      .filter(cName => cName.includes(CACHE))
      .sort((a, b) => a - b);

    // open first cache
    caches.open(cacheList[0])
      .then(cache => {

        // fetch cached pages
        cache.keys()
          .then(reqList => {

            let frag = document.createDocumentFragment();

            reqList
              .map(req => req.url)
              .filter(req => (req.endsWith('/') || req.endsWith('.html')) && !req.endsWith(offlineURL))
              .sort()
              .forEach(req => {
                let
                  li = document.createElement('li'),
                  a = li.appendChild(document.createElement('a'));
                  a.setAttribute('href', req);
                  a.textContent = a.pathname;
                  frag.appendChild(li);
              });

            if (list) list.appendChild(frag);

          });

      })

  });

上面這些代碼demo在 https://github.com/craigbuckler/pwa-retrofit

上面只簡單講了 Service Worker 如何工作。我們會發現有很多問題需要我們進一步解決:

  • 預緩存的靜態資源修改后在下一次發版本時的文件名都不一樣,手動寫死太低效,最好每次都自動生成資源文件名。
  • 緩存資源是以硬編碼字符串判斷是否有效,這樣每次發版本都需要手動修改,才能更新緩存。并且每次都是全量更新。能否以文件的粒度進行資源緩存呢?
  • 請求代理沒有區分靜態資源和動態接口。已經緩存的動態接口也會一直返回緩存,無法請求新數據。

上面只列出了三個明顯的問題,還有很多問題是沒有考慮到的。如果讓我們自己來解決這些問題,不僅是工作量很大,而且也很難寫出生產環境可用的 Service Worker。

3. workbox

既然如此,我們最好是站在巨人的肩膀上,這個巨人就是谷歌。workbox 是由谷歌瀏覽器團隊發布,用來協助創建 PWA 應用的 JavaScript 庫。當然直接用 workbox 還是太復雜了,谷歌還很貼心的發布了一個 webpack 插件,能夠自動生成 Service Worker 和 靜態資源列表 - workbox-webpack-plugin。

只需簡單一步就能生成生產環境可用的 Service Worker :

const { GenerateSW } = require('workbox-webpack-plugin')

new GenerateSW()

分享到:
標簽:PWA
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定