1.なに?
A new way to deliver amazing user experiences on the web.
Webユーザーエクスペリエンスを向上させる方法。Webの自然な(便利な)エクスペリエンスに加えて、3つの機能があります:信頼性、高速、魅力的
信頼性:不確実なネットワーク環境では、古代に戻らずにすぐにロードできます(切断のため)
信頼性とは、オフラインキャッシングと、オフラインシナリオを引き続き利用できるようにするための切断状態でのキャッシングを指します。サービスワーカーは、キャッシュAPIと連携して、キャッシュプロキシメカニズムを確立します。
高速:フレームドロップやスタックスクロールなしで、インタラクティブなフィードバックとしてシルキーアニメーションをすばやく使用します
速い、尊敬されているマテリアルデザインに関連するインタラクティブなフィードバック「速く感じる」を強調するだけで、実際の速度の利点はありません(少なくとも最初の画面では)
さらに、キャッシュプロキシメカニズムのおかげで、ローカルキャッシュは再度アクセスされたときに非常に高速になります
ネイティブ:デバイスネイティブアプリと同様に、没入型のユーザーエクスペリエンス(フルスクリーン)を備えています
フルスクリーンに加えて、ホーム画面アイコン(Webアプリをホーム画面に配置できるようにする)とシステム通知(「ライブ」機能)もあります。これらは、ユーザー環境のサポートに応じて、Webアプリマニフェスト構成を通じて実装されます。
抽象形のPSEngagingは翻訳が非常に難しいので、ネイティブのように、とりあえず実際の意味を考えてみましょう。
したがって、表面上、PWAのハイライトは2つの部分に分かれています。
(オフライン)キャッシュプロキシメカニズム
フルスクリーン、ホーム画面アイコン、システム通知などのネイティブ機能
キャッシングメカニズムはWebApp / SPAの新機能ではありません。データレイヤーを抽出した後、キャッシングはスムーズに行われます。ただし、焦点は異なります。PWAのキャッシングメカニズムは静的リソースキャッシングに偏っていますが、Web App / SPAのキャッシングレイヤーは主に動的コンテンツキャッシングに使用されます(最後のコンテンツが期限切れになっていない場合、動的部分は取得されませんが、クライアントは直接使用されます。レンダリングの終了)
フルスクリーン、ホーム画面アイコン、システム通知、およびその他のネイティブ機能については、サポートされているユーザー環境で利用できるプログレッシブ拡張の拡張と見なされます(一部のブラウザーはサポートを提供しますが、より広いWebView環境は近い将来機能しない可能性があります) 。しかし、これは、WebがPC時代から徐々に強化され、モバイルに移行していることを示しています。
2.デモ
は環境HTTPSに依存し
ます
サービスソースは安全である必要があるため、HTTPS環境が必要です。ウェブ情報のセキュリティへの配慮に加えて、HTTPSの普及を促進する重要な理由でもあります。ウェブテクノロジーの開発に必要なインフラストラクチャとして、HTTPSは写真撮影、録音、プッシュAPIなどの新機能に対するユーザー権限を必要とし、HTTPSが権限です。ワークフローの重要な部分
PSは、permission.siteでユーザー認証を取得する際に、HTTPS環境とHTTP環境の違いを体験できます。
ネイティブの機能強化は
、PWAをサポートするブラウザーで有効になるWeb App Manifest構成ファイルを導入することによって実現されます(サポートされていない環境での最悪の結果は、もう1つのJSONファイルを要求することです)。
<link rel = "manifest" href = "./manifest.json">
アプリケーションキャッシュ(HTML5機能、廃止)と呼ばれる同様のものがあり、そのマニフェストは異なる方法で導入されていることに注意してください。
<html manifest="example.appcache">
...
</html>
2つの導入方法が異なるため、Web AppManifestとApplicationCacheは無関係であり、過去の手荷物について心配する必要はありません。
PSApplication CacheはSPAをより適切にサポートしますが、複数ページのアプリケーションには適していませんが、多くの問題があるため、ここではこれ以上紹介しません。
ホーム画面アイコン
Webアプリマニフェストの内容の例は次のとおりです。
{
"short_name": "主屏显示的应用名称",
"name": "安装banner显示的应用名称",
"icons": [
{
"src": "launcher-icon-1x.png",
"type": "image/png",
"sizes": "48x48",
"density": "1.0"
},
{
"src": "launcher-icon-2x.png",
"type": "image/png",
"sizes": "96x96",
"density": "1.0"
},
{
"src": "launcher-icon-4x.png",
"type": "image/png",
"sizes": "192x192",
"density": "1.0"
}
],
"start_url": "index.html?launcher=true"
}
PSインストールバナーは、権限の取得と同様のポップアップパネルを指します。ユーザーは、メイン画面に追加するかキャンセルするかを選択できます。特定の条件が満たされると、Chromeは自動的にインストールバナーをポップアップします。詳細については、Webアプリインストールバナーを参照してください。
このように、理想的にはホーム画面アイコンがあり、Webアプリマニフェストをサポートする環境が最適なアイコン(48dpに最も近い)を選択します
注:index.htmlのコンテンツは、最初の画面のレンダリングに必要な最小限のコンテンツである必要があります。最初の画面をすぐに読み込む効果を実現するために、読み込みとデフォルトのプレースホルダーを含むページフレームをアプリシェルとして表示できます。さらに、数秒で利用可能な最初の画面のパフォーマンスを実現するために、直接データ出力など、Webアプリの最初の画面のパフォーマンスを最適化する他の従来の方法もPWAで推奨されます。冒頭で述べたように、PWAには固有の(最初の画面の)パフォーマンス上の利点はなく、Webアプリの従来の最適化方法は依然として必要です。
スプラッシュ画面(スプラッシュ)は
メイン画面のアイコンから入力され、カスタマイズ可能な起動プロセスの表示コンテンツには、タイトル、背景色、画像が含まれます。新しい構成項目は次のとおりです。
// 背景色
"background_color": "#2196F3",
// 主题色,包括工具栏
"theme_color": "#2196F3",
画像スプラッシュ画面としてアイコンから128dpに最も近い画像を選択します。アニメーション画像はサポートしていません。
さらに、表示モードとページの向きを指定することもできます。
// 全屏(隐藏浏览器的UI)
"display": "standalone",
// 显示浏览器外壳,像打开书签一样
"display": "browser",
// 横屏
"orientation": "landscape"
PSスプラッシュ画面の例と詳細については、Chrome47にインストールされているWebアプリのスプラッシュ画面の追加を参照してください。
特記事項:manifest.jsonファイルが更新された場合、ユーザーがアプリケーションをメイン画面に再度追加しない限り、これらの変更は自動的に有効になりません。
システム通知は
WebApp Manifestとは関係がなく、PushAPIに依存しています。簡単な例は次のとおりです。
// service-worker.js
self.addEventListener("push", function (event) {
event.waitUntil(
self.self.registration.showNotification("发布新文章啦", {
body: "有新文章发布啦,点击查看。"
})
);
});
ここではあまり紹介しません(現在(2017/12/15)この機能はほとんど存在しないと考えられます)。仕様ではAPIが定義されていますが、統一されたプッシュプロトコルが規定されていないため、Chromeなどの各ブラウザのプッシュメカニズムは異なります。 GCMは私たちの空の下では利用できません
Push APIの詳細については、[ServiceWorker]メッセージプッシュ機能「Annihilated」を確認してください。
キャッシュ-プロキシ
キャッシュはいくつかの部分に分かれています。
最初の画面の静的リソースキャッシュ(プリキャッシュ)
アクセスされたリソースキャッシュ(ランタイムキャッシュ)
動的コンテンツキャッシング(ランタイムキャッシング)
キャッシュは純粋なデータ操作(永続性を含む)であり、サービスワーカーはバックグラウンドで実行できます。これは、ページやインタラクションとは関係のない処理に特に適しています。したがって、サービスワーカーはキャッシュAPIおよびプッシュAPIのパートナーです。ただし、サービスワーカー自体も「拡張」アイテムと見なす必要があります。サービスワーカーをサポートしない環境では、基本的なページエクスペリエンスを確保するために、キャッシュメカニズムをスキップする必要があります。単純な機能検出スキームは次のとおりです。
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('./service-worker.js')
.then(function() { console.log('Service Worker Registered'); });
}
Service Workerは、インストールイベントハンドラーにAppShellを含む最初の画面の静的リソースキャッシュを完了します。
// service-worker.js
var cacheName = 'weatherPWA-step-6-1';
var filesToCache = [
// 入口URL
'/',
'/index.html',
'/scripts/app.js',
'/styles/inline.css',
// App Shell需要的资源
'/images/ic_add_white_24px.svg',
'/images/ic_refresh_white_24px.svg',
// 内容展示可能用到的资源
'/images/clear.png',
'/images/cloudy-scattered-showers.png',
'/images/cloudy.png',
'/images/fog.png',
'/images/partly-cloudy.png',
'/images/rain.png',
'/images/scattered-showers.png',
'/images/sleet.png',
'/images/snow.png',
'/images/thunderstorm.png',
'/images/wind.png'
];
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
//! 只要有一个失败就不接着做下一个了
return cache.addAll(filesToCache);
})
);
});
もちろん、キャッシュの基本的なバージョン制御も行う必要があります。
// service-worker.js
self.addEventListener('activate', function(e) {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
// 以为cacheName为cache key,如果存在旧的缓存,删除掉
if (key !== cacheName) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
// 要求立即激活service worker,避免边界case
return self.clients.claim();
});
PS境界の場合は、サービスワーカーをすぐにアクティブ状態に復元できない場合があり、その結果、キャッシュが作成されないことを意味します。これらの境界ケースを保護するために、GoogleChromeLabs / sw-precacheを使用して、キャッシュ制御の問題(有効期限、更新ポリシーなどを含む)に対処することをお勧めします。
キャッシュはそこにあり、プロキシ部分を実装し、要求をインターセプトし、キャッシュされたコンテンツで応答します。
// service-worker.js
// 拦截请求
self.addEventListener('fetch', function(event) {
console.log('[ServiceWorker] Fetch', e.request.url);
// 自定义响应内容
e.respondWith(
// 查找缓存,没有才请求
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});
この時点で、基本的なキャッシュプロキシメカニズムの準備が整いました。次のことを実行しました。
リソースリストごとに静的リソースを事前にキャッシュする
傍受リクエスト
過去への応答としてキャッシュされたコンテンツを送信する
3つの考慮事項があります。
ブラウザのキャッシュがキャッシュの更新に影響を与える可能性があるため、インストールイベントハンドラのリクエストはキャッシュに送信されず、ネットワークに直接入力されます
Service Workerをログアウトしても、キャッシュはクリアされません。キャッシュキーが同じままの場合は、後で古いキャッシュコンテンツを取得します。
デフォルトでは、新しく登録されたService Workerは、特別な処理が行われない限り、ページが再読み込みされるまで有効になりません。
さらに、簡略化された実装には、次のようないくつかの問題があります。
キャッシュバージョンコントロールは静的キャッシュキーに依存しています。静的キャッシュキーは、service-worker.jsが更新されるたびに変更する必要があります。
キャッシュキーが変更されると、すべてのキャッシュが消去され、リクエストが再度行われます。これは静的リソースの浪費です。
ランタイムキャッシュの欠如、リソースリストは十分な柔軟性がなく、アクセス中により強力なキャッシュを期待します
最初の問題は適切な解決策ではありません。2番目の問題は、リソースタイプを細分化することで軽減できます。次に例を示します。
// Shorthand identifier mapped to specific versioned cache.
var CURRENT_CACHES = {
font: 'font-cache-v' + FONT_CACHE_VERSION,
css: 'css-cache-v' + CSS_CACHE_VERSION,
img: 'img-cache-v' + IMG_CACHE_VERSION
};
よりきめ細かいバージョン制御により、キャッシュの強制更新のコストをある程度削減できます。もちろん、キャッシュレイヤーの下にHTTPキャッシュもあります。キャッシュ更新のコストはそれほど重要ではありません。
ランタイムキャッシングに関しては、実際、最後の小さなステップだけが必要です。
キャッシュが不足している場合は、リソースとキャッシュをリクエストしてください
詳細は次のとおりです。
// 查找缓存,没有才请求
caches.match(e.request).then(function(response) {
return response || fetch(e.request).then(function(res) {
return caches.open(dataCacheName).then(function(cache) {
// 并缓存起来
cache.put(e.request.url, res.clone());
return res;
)
})
})
さらに、リソースタイプとシナリオ要件に基づいて、適切なキャッシュ戦略を選択できます。次に例を示します。
// service-worker.js
self.addEventListener('fetch', function(e) {
console.log('[Service Worker] Fetch', e.request.url);
var dataUrl = 'https://cache.domain.com/fresh/';
// 策略1:有实时性要求的资源,请求优先,fetch then cache
if (e.request.url.indexOf(dataUrl) > -1) {
e.respondWith(
caches.open(dataCacheName).then(function(cache) {
return fetch(e.request).then(function(response){
cache.put(e.request.url, response.clone());
return response;
});
})
);
} else {
// 策略2:一般资源,缓存优先,cache falling back to fetch
}
});
PSその他のキャッシング戦略については、リファレンスセクションを参照してください
3.
デモ公式デモ:Weather PWA、通常はアクセスできない場合があります
デモの移動(公式デモのgithubページへの移動):https://ayqy.github.io/pwa/demo/weather-pwa/index.html
PSgithubページは、テストフィールド、安定した信頼性の高いHTTPSとして使用するのに非常に適しており、公開されたコンテンツのコンテンツに制限はありません。それについて投げることができます。将来のブログデモは徐々に過去に移行します(以前は独自のFTPに配置されていましたが、これは本当にばかげています...)
天気-pwa
あまり楽観的ではないニュース:実際、ユーザー環境は意図的に準備されており(公式の正規のChrome +公式のデモ)、Mi 4には自動ポップアップインストールバナーがありませんでした(操作姿勢やその他の条件が満たされていない可能性があります。上記を参照)。手動でクリックしてください。 「ホーム画面に追加」、トーストは正常に追加されましたが、ホーム画面に何も表示されません...これが、手書きのデモに興味がない理由です(もちろん、主な理由は怠惰です;))
4.ケース
アリババインターナショナルステーション
AliExpress
お腹が空いていますか:奇妙なことに、なぜキャッシュの効果を感じなかったのですか?
ステルスモードでは、Alibaba InternationalStationのサービスワーカーが次のエラーをスローする可能性があることに注意してください。
キャッチされていない(約束されている)DOMException:クォータを超えました。
通常の環境を正常に体験できます。
PSその他のケースについては、ケーススタディ| Web | Google |開発者を確認してください。
V.アプリケーションシナリオ
要するに、PWAはWebアプリのアップグレードバージョンであり、主なハイライトはネイティブサポートです。徐々に強化された方法で、WebアプリからPWAへの「アップグレード」をあまりコストをかけずに完了することができるため、一部のユーザー(PWAをサポートする環境)は、ネイティブエクスペリエンス(フルスクリーン)のように、より速く(キャッシュ)、より便利に(ホーム画面アイコン)取得できます。 )
次に、特定のアプリケーションシナリオを次のカテゴリに分類します。
キャッシングが明らかなメリットをもたらすことができるWebアプリ
オフライン機能やネイティブエクスペリエンスが必要な場合、または単にホーム画面アイコンが付いたWebアプリケーションが必要な場合
テクノロジーのホットスポットを活用したり、開発を促進したりすることを期待しているWebアプリケーションまたはブラウザーのサプライヤー
アプリケーションのシナリオに関係なく、zxxのキャッシング(またはワーカー?)に関する記事で述べたように、このような小さなコストでページがオフラインになる可能性があります。キャッシングの利点を実際に確認した場合は、そうしないでください。 ?
さらに、Angular、React、Vueなどの主流のフレームワークはすべてPWAスキャフォールディングを提供します。詳細については、プログレッシブWebアプリケーションの究極のガイドを参照してください。
参考資料
オフラインクックブック:グラフィカルなキャッシュ戦略、良いこと、翻訳するには、ServiceWorkerクックブックをご覧ください。
プログレッシブWebアプリの開発見通しをどのように見ていますか?
最初のプログレッシブWebアプリ:公式チュートリアル
プログレッシブWebアプリのビギナーズガイド:より包括的なガイド
あなたのウェブサイトをPWAに変える:プログレッシブウェブアプリとしてあなたのウェブサイトをオリジナルに改造する