paiza times

paizaがお届けする、テック・キャリア・マネジメント領域における「今必要な情報」を届けるWebメディア

logo

paizaがお届けする、テック・キャリア・マネジメント領域の「今必要な情報」を届けるWebメディア

PWA入門!JavaScriptで簡単に高速化&オフライン対応のWebサイト制作チュートリアル!

f:id:paiza:20180829111252j:plain
どうも、まさとらん(@0310lan)です!

今回は、基本的な機能を持った簡易的なPWA(Progressive Web Apps)対応サイトをフレームワークなどを使わず素のJavaScriptで作ってみたいと思います。

主に、スマホのホーム画面からアプリのように起動したり、サービスワーカーを使ってオフライン対応や表示の高速化などを試していきましょう。

誰でも今すぐ実践できる内容なので、PWAに興味がある方はぜひ参考にしてみてください!

■開発環境について

早速プログラミングを始めたいところなのですが、その前に1つ注意点があります。

オフライン対応やキャッシュによる高速化を実現するには「サービスワーカー」を利用するのですが、これにはSSL対応のサーバー環境が必要になります。

すでに環境が整っている方は問題ありませんが、そうでない方やサーバーを用意するのが面倒だという方はオンラインコードエディタの「glitch」を使うと簡単です!

f:id:paiza:20180829111431j:plain

過去にも記事にしましたが、ログイン不要でブラウザからアクセスするだけでSSL対応のサーバー環境と開発用のコードエディタが無料で利用できます。
paiza.hatenablog.com

作成したサイトはそのまま公開もできるし、無料のユーザー登録をすればファイルの保存やGitHub連携、LinuxベースのCLIによるコマンド実行なども可能です。

簡単なWebサイトやアプリ制作・学習用などに最適なので、すぐにプログラミングを始めたい方はぜひ使ってみてください!

■事前準備

それでは、まず最初にベースとなるHTMLファイルを準備していきましょう。

今回は解説がしやすいように、文字列と画像を1枚配置しただけの単純な構成にしています。(index.html)

<body>
    <h1>サンプルPWAサイト</h1>
    
    <img src="pwa-logo.png">
       
    
    <script>
        //ここにJavaScriptを記述していく
    </script>
</body>


ブラウザで表示するとこんな感じです。

f:id:paiza:20180829111619j:plain

このサイトを、スマホアプリのように起動させたりオフライン対応をしていきましょう。

ちなみに、PWAのロゴ画像はGitHubで公開されており誰でもダウンロードできるようになっています。


<参考>

■「マニフェストファイル」を作ってみよう!

まずはスマホのアプリみたいにホーム画面からアイコンをタップして起動できるようにしてみましょう!

これを実現するためにはJSON形式の「マニフェストファイル」を作成します。


ファイル名を「manifest.json」として次のようなJSON形式のデータを記述してみましょう!

{
  "short_name": "PWAサイト",


  "name": "サンプルのPWAサイト",


  "start_url": "https://pwa.glitch.me/",


  "display": "standalone",
}

それぞれのプロパティの意味は以下の通りです。

「short_name」:スマホのホーム画面に表示される名前
「name」:インストールを促すバナーに表示される名前
「start_url」:ホーム画面から起動する最初のサイトURL
「display」:ホーム画面から単独で起動するかを決める

このなかで、「display」の値を「standalone」に指定すると一般的なスマホアプリのように単独で起動するのでオススメです。

「browser」を指定するとスマホブラウザの新規タブか新規ウィンドウで表示されるようになります。


また、スマホのホーム画面に配置するアイコンを好きな画像にしたり、スマホの向きを固定にする設定やスプラッシュスクリーンの背景色を変更することもできます!

{
・
・
・
  "icons": [
    {
      "src": "image/icon.png",
      "type": "image/png",
      "sizes": "192x192"
    }
  ],
  "background_color": "#2196F3",
  "orientation": "portrait"
}

アイコン画像は任意のサイズを配列に複数登録することも可能です。

マニフェストにどのような設定が記述できるのかについては、MDNのページに詳しく掲載されているので合わせて参考にしてみるといいでしょう。


<参考>


マニフェストファイルを作成したら、HTML内の「headタグ」に次のような記述をします!

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

このように、「manifest.json」ファイルを「linkタグ」で設定するだけで、作成したマニフェストがこのWebサイトに適用されます。


本当に適用されているかを確認するには、Chromeブラウザの場合なら開発者ツールの「Application」タブから「Manifest」の項目をクリックします!

f:id:paiza:20180829111856j:plain

正常に適用されていれば設定した内容が表示されるようになります。


実際にブラウザアプリの設定メニューから「ホーム画面に追加」をタップして、スマホのホームに生成されたアイコンから起動できるかを確認してみましょう!

f:id:paiza:20180829111907j:plain


マニフェストの「display」を「standalone」に設定していれば、以下のようにサイトが単独で起動しているのが分かります。

f:id:paiza:20180829111916j:plain

■「サービスワーカー」を登録しよう!

今度は、「サービスワーカー」が使えるようにサイトへ登録しましょう!

「サービスワーカー」を使うと、通常のJavaScriptとは別にバックグラウンドで実行できるようになります。

そのため、ページを読み込んだ時とかPush通知の送受信など任意のタイミングで事前に用意したJavaScriptを実行できるわけです。

この仕組はWebサイトのオフライン対応や高速化にも繋がるので、重要なポイントになるといえるでしょう。


さて、「サービスワーカー」の使い方ですが、サイトへの登録自体は簡単です!

次のようなJavaScriptで実現できます。

navigator.serviceWorker.register('/sw.js')

「register()」の引数に指定した「sw.js」は、これから作成するサービスワーカーの中身を記述するファイルなので事前に空のファイルを作成しておきましょう。


この1行だけで登録は完了しますが、正常に登録できなかった場合も想定して以下のようにエラー処理も記述した方が良いでしょう。

navigator.serviceWorker.register('/sw.js').then(function() {


        console.log('サービスワーカーの登録成功');


}).catch(function(err) {


        console.log('サービスワーカーの登録ができませんでした:', err);


});


さらに、「サービスワーカー」に対応したブラウザで閲覧しているかを確認したい場合は、IF文で条件分岐させる方法が簡単です。

if ('serviceWorker' in navigator) {


    navigator.serviceWorker.register('/sw.js')


}


実際にサービスワーカーが登録できているかは、マニフェストファイルと同じく開発者ツールの「Application」タブから「Service Workers」の項目を見ると確認できます!

f:id:paiza:20180829112029j:plain

正常に登録できていれば緑色のマークと「activated and running」と記載されているはずです。

■「サービスワーカー」3つの状態をプログラミング!

「サービスワーカー」を登録できたところで、今度はその中身(sw.js)を作成していきましょう!

一般的なJavaScriptと違ってサービスワーカーは独自のライフサイクルを持っており、インストールされた時や有効化した時、リクエストの要求によりページが読み込まれた時などさまざまな状態を持っています。

そこで、今回は「インストール状態」「有効化状態」「リクエスト取得状態」の3つの状態に対して基本的なプログラムを組み立てることで、自動的にバックグラウンドで実行されるようにしてみましょう。


まずは「インストール状態」です!

ここでは、サービスワーカーがサイトに登録(インストール)されるタイミングで、同時に必要なリソースをキャッシュしてオフラインでも使えるようにしていきます。

サービスワーカーの状態を知るには「self.addEventListener()」を使い、「installイベント」の中にキャッシュ処理を書いていくのが基本です。

var CACHE_NAME = 【キャッシュ名】;


self.addEventListener('install', function(event) {
  event.waitUntil(


    caches.open(CACHE_NAME)
    .then(function(cache) {
      
        return cache.addAll(【キャッシュしたいリソースのパス】);
      
    })


  );
});

「event.waitUntil()」内にキャッシュ処理を記述することで、すべてのリソースが無事にキャッシュされたことを確認したあとにサービスワーカーのインストールが完了します。

逆に1つでもキャッシュできないファイルがあれば処理は中断されるというわけです。

「キャッシュ名」は特に何でも構わないのですが、「cache-v1」のようにバージョン番号を付与していると管理しやすいでしょう。

また、「cache.addAll()」にはキャッシュしたいCSSファイルや画像ファイルなどのリソースがあるパスを配列で指定します。


本当にキャッシュされているかについては、これまでと同じく開発者ツールから「Cache Storage」の項目で確認することができます。

f:id:paiza:20180829112111j:plain


次に、「有効化状態」のプログラムです!

ここでは、サービスワーカーがインストールされて有効化されたタイミングで、キャッシュの更新がないかを確認・処理していきましょう。

つまり、古いキャッシュを削除して常に新しい最新版のキャッシュリソースを使えるようにするわけです。


例えば「キャッシュ名」のバージョンだけを変えて実行してみてください。

すると、「Cache Storage」には古いバージョンと新しいバージョンのキャッシュが2つ存在することになります!

f:id:paiza:20180829112128j:plain

しかし、このままだといつまで経っても古いバージョンのキャッシュだけが使われることになります。

そこで、「activateイベント」の中で「caches.keys()」を使ってすべてのキャッシュ名を取得し、古いキャッシュだけを削除する処理を記述します!

self.addEventListener('activate', function(event) {  
  event.waitUntil(
    
    caches.keys().then(function(cache) {
      cache.map(function(name) {
        if(CACHE_NAME !== name) caches.delete(name);
      })
    })
    
  );
});

キャッシュを削除するには「caches.delete()」の引数に削除したいキャッシュ名を指定するだけなので簡単です。

ブラウザのタブを閉じてから、もう一度サイトを開くと最新版のキャッシュだけになっているのが分かります。


最後に、「リクエスト取得状態」のプログラムです!

ここではページが読み込まれた時に、キャッシュに保存されているリソースがある場合はそれを使って処理できるように記述します。

サイトを構成するリソースをキャッシュから読み込むのでネット通信が不要となり、自動的にオフライン対応にもなるというわけです!


基本的な書き方としては、「fetchイベント」の中で「event.respondWith()」を使い、「caches.match()」でリクエストされたリソースがキャッシュに存在するかどうかを調べます。

self.addEventListener('fetch', function(event) {
  event.respondWith(
    
    caches.match(event.request).then(function(res) {
        if(res) return res;
      
        return fetch(event.request);
    })
    
  );
});

キャッシュの中に該当するCSSファイルや画像などのリソースがあれば、それらを使うようにレスポンスを返せばOKです!


実際に機能しているかどうかは、開発者ツールの「Network」タブでそれぞれのリソースが「from ServiceWorker」と記載されているかを確認することで判断できます。

f:id:paiza:20180829112216j:plain

通常ならサーバーと通信するわけですが、キャッシュを使えば通信不要なのでこのような表記になるわけです。

また、キャッシュを使うということは同時に表示の高速化にも繋がるので一石二鳥と言えるでしょう。


ここまでのソースコードは以下のリンクからすべて閲覧できるので、ぜひ参考にしてみてください!

【 PWAの基本サンプルコード|GitHub 】

■PWAのチェック項目について

ここまでPWAの基本的な部分に絞って解説してきましたが、もっとPWAのことが知りたい!…という方は、Googleが提供しているチェックリストを参考にするといいでしょう。

【 PWAチェックリスト 】

f:id:paiza:20180829112250j:plain

このリストには、例えばSSL対応のサーバー環境であるかどうか、モバイルに最適化されたレスポンシブなデザインになっているか…など、さまざまな確認項目が用意されておりどのように実現するかも一緒に記載されています。


さらに、サイトのパフォーマンスなどを自動テストできる「Lighthouse」のChrome拡張機能も用意されているのでオススメです!

【 Lighthouse|Chrome拡張機能 】

f:id:paiza:20180829112310j:plain

このテストの中には「PWA」の最適化についてのチェック項目もあるので、どのような改善が必要かを判断するのに役立ちます。


また、海外で「PWA」に対応しているWebサイトやサービスなどをキュレーションしたサイトも参考になります。

【 Progressive Web Apps 】

f:id:paiza:20180829112330j:plain

すでにPWA対応しているサイトのソースコードを参考にすることで、さらなるステップアップにつながるでしょう。

■まとめ

今回は、素のJavaScriptで簡単なPWAサイトを作ってみました。

一般的にはWebサイトをPWA対応するのに役立つさまざまなライブラリが存在しており、例えばGoogleが提供する「Workbox」などを使うとサービスワーカーの処理を効率的に記述できます。

ただし、基本となる部分は今回ご紹介した内容がベースになるので、これからPWAの学習を始めたい人はぜひ参考にしてみてください!



 

paizaラーニング」では、未経験者でもブラウザさえあれば、今すぐプログラミングの基礎が動画で学べるレッスンを多数公開しております。

詳しくはこちら

paizaラーニング

そしてpaizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。

スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。

詳しくはこちら

paizaのスキルチェック

paizaのおすすめコンテンツ

PPG proken プログラミングゲーム「初恋 プログラミング研究会〜海に行こうよ〜」 PPG Bingo プログラミングゲーム「コードレビューBINGO!!」
paiza転職 paiza新卒 EN:TRY paizaラーニング 記事内に記載している情報は、記事公開時点でのものとなります。 Copyright Paiza, Inc, All rights reserved.