ゼロから学ぶ ウェブ開発-高度開発ドキュメント
PWA篇
・はじめに
高度開発講座へようこそ!
ここではJavaScriptの応用と、更に拡張的な内容学んでいく場所になります。
・PWAとは?
PWAとは、「Progressive Web Apps」(プログレッシブウェブアプリ)の略称です。ウェブ技術(HTML、CSS、JavaScriptなど)を使って構築されたウェブアプリケーションですが、ネイティブアプリ(App StoreやGoogle Playからダウンロードするアプリ)のような使い勝手と機能を提供するものです。
・PWAの特徴
1. インストールができる!:
ブラウザから「ホーム画面に追加」するだけで、スマートフォンやPCのホーム画面にアイコンを置け、ブラウザのタブではなく独立したウィンドウで起動できます。
2. オフラインでも使える!:
Service Workerという技術でコンテンツをキャッシュし、ネットワークがなくても一部の機能が使えます。
3. プッシュ通知:
ネイティブアプリ同様に、常時通知配信が可能!
4. 高速でレスポンシブ:
デバイスやネットワーク環境に合わせて最適化され、素早い読み込みとスムーズな操作を実現します。
5. プログレッシブエンハンスメント
古いブラウザでも基本機能が動き、現代のブラウザでは高度な機能が追加される「段階的な強化」が特徴です。
など簡単にOS関係なくアプリ化、しかも軽量軽快に動作するというメリットがあります。
ただしPWAはあくまでもWEBサイトをブラウザベースでアプリ化するというものです。そのため100%アプリになるわけでなくブラウザに依存しながら動作するものになるため、カメラやマイク機能はアクセス制限がかかること、高度なアプリ開発には限界が来るということを承知しておいてください。
- PWAで動作するアプリの例 -
X
YouTube
Google Chat
Zoom
Microsoft Teams
Microsoft Clipchamp
ロイロノート(Android)
Novel Genesis Editor
・PWA開発における注意
先程、PWAはブラウザで動作すると説明しました。
しかし、全てのブラウザで動作するわけではないのでそこを覚えておいてください。
基本的にChromeベースのブラウザはPWAに対応しています。
Safariは対応はしていますが、プログラムの仕様がChromeと異なります。
・動作するブラウザ
Google Chrome
- Chromeベースのブラウザ -
Microsoft Edge
Samsung Browser
Opera
Brave
・開発に難ありのブラウザ
Safari
・非対応のブラウザ
Mozilla Firefox
・Chrome版 開発開始!
まずは以下のプログラムをアプリ化したいHTMLの< </の中に書き込んでください。
<!まずは上記のような構成でPWAに関連のあるコードを貼り付けてください。DOCTYPE html > <html lang ="ja" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content="width=device-width, initial-scale=1.0" > <link rel ="shortcut icon" href ="ファビコンのファイル名" type ="image/x-icon" > <link rel ="stylesheet" href ="CSSのファイル名" > <title >サイト名(ブラウザのタブに表示される)</title ><!-- ここからPWA開発の記述 --> <!-- アプリのテーマカラーの設定 --> <meta name ="theme-color" content ="テーマカラー(16進法、RGB値、カラーネーム)" ><!-- ウェブアプリマニフェスト(アプリ化するページのrootディレクトリに入れてください。) --> <link rel ="manifest" href ="manifest.json" ><!-- PWAのアイコン --> <link rel ="icon" href ="アプリアイコンのファイルパス" sizes ="192x192" ><!-- サイズ 192px × 192px --> <link rel ="icon" href ="アプリアイコンのファイルパス" sizes ="512x512" ><!-- サイズ 512px × 512px --> </head > <body ><!-- ここにページの内容を書き込む --> <!-- PWAが登録可能か検査 --> <script >// rootディレクトリに「sw.js」というJSファイルを作成しておいてください。> if ( 'serviceWorker' in navigator ) { window .addEventListener ( 'load' ,() => { navigator .serviceWorker .register( './sw.js' )// rootディレクトリの「sw.js」を読み込み> .then( reg => { console .log ( "Service Worker 登録成功:" ,reg .scope ) ;} ) .catch( err => { console .log ( "Service Worker 登録失敗:" ,err ) ;} ) } ) ;} </script > </body > <script src ="JavaScriptのファイル名" ></script > </html >
アプリ化するHTMLと同じ階層(同じディレクトリ)に「sw.js」と「manifest.json」というファイルを作成しておいてください。
これらが終わったらHTMLでの操作はほぼ終了です。
次に「manifest.json」を設定していきます。以下のプログラムを参考に書いてください。
これでアプリのアイコンと情報の設定は完了です。{ "name" :"アプリ名をここに書く" ,"short_name" :"略称アプリ名をここに書く" ,"description" :"アプリの説明をここに書く" ,"start_url" :"アプリを開いた時に表示するHTMLファイルのパスをここに書く" ,"display" :"standalone" ,"background_color" :"背景色(16進法、RGB値、カラーネーム)" ,"theme_color" :"テーマカラー(16進法、RGB値、カラーネーム)" ,"orientation" :"landscape" ,// アプリを開いたときの表示方法(ここでは横向きでの表示を強制) "icons" :[ { "src" :"アプリアイコンのディレクトリパス" ,"sizes" :"192x192" ,// アイコンのサイズ "type" :"image/png" ,// アイコン画像のファイル形式(ここではpng画像) } ,{ "src" :"アプリアイコンのディレクトリパス" ,"sizes" :"512x512" ,// アイコンのサイズ "type" :"image/png" ,// アイコン画像のファイル形式(ここではpng画像) "purpose" :"maskable any" ,// マスク可能(maskable)であり、かつあらゆる目的(any)**に使用できることを宣言 } ,] }
補足として説明すると、
"orientation" : "landscape" は、アプリの画面の向きを宣言するものです。"landscape" は画面を常時横向きで固定、"portrait" は画面を常時縦向きで固定、"natural" はデバイスの画面の向きに合わせるというものです。特にスマホ、タブレットでは表示が異なるため、サイト、WEBアプリの設計に応じて使い分ける必要があります。
Novel Genesis EditorではPC向けに設計してあるので、Android端末などでも常時横向きになるように
"landscape" を宣言しています。また、
"purpose" : "maskable any" ,は、アイコンを切り抜いたり変形させても良いという宣言になります。Androidでは特に、メーカーやキャリアによって使用するホーム画面のランチャーが異なります。
GoogleではPixel Launcher、プレーンのAndroidだとGoogle Nowランチャー、Samsung GalaxyではOneUI、他にもMicrosoft launcher、docomo live UXなど多岐にわたり、それぞれ表示方法やインターフェースが大きく異なります。
そのインターフェースはアプリのアイコンにも適応され、例えば「Minecraft」のアイコンは docomo live UXでは正方形の角ばったアイコンで表示されるのに対し、 Galaxy OneUIでは少し丸みを帯びたアイコンで表示されます。
こういたランチャーごとの違いに適応させるか否かを設定するのが
"purpose" : "maskable any" ,です。アプリの情報が一通りできたので、いよいよアプリのメインロジックを書いていきます。
と言ってもすることは、デバイス(ブラウザのキャッシュ)内に保存するデータの指定と、オフライン時にキャッシュに保存したデータを表示する宣言です。
これによってオフライン時でもブラウザのページやPWAアプリ、AndroidアプリでWEBアプリ、WEBサイトを表示できるようにします。
操作するのは、最初に作った「sw.js」です。
このファイルではキャッシュとして保存するファイルのディレクトリパスを指定し、そのファイルをブラウザに記憶させる宣言、オフラインのときブラウザのキャッシュから表示するページの宣言までが書かれています。const CACHE_NAME ='キャッシュ名(自由に決めておk)' ;const urlsToCache =[ 'キャッシュとして保存するファイルのディレクトリパス' ,'キャッシュとして保存するファイルのディレクトリパス' ,'キャッシュとして保存するファイルのディレクトリパス' ,'キャッシュとして保存するファイルのディレクトリパス' ,] ;// インストール時にキャッシュ self .addEventListener ( 'install' ,event => { event .waitUntil ( caches .open( .CACHE_NAME )then( cache => cache .addAll .( )urlsToCache )then( () => self .skipWaiting () )) ;} ;) // アクティブ化時に古いキャッシュ削除 self .addEventListener ( 'activate' ,event => { event .waitUntil ( caches .keys() .then( cacheNames => { return Promise .all ( cacheNames .filter( name !===> nameCACHE_NAME ) .map( name .=> cachesdelete ( name )) ) ;} .) then( () => self .clients .claim () )) ;} ;) // 通信時にキャッシュから返す self .addEventListener ( 'fetch' ,event => { event .respondWith ( caches .match ( event .request ) .then ( response => { // キャッシュにあれば返す、なければネットワークから return response ||fetch ( event .request ) ;} .) catch ( () => {// 完全にオフラインでHTMLリクエストならオフライン画面(キャッシュとして保存するよう宣言したHTMLファイルから書き込む) if ( event .request .destination ==='document' ) { return caches .match ('./オフライン時に表示するHTMLファイル') ;} } ) ) ;} ;)
ページ、あるいはアプリやゲーム全体を保存する場合は、キャッシュとして保存するファイルを全て指定してあげてください。
ファイルのパスは、アプリ化するHTMLのある場所からの参照です。
それでは実際にPWA化できるのか検証してみましょう。
例ではノベルジェネシス・エディターに導入した際のスクショを貼っています。
PWAを導入したHTMLをVScodeのLiveサーバーで開きます。このときChrome系のブラウザで実行してください。
FirefoxやSafariではうまく動作しません。

開くと「インストール」や「利用可能なアプリ」というような内容でURLバーに項目が表示されます。
これをインストールしてみるとデスクトップアプリケーションのように使うことができます!

・Safari版 開発
Appleが開発・販売するiOS端末でも、ChromeならPWAとしてサイトのインストールが可能です。
しかしSafariではChrome版のプログラムでは、PWAにしても情報が表示されなかったり、アイコンがない状態のアプリになってしまいます。
そこで、< </の中に以下のコードを追加してください。
これで、iOSでもPWAが利用可能になります!<!-- iOS(Safari)対応 --> <link rel ="apple-touch-icon" href ="iOSで表示するアプリアイコン" > <meta name ="apple-mobile-web-app-capable" content ="yes" > <meta name ="apple-mobile-web-app-status-bar-style" content ="black-translucent" > <meta name ="apple-mobile-web-app-title" content ="アプリの名前" >