プログレッシブ ウェブ アプリ (PWA) の開発方法

プログレッシブ ウェブ アプリ (PWA) の開発方法

概要

Apple が iPhone App Store を立ち上げて以来、アプリは私たちの生活に欠かせないものになりましたが、実店舗でも同じことが言えます。現在、あらゆる業界が独自のアプリをリリースしていますが、次のようなシナリオを考えたことがある人はいませんか。潜在的な顧客がまだアプリをインストールしていない場合、またはインストールしたとしても、携帯電話のストレージ容量が不足しているためにアプリをアンインストールしてしまった場合です。アプリを軽量化し、インストールしやすくする技術的な解決策はありますか?答えは「はい」です。

プログレッシブ ウェブ アプリケーションは、この目的のために作成されます。ウェブ アプリケーションの機能と、以前はネイティブ アプリケーションでのみ使用可能だった機能の両方を備えています。プログレッシブ ウェブ アプリケーションは、ホーム画面上のアイコンから、またはプッシュ通知に基づいて起動されます。読み込み時間はほとんど無視でき、オンラインでの使用に加えて、オフラインでの使用のためにパッケージ化することもできます。

何よりも、プログレッシブ ウェブ アプリは Web サイトの拡張機能に過ぎないため、モバイル フォンで簡単に作成できます。誰かが初めて Web サイトにアクセスすると、承認後に PWA 機能が携帯電話に自動的に作成されます。

次に、独自の PWA アプリケーションを作成する方法を見ていきます。

必要とする

このチュートリアルを開始するには、次のソフトウェアがインストールされている必要があります。

    Node 8.9 以上 (https://nodejs.org/en/download/)。Yarn (https://yarnpkg.com) Git。

このチュートリアルの最初のプロジェクトとして、次の Github リポジトリをクローンできます。

git クローン https://github.com/petereijgermans11/progressive-web-app

次に、次のディレクトリに移動します

cd pwa-article/pwa-app-manifest-init

次のコマンドを使用して依存関係をインストールし、プロジェクトを開始します。

npm i && npm スタート

次のアドレスでアプリケーションを開きます: http://localhost:8080

アプリケーションのURL

ローカルホストにアクセスする方法はいくつかあります。リモートでアクセスするには、マシンのポート 8080 にアドレスを投稿します。この目的には、ngrok を使用できます。参照: https://ngrok.com/

次のコマンドを使用して ngrok をインストールします。

npm インストール -g ngrok

ターミナルで次のコマンドを実行します。このコマンドは、外部からアクセスできるURLを生成します。

ngrok http 8080 です

次に、モバイル デバイスの Chrome で生成された URL を参照します。

PWA にはどのような技術コンポーネントが必要ですか?

PWA には、次の 3 つの重要な技術コンポーネントが調和して動作します。

マニフェスト ファイル、Service Worker、https で実行中。

マニフェストファイル

マニフェスト ファイルは、アプリのアイコン、Web アプリケーション名、背景色など、PWA に関する基本情報が含まれる JSON 構成ファイルです。ブラウザがウェブサイトに PWA マニフェスト ファイルが存在することを検出すると、Chrome は自動的に「ホーム画面に追加」ボタンを表示します。ユーザーが「同意する」をタップすると、アイコンがホーム画面に追加され、PWA がインストールされます。

Manifest.jsonを作成する

PWA の Manifest.json ファイルは次のようになります。

JSON形式

{
  "name": "プログレッシブセルフィー",
  "short_name": "PWA セルフィー",
  「アイコン」: [
    {
      "src": "/src/images/icons/app-icon-192x192.png",
      "タイプ": "image/png",
      "サイズ": "192x192"
    },
    {
      "src": "/src/images/icons/app-icon-512x512.png",
      "タイプ": "image/png",
      "サイズ": "512x512"
    }
  ]、
  "start_url": "/index.html",
  「スコープ」:「。」,
  "ディスプレイ": "スタンドアロン",
  "背景色": "#fff",
  "テーマカラー": "#3f51b5"
}

アプリケーションのマニフェストをブラウザに伝える

index.html ファイルと同じレベルのディレクトリに Manifest.json ファイルを作成します。マニフェスト ファイルが作成されたら、マニフェスト ファイル参照リンクを index.html に追加します。

<link rel=”マニフェスト” href=”/manifest.json”>

マニフェスト属性

マニフェストには多くの構成プロパティがあります。次に、プロパティについて簡単に説明します。

  • name、short_name: Web アプリケーションの名前を指定します。short_name はアプリケーションの略語です。アプリケーションの name 属性を表示するスペースが足りない場合は、short_name が使用されます。
  • display: display 属性は、Web アプリケーションの表示モードを指定します。設定する値は、fullscreen、standalone、minimal-ui、browser の 4 つですが、よく使用される属性は fullscreen と standalone です。 fullscreen: 全画面表示、standalone: このモードで開いたアプリケーションにはブラウザのアドレスバーがないため、ネイティブアプリケーションのように見えます。minimal-ui、browser: ブラウザを使用してアクセスする場合とほとんど変わりません。
  • 方向: Web アプリケーションの表示方向を制御し、携帯電話の画面の回転を禁止します。
  • icons、background_color: icon はアプリケーション アイコンを指定するために使用され、background_color はアプリケーションがロードされる前の背景色です。これら 2 つのプロパティを設定することで、アプリケーションのスプラッシュ スクリーンに組み合わせることができます。
  • theme_color: アプリケーションのデフォルトのテーマカラーを定義します。
  • description: アプリケーションの説明を設定します。

上記は、pwa マニフェスト ファイルのプロパティの説明です。マニフェスト ファイルを設定し、index.html ファイルと同じレベルのディレクトリに配置することで、マニフェスト ファイルを追加できます。

Chrome デベロッパー ツール – アプリケーション – マニフェストを開き、追加したマニフェスト ファイルが読み込まれているかどうかを確認します。以下のように情報がない場合、npm start でサーバーを再起動することで再読み込みできます。

Service Worker とは何ですか?

Service Worker (SW) は、ブラウザと Web サーバー間のプロキシとして機能する JavaScript です。 Service Worker は、オフライン キャッシュ、メッセージ プッシュ、サイレント更新などのネイティブ アプリケーションの一般的な機能をブラウザーベースの Web アプリケーションに実装し、より優れた、より豊かなユーザー エクスペリエンスを Web アプリケーションに提供できます。

さらに、この API ではキャッシュを使用してオフライン エクスペリエンスをサポートできるため、開発者はユーザー エクスペリエンスを完全に制御できます。

サービスワーカーのライフサイクル

Service Worker の場合、基本的なセットアップの手順は次のとおりです。

  • まず、SW を登録する必要があります。SW が登録されている場合、ブラウザはインストール イベントに基づいて自動的にインストールを開始します。
  • SW がインストールされると、アクティベーション イベントを受信します。このアクティベーション イベントは、以前のバージョンの SW で使用されたリソースをクリーンアップするために使用できます。

実際の操作では、まずindex.htmlと同じレベルにsw.jsという名前の空のファイルを作成する必要があります。次に、次のように index.html ファイルにベース タグを追加します。

<base href="/" rel="外部nofollow" >

最後に、SW を登録するために、src/js/app.js に次のコードを追加します。このコードは、ページの「読み込み」プロセス中にアクティブ化されます。

Chrome DevTools - アプリケーション - Service Worker を開いて、SW が有効になっているかどうかを確認できます。

window.addEventListener('load', () => {
    定数 base = document.querySelector('base');
    baseUrl = base && base.href || '' とします。
    ベースURLが'/'で終わる場合
        ベースUrl = `${baseUrl}/`;
    } 
   
    if ('serviceWorker' in ナビゲータ) {
        ナビゲーターのサービスワーカーを登録します(`${baseUrl}sw.js`)
            .then( 登録 => {
            // 登録は成功しました
            console.log('ServiceWorker の登録がスコープで成功しました: ', registration.scope);
        })
        .catch(エラー => {
            //登録に失敗しました:(
            console.log('ServiceWorker の登録に失敗しました: ', err);
        });
    }
});

上記のコードの主な目的は、ウィンドウ オブジェクトの navigator プロパティで SW API が使用可能かどうかを確認することです。 window オブジェクトはブラウザ ウィンドウを表します。ナビゲータで SW が利用可能な場合は、ページが読み込まれたらすぐに SW を登録します。

SW の登録は簡単ですが、Service Worker の登録で問題が発生する場合があります。SW を登録できない理由とその解決方法を見てみましょう。

  • アプリケーションは HTTPS では実行できません。開発中は、 localhost経由で SW を使用できます。ただし、Web サイトに展開する場合は、HTTPS を有効にする必要があります。
  • SWへのパスが正しくありません。

リロード時の更新はチェックされません。

サービスワーカーイベント

インストール イベントとアクティブ化イベントに加えて、メッセージ、フェッチ、同期、プッシュ イベントなどのイベントもあります。

ライフサイクル イベント (インストールとアクティブ化) をリッスンするには、次のコードを SW に追加します。

self.addEventListener('インストール', イベント => {
    console.log('[Service Worker] Service Workerをインストールしています...', event);
    イベントを待機するまで待機します。
});
self.addEventListener('activate', イベント => {
    console.log('[Service Worker] Service Worker をアクティブ化しています...', event);
    self.clients.claim() を返します。
});

インストール コールバックは skipWaiting() 関数を呼び出して activate イベントをトリガーし、ユーザーが別のページに移動したりページを再読み込みしたりするのを待たずに、すぐに作業を開始するように Service Worker に指示します。

skipWaiting() 関数は、待機中の Service Worker を強制的にアクティブな Service Worker にします。 self.skipWaiting() 関数を self.clients.claim() 関数と一緒に使用して、基盤となる Service Worker への更新がすぐに有効になるようにすることもできます。

この場合、self プロパティはウィンドウ オブジェクト (つまり、ブラウザー ウィンドウ) を表します。

ホームボタンに追加

「ホーム画面に追加ボタン」を使用すると、ユーザーはデバイスに PWA をインストールできます。このボタンを使用して PWA を実際にインストールするには、SW でフェッチ イベント ハンドラーを定義する必要があります。 sw.js でこれを修正しましょう。

self.addEventListener('fetch', イベント => {
    console.log('[Service Worker] 何かを取得しています....', event);
    // これは、開発者ツールを開いたときにChromeで発生する奇妙なバグを修正します
    event.request.cache === 'キャッシュされた場合のみ' && event.request.mode !== '同じオリジン' の場合 {
        戻る;
    }
    イベントを応答します。
});

サービスワーカーキャッシュ

Service Worker の強みは、HTTP リクエストをインターセプトする機能にあります。このステップでは、このオプションを使用して HTTP リクエストと応答をインターセプトし、キャッシュから直接ユーザーに超高速の応答を提供します。

Service Worker のインストール中に事前キャッシュする

ユーザーが初めて Web サイトにアクセスすると、SW が自動的にインストールを開始します。このインストール フェーズでは、PWA で使用されるすべてのページ、スクリプト、およびスタイル ファイルをダウンロードしてキャッシュできます。これを行う sw.js ファイル コードは次のとおりです。

const CACHE_STATIC_NAME = 'static';
定数 URLS_TO_PRECACHE = [
    '/',
    'index.html',
    'src/js/app.js',
    'src/js/feed.js',
    'src/lib/material.min.js',
    'src/css/app.css',
    'src/css/feed.css',
    'src/images/main-image.jpg',
    'https://fonts.googleapis.com/css?family=Roboto:400,700',
    'https://fonts.googleapis.com/icon?family=Material+Icons',
];
self.addEventListener('インストール', イベント => {
    console.log('[Service Worker] Service Workerをインストールしています...', event);
    イベント.waitUntil()
        キャッシュを開く(CACHE_STATIC_NAME)
            .then(キャッシュ => {
                console.log('[Service Worker] App Shell を事前キャッシュしています');
                キャッシュにURLをすべて追加します。
            })
            .then(() => {
                console.log('[ServiceWorker] インストールの待機をスキップ');
                self.skipWaiting() を返します。
            })
    );
});

このコードはインストール イベントを使用し、インストール フェーズ中に URLS_TO_PRECACHE の配列を追加します。 caches.open 関数を呼び出したら、cache.addAll() 関数を使用して配列内のファイルをキャッシュできます。インストールにかかる時間とインストールが成功したかどうかを知るには、event.waitUntil() メソッドで JavaScript Promise を使用します。

インストール イベントは self.skipWaiting() を呼び出して、SW を直接アクティブ化します。すべてのファイルが正常にキャッシュされると、SW がインストールされます。ただし、いずれかのファイルのダウンロードに失敗すると、インストール手順は失敗します。 Chrome デベロッパー ツールでは、キャッシュ (キャッシュ ストレージ内) が URLS_TO_PRECACHE 配列内の静的ファイルで埋められているかどうかを確認できます。

ただし、[ネットワーク] タブを見ると、ファイルは引き続きネットワーク経由で取得されています。その理由は、キャッシュは準備ができているにもかかわらず、参照されたリソースをキャッシュから読み取っていないためです。したがって、この作業部分を完了するには、まずアプリケーションのフェッチ イベントをリッスンし、次にキャッシュからリソースをインターセプトして取得する必要があります。次のコードを見てみましょう。

self.addEventListener('fetch', イベント => {
    console.log('[Service Worker] 何かを取得しています....', event);
    イベント.respondWith()
        キャッシュ.match(イベント.リクエスト)
            .then(応答 => {
                if (応答) {
                    console.log(応答);
                    応答を返します。
                }
                fetch(event.request) を返します。
            })
    );
});

caches.match() 関数を使用して、受信 URL が現在のキャッシュ内にある可能性のあるリソースと一致するかどうかを確認します。一致する場合はキャッシュされたリソースを返しますが、リソースがキャッシュ内に存在しない場合は、通常どおり要求されたリソースの取得を続行します。

Service Worker がインストールされアクティブ化されたら、ページを更新して [ネットワーク] タブを再度確認します。これで、Service Worker は、サーバーにネットワーク リクエストを送信する代わりに、HTTP リクエストをインターセプトし、対応するリソースをキャッシュからオンザフライでロードするようになります。

ここで、[ネットワーク] タブでオフライン モードを設定しても、アプリは正常に動作します。

バックグラウンド転送

バックグラウンド フェッチ API は、SW のバックグラウンド機能であり、ユーザーはこれを使用して、大きなファイル、ビデオ、音楽、その他のリソースをバックグラウンドでダウンロードできます。取得/転送プロセス中、ユーザーは転送タスクをクリアせずにタブを閉じたり、ブラウザ全体を閉じたりすることができます。ユーザーがブラウザを再度開くと、転送プロセスが再開されます。この API は転送の進行状況をユーザーに表示することもでき、ユーザーはプロセスをキャンセルまたは一時停止できます。

デフォルトではバックグラウンド転送は利用できません。URL (chrome://flags/#enable-experimental-web-platform-features) から Chrome の「試験運用版ウェブ プラットフォーム機能」オプションを有効にする必要があります。

以下は、このようなバックグラウンド転送を実装する方法の例です。

index.htmlファイルにID「bgFetchButton」のボタンを追加します。

<button id="bgFetchButton">アセットをローカルに保存する</button>

次に、app.jsのロードイベントハンドラに、バックグラウンド転送を実行するコードを追加します。

window.addEventListener('load', () => {
...
       bgFetchButton = document.querySelector('#bgFetchButton');
       bgFetchButton.addEventListener('click', 非同期イベント => {
         試す {
            const 登録 = navigator.serviceWorker.ready を待機します。
            registration.backgroundFetch.fetch('my-fetch', [新しいリクエスト(`${baseUrl}src/images/main-image-lg.jpg`)]);
         } キャッチ (エラー) {
            コンソールエラー(err);
         }
     });
...
});

上記のコードは、次の条件下でバックグラウンド転送を開始します。

  • ユーザーはIDがbgFetchButtonのボタンをクリックする
  • SWが登録されました

転送プロセスはユーザー インターフェイスをブロックできないため、バックグラウンド転送は非同期関数で実行する必要があります。

転送が完了するとキャッシュに保存されます

self.addEventListener('backgroundfetchsuccess', イベント => {
  console.log('[Service Worker]: バックグラウンドフェッチ成功', event.registration); event.waitUntil(
   (非同期関数() {
     試す {
     // レコードを反復処理してキャッシュにデータを追加します
       const cache = await caches.open(event.registration.id); const records = await event.registration.matchAll(); const promises = records.map(async record => {
         const 応答 = record.responseReady を待機します。
         cache.put(record.request, response) を待機します。
       });
       Promise.all(promises) を待機します。
     } キャッチ (エラー) {
       console.log('[Service Worker]: キャッシュエラー');
     }
   })()
  );
});

このコードは次の手順で構成されています。

  • バックグラウンド フェッチ転送が完了すると、SW はバックグラウンド フェッチ成功イベントを受信します。
  • registration.id と同じ名前の新しいキャッシュを作成して開きます。
  • すべてのレコードを取得し、registration.matchAll() を介してそれらを走査します。

最後に、すべての Promise は Promise.all() を介して実行されます。

要約する

この記事では、PWA の 2 つの基本コンポーネント、マニフェストとサービス ワーカーの基本機能について説明しました。HTTPS についてはすでに説明しました。

以上がプログレッシブウェブアプリケーションPWAの開発方法の詳細です。プログレッシブウェブアプリケーションの開発の詳細については、123WORDPRESS.COMの他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • フロントエンドのプログレッシブフレームワークVUEの簡単な紹介
  • vuex プログレッシブチュートリアルのサンプルコードの詳細な説明
  • Spring Boot Web アプリケーション構成の詳細な説明
  • Spring Boot を使用して Web アプリケーションを作成するためのサンプル コード
  • NodeJs の高メモリ使用量のトラブルシューティング実戦記録
  • Nodejs 組み込み暗号化モジュールを使用してピアツーピアの暗号化と復号化を実現する詳細な説明
  • Node.js での組み込みモジュールとカスタムモジュールの実装
  • node.js でマルチコア CPU を最大限に活用する方法
  • Node.js コード実行をバイパスするためのヒントのまとめ

<<:  LinuxのCPU負荷とCPU使用率の詳細な説明

>>:  MySQL での実行計画の explain コマンド例の詳細な説明

推薦する

Linux リモート開発に vs2019 を使用する方法

通常、Linux プログラムを開発する場合、次の 2 つのオプションがあります。 Linux上で直接...

Nginx は高可用性クラスタ構築を実装します (Keepalived+Haproxy+Nginx)

1. コンポーネントと実装機能Keepalived: Haproxy サービスの高可用性を実現し、...

Mysql Explainコマンドの使用と分析

mysql explain コマンドは、MySQL がインデックスを使用して選択ステートメントを処理...

HTML フォーマットの json のサンプルコード

さっそく、コードを直接投稿します。具体的なコードは次のとおりです。 <!DOCTYPE htm...

JavaScript strictモードの概要 strictを使用する

目次1. 概要1.1 厳密モードとは何ですか? 1.2 厳密モードの目的2. 厳密モードを有効にする...

Vueページジャンプの実装方法

1. this.$router.push() 1. ビュー <テンプレート> <d...

Ubuntu20のtzselect設定時間失敗問題、Raspberry Piサーバ(推奨)

2 日前、Raspberry Pi サーバーを Ubuntu 20 にアップグレードしました。今日...

CentOS 8にdockerをインストールする最も詳細な方法

CentOS 8にDockerをインストールする公式ドキュメント: https://docs.doc...

Vueはユーザーログイン切り替えを実装します

この記事では、ユーザーのログイン切り替えを実現するためのVueの具体的なコードを例として紹介します。...

MySQL データベースの最適化: テーブルとデータベースのシャーディング操作の詳細な説明

この記事では、例を使用して、MySQL データベースの最適化のためのテーブルおよびデータベース シャ...

SQLベースのクエリステートメント

目次1. 基本的なSELECT文1. 指定されたフィールドをクエリする3. エイリアスを設定する4....

MySQL 8.0.18 インストール構成の最適化チュートリアル

MySQLのインストール、設定、最適化は参考用です。具体的な内容は次のとおりです。 MySQL ダウ...

Vue3 のリアクティブ関数 toRef 関数 ref 関数の紹介

目次リアクティブ機能使用法: toRef 関数 (理解するだけ)使用法: ref関数レスポンシブデー...

ウェブページの再設計の7つの主要要素 ウェブページの再設計の7つの主要要素を共有する

Shopify Plus は、私たちが設立した e コマース プラットフォームのエンタープライズ バ...

React Diff Principle の詳細な分析

目次差分アルゴリズムレイヤーごとの比較同じタイプのコンポーネントを比較する同じタイプの要素の比較子ノ...