diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/ja/web/progressive_web_apps | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/ja/web/progressive_web_apps')
10 files changed, 1923 insertions, 0 deletions
diff --git a/files/ja/web/progressive_web_apps/add_to_home_screen/index.html b/files/ja/web/progressive_web_apps/add_to_home_screen/index.html new file mode 100644 index 0000000000..c0b922174f --- /dev/null +++ b/files/ja/web/progressive_web_apps/add_to_home_screen/index.html @@ -0,0 +1,222 @@ +--- +title: ホーム画面に追加 +slug: Web/Progressive_web_apps/Add_to_home_screen +tags: + - Manifest + - PWA + - Progressive web apps + - Service Worker + - a2hs + - add to home screen + - icon +translation_of: Web/Progressive_web_apps/Add_to_home_screen +--- +<p class="summary">ホーム画面に追加 (または A2HS と略記) は最近のブラウザーで利用できる機能で、ユーザーがウェブアプリを「インストール」、すなわちお気に入りのウェブアプリケーション (またはウェブサイト) を表すショートカットを自分のホーム画面に追加することができるので、今後はこのショートカットを一回タップすればアクセスできるようになります。このガイドでは、 A2HS の使用方法と、ユーザーがこの機能を利用できるようにするために開発者として行う必要のあることについて説明します。</p> + +<h2 id="Why_A2HS" name="Why_A2HS">なぜ A2HS か</h2> + +<p>A2HS は<a href="/ja/docs/Web/Progressive_web_apps">プログレッシブウェブアプリ</a>の思想の一環となるよう考えられています。 — ウェブアプリにネイティブアプリと同等の使い勝手を与えることで、今日のエコシステム戦争に参戦できるものです。この部分はホーム画面のアイコンをタップするという簡単な操作でアプリを起動できるものであり、きちんとした独自のウィンドウに表示されます。 A2HS ではこれを実現します。</p> + +<h2 id="What_browsers_support_A2HS" name="What_browsers_support_A2HS">A2HS に対応しているブラウザー</h2> + +<p>A2HS は、 iOS webview を除いたすべてのモバイルブラウザーが対応しています。また、一部の Chromium ベースのデスクトップブラウザーも対応しています。<br> + Firefox はモバイルでの対応を<a href="/ja/docs/Mozilla/Firefox/Releases/58#Other">v58 から</a>行っており、<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1407202">デスクトップでの対応</a>は作業中です。</p> + +<p>正確な詳細は <a href="https://caniuse.com/#feat=web-app-manifest">caniuse.com</a> を参照してください。</p> + +<h2 id="How_do_you_use_it" name="How_do_you_use_it">利用方法</h2> + +<p>A2HSを説明するために最小構成のサンプルページを作成しました(デモページは<a href="https://mdn.github.io/pwa-examples/a2hs/">ここから</a>, ソースコードは <a href="https://github.com/mdn/pwa-examples/tree/master/a2hs">こちらから</a>)。このページ自体に大した機能はありませんが、ページを端末のホーム画面に追加してサービスワーカーのお陰でページをオフラインで使用可能にするために必要なコードが書かれています。このページは何枚かのキツネの写真を表示します。</p> + +<p>もし Android 版 Firefox を使用可能であれば、それを使用して <code>https://mdn.github.io/pwa-examples/a2hs/</code> にあるデモに移動してみてください。キツネの写真を見ることができますが、もっと重要なのは、その中にプラス (+) アイコンを持つ "ホーム " のアイコンが表示されることです。 — これは、必要な機能が所定の場所にある任意のサイトのために表示される "ホーム画面に追加 "アイコンです。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15762/add-to-home-screen-icon.png" style="border-style: solid; border-width: 1px; display: block; height: 64px; margin: 0px auto; width: 500px;"></p> + +<p>このボタンをタップすると、このページをホーム画面に追加するかどうかの確認バナーが表示されます。ここで大きな + <em>ADD TO HOME SCREEN</em> を選択するとウェブアプリがホーム画面に追加されます。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15772/fx-a2hs-banner.png" style="border-style: solid; border-width: 1px; display: block; height: 421px; margin: 0px auto; width: 700px;"></p> + +<p>もし Chrome をお使いの場合は操作方法がやや異なります。 Chrome では、ページを読み込むと自動的にホーム画面に追加するかどうかのポップアップが現れます。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15771/chrome-a2hs-banner.png" style="border-style: solid; border-width: 1px; display: block; height: 421px; margin: 0px auto; width: 700px;"></p> + +<div class="note"> +<p><strong>注</strong>: Chrome でもバナーを表示したい場合は <a href="https://developers.google.com/web/fundamentals/app-install-banners/">Web App Install Banners</a> の記事が役立ちます。</p> +</div> + +<p>このポップアップで「追加しない」を選んでしまったけれど、やっぱりインストールを行ないたい場合は Chrome のメニューを開いて「ホーム画面に追加」を押せば追加することができます。</p> + +<p>ホーム画面に追加したウェブアプリは、どのブラウザーをお使いの場合でもフルネームではなく短縮名のほうで表示されます。これはほかのネイティブアプリの挙動と同じです。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15770/a2hs-on-home-screen.png" style="border-style: solid; border-width: 1px; display: block; height: 243px; margin: 0px auto; width: 400px;"></p> + +<p>このアイコンをタップすると開きますが、全画面アプリとして開き、その周囲のブラウザー UI は表示されません。</p> + +<h2 id="How_do_you_make_an_app_A2HS-ready" name="How_do_you_make_an_app_A2HS-ready">アプリを A2HS 対応にするには</h2> + +<p>ウェブアプリをA2HS対応にするには、次の要件を満たしている必要があります。</p> + +<ul> + <li>ウェブアプリが HTTPS で配信されていること ― ウェブはいまよりセキュアなほうへ向かっており A2HS を含むモダンなウェブ技術はセキュアな通信の上でのみ動くようになっています。</li> + <li>正しくフィールドが記入されたマニフェストファイルが含まれていて、それが HTML の <head> 部分にリンクされていること</li> + <li>ホーム画面に追加した時に正しく表示されるように適切なアイコンが含まれていること</li> + <li>Chrome は、追加でアプリがサービスワーカーを登録しておく必要があります (例えば、オフライン時に機能するように)。</li> +</ul> + +<h3 id="Manifest" name="Manifest">マニフェスト</h3> + +<p>マニフェストファイルは JSON 形式で書かれ、ウェブアプリ内のどこかに設置される必要があります (置き場所はルートディレクトリにするのがよいです)。またファイルの拡張子は <code>.webmanifest</code> にします。ここでは <code>manifest.webmanifest</code> といファイル名にしました。このファイルにはウェブアプリについての情報やどのような挙動をするのかについての設定が記されています。</p> + +<div class="note"> +<p><strong>注</strong>: 拡張子<code>.webmanifest</code> は W3C の<a href="/ja/docs/">WebAppManifestについてのドキュメント</a>の中の <a href="https://w3c.github.io/manifest/#media-type-registration">Media type registration</a> の節の中で定義されています。ただ、多くの場合ブラウザーは拡張子 <code>.json</code> マニフェストファイルをサポートしています。</p> +</div> + +<p>A2HS に必要なフィールドは次の通りです。</p> + +<ul> + <li><code>background_color</code>: いくつかのアプリのコンテキストで使用する背景色を指定します。 A2HS に最も関連するのは、ホーム画面のアプリアイコンをタップして最初にロードを開始したときに表示されるスプラッシュ画面です (現在のところ、これは Chrome でアプリがホーム画面に追加されたときにのみ表示されます)。</li> + <li><code>display</code>: アプリの表示方法を指定します。独立したアプリ (単なるウェブページではなく) のように見せるには、 <code>fullscreen</code> (UIが全く表示されない) や <code>standalone</code> (よく似ているが、ステータスバーなどのシステムレベルの UI 要素が表示される場合がある) などの値を選択してください。</li> + <li><code>icons</code>: アプリをさまざまな場所 (タスク切り替えや肝心のホーム画面) など、で表示する際に使用するブラウザーのアイコンを指定します。今回のデモでは1つだけを含めました。</li> + <li><code>name</code>/<code>short_name</code>: これらのフィールドは、異なる場所でアプリを表示する際に表示されるアプリ名を提供します。 <code>name</code> はアプリの完全な名前を提供し、 <code>short_name</code> は完全な名前を表示するためのスペースが不足している場合に使用される短縮名を提供します。アプリの名前が特に長い場合は、両方を指定することをお勧めします。</li> + <li><code>start_url</code>: ホーム画面に追加したアプリが起動したときに読み込まれる資産へのパスを指定します。これは、サイトインデックスを指す相対 URL であり、マニフェストの URL からの相対 URL でなければならないことに注意してください。また、 Chrome ではインストールバナーを表示するのに必要ですが、 Firefox でプラス印の付いたホームのアイコンを表示するためは必要ではないことに注意してください。</li> +</ul> + +<p>サンプルアプリのマニフェストは次のようになります。</p> + +<pre class="brush: js notranslate">{ + "background_color": "purple", + "description": "Shows random fox pictures. Hey, at least it isn't cats.", + "display": "fullscreen", + "icons": [ + { + "src": "icon/fox-icon.png", + "sizes": "192x192", + "type": "image/png" + } + ], + "name": "Awesome fox pictures", + "short_name": "Foxes", + "start_url": "/pwa-examples/a2hs/index.html" +}</pre> + +<h3 id="Appropriate_icon" name="Appropriate_icon">適切なアイコン</h3> + +<p>As shown in the above manifest listing, we are including a 192 x 192 px icon for use in our app. You can include more sizes if you want; Android will choose the most appropriate size for each different use case. You could also decide to include different types of icons so devices can use the best one they are able to (e.g., Chrome already supports the WebP format).</p> + +<p>Note that the <code>type</code> member in each icon's object specifies the icon's mimetype, so the browser can quickly read what type the icon is, and then ignore it and move to a different icon if it doesn't support it.</p> + +<p>In terms of how to design the icon, you should follow the same best practices you'd follow for any Android icon (see the <a href="https://developer.android.com/guide/practices/ui_guidelines/icon_design.html">Android icon design guidelines</a>).</p> + +<h3 id="Link_the_HTML_to_the_manifest" name="Link_the_HTML_to_the_manifest">HTML からマニフェストへリンクする</h3> + +<p>To finish setting up your manifest, you need to reference it from the HTML of your application's home page:</p> + +<pre class="brush: html notranslate"><link rel="manifest" href="manifest.webmanifest"></pre> + +<p>Browsers that support A2HS will know where to look for your manifest once this is in place.</p> + +<h2 id="What_does_A2HS_not_give_you" name="What_does_A2HS_not_give_you">A2HS でできないこと</h2> + +<p>Bear in mind that when you add an app to your Home screen, it just makes the app easily accessible — it doesn't download the app's assets and data to your device and make the app available offline, or anything like that. To make your app work offline, you have to use the <a href="/ja/docs/Web/API/Service_Worker_API">Service Worker API</a> to handle storing the assets offline, and if required, <a href="/ja/docs/Web/API/Web_Storage_API">Web storage</a> or <a href="/ja/docs/Web/API/IndexedDB_API">IndexedDB</a> to store its data.</p> + +<p>In our example app, we've just used a service worker to store all necessary files. The service worker is registered against the site with the final code block in the <code><a href="https://github.com/mdn/pwa-examples/blob/master/a2hs/index.js">index.js</a></code> file. We then cache all the site's assets using the <a href="/ja/docs/Web/API/Cache">Cache API</a>, and serve them from the cache instead of the network using the code in the <a href="https://github.com/mdn/pwa-examples/blob/master/a2hs/sw.js">sw.js</a> file.</p> + +<h2 id="A2HS_on_desktop" name="A2HS_on_desktop">デスクトップでの A2HS</h2> + +<p>While originally intended to improve user experience on mobile OSes, there is movement to make PWAs installable on desktop platforms too.</p> + +<div class="note"> +<p><strong>Note</strong>: At the time of writing, the functionality described below was only supported in newer versions of Chrome — by default on Windows, and behind the <code>#enable-desktop-pwas</code> flag on macOS.</p> +</div> + +<h3 id="Adding_an_install_button" name="Adding_an_install_button">インストールボタンの追加</h3> + +<p>PWA インストール機能をデスクトップでも実現するには、まずインストールボタンをドキュメントに追加する必要があります。デスクトップではモバイル端末とは違い自動的にポップアップなどが出るわけではなくユーザーがトリガーを設定してやる必要があるのです。</p> + +<pre class="brush: html notranslate"><button class="add-button">ホーム画面に追加</button></pre> + +<p>例えばこんなふうにデザインします。</p> + +<pre class="brush: css notranslate">.add-button { + position: absolute; + top: 1px; + left: 1px; +}</pre> + +<h3 id="JavaScript_for_handling_the_install" name="JavaScript_for_handling_the_install">インストールを扱うための JavaScript</h3> + +<p>At the bottom of our <a href="https://github.com/mdn/pwa-examples/blob/master/a2hs/index.js"><code>index.js</code> file</a>, we added some JavaScript to handle the installation. First of all, we declare a <code>deferredPrompt</code> variable (which we'll explain later on), get a reference to our install button, and set it to <code>display: none</code> initially:</p> + +<pre class="brush: js notranslate">let deferredPrompt; +const addBtn = document.querySelector('.add-button'); +addBtn.style.display = 'none';</pre> + +<p>We hide the button initially because the PWA will not be available for install until it follows the A2HS criteria. When this happens, supporting browsers will fire a <code>beforeinstallprompt</code> event. We can then use a handler like the one below to handle the installation:</p> + +<pre class="brush: js notranslate">window.addEventListener('beforeinstallprompt', (e) => { + // Prevent Chrome 67 and earlier from automatically showing the prompt + e.preventDefault(); + // Stash the event so it can be triggered later. + deferredPrompt = e; + // Update UI to notify the user they can add to home screen + addBtn.style.display = 'block'; + + addBtn.addEventListener('click', (e) => { + // hide our user interface that shows our A2HS button + addBtn.style.display = 'none'; + // Show the prompt + deferredPrompt.prompt(); + // Wait for the user to respond to the prompt + deferredPrompt.userChoice.then((choiceResult) => { + if (choiceResult.outcome === 'accepted') { + console.log('User accepted the A2HS prompt'); + } else { + console.log('User dismissed the A2HS prompt'); + } + deferredPrompt = null; + }); + }); +});</pre> + +<p>So here we:</p> + +<ul> + <li>Call {{domxref("Event.preventDefault()")}} to stop Chrome 67 and earlier from calling the install prompt automatically (this behavior changed in Chrome 68).</li> + <li>Store the event object in the <code>deferredPrompt</code> variable so it can be used later on to perform the actual installation.</li> + <li>Set the button to <code>display: block</code> so it appears in the UI for the user to click.</li> + <li>Set a <code>click</code> handler for the button.</li> +</ul> + +<p>The click handler contains the following steps:</p> + +<ul> + <li>Hide the button again with <code>display: none</code> — it is no longer needed once the app is installed.</li> + <li>Use the <code>prompt()</code> method available on the <code>beforeinstallprompt</code> event object (stored in <code>deferredPrompt</code>) to trigger showing the install prompt.</li> + <li>Respond to the user's interaction with the prompt using the <code>userChoice</code> property, again available on the <code>beforeinstallprompt</code> event object.</li> + <li>Set <code>deferredPrompt</code> to null since it is no longer needed.</li> +</ul> + +<p>So when the button is clicked, the install prompt appears.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16281/chrome-desktop-a2hs-banner.png" style="border-style: solid; border-width: 1px; display: block; height: 163px; margin: 0px auto; width: 300px;"></p> + +<p>If the user selects <em>Install</em>, the app is installed (available as standalone desktop app), and the Install button no longer shows (the <code>onbeforeinstallprompt</code> event no longer fires if the app is already installed). When you open the app, it will appear in its own window:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16280/a2hs-installed-desktop.png" style="border-style: solid; border-width: 1px; display: block; height: 296px; margin: 0px auto; width: 500px;"></p> + +<p>If the user selects <em>Cancel</em>, the state of the app goes back to how it was before the button was clicked.</p> + +<div class="note"> +<p><strong>Note</strong>: The code for this section was mostly taken from <a href="https://developers.google.com/web/fundamentals/app-install-banners/">App install banners/Add to Home Screen</a> by Pete LePage.</p> +</div> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li><a href="/ja/docs/Web/Progressive_web_apps">プログレッシブウェブアプリ</a></li> + <li><a href="/ja/docs/Web/API/Service_Worker_API">Service Worker API</a></li> + <li><a href="/ja/docs/Web/Manifest">ウェブマニフェストリファレンス</a></li> + <li><a href="https://developers.google.com/web/fundamentals/app-install-banners/">App install banners</a></li> +</ul> + +<div>{{QuickLinksWithSubpages("/ja/docs/Web/Progressive_web_apps/")}}</div> diff --git a/files/ja/web/progressive_web_apps/advantages/index.html b/files/ja/web/progressive_web_apps/advantages/index.html new file mode 100644 index 0000000000..54934889cc --- /dev/null +++ b/files/ja/web/progressive_web_apps/advantages/index.html @@ -0,0 +1,64 @@ +--- +title: プログレッシブウェブアプリの利点 +slug: Web/Progressive_web_apps/Advantages +tags: + - PWA + - Progressive web apps + - advantages + - concepts +translation_of: Web/Progressive_web_apps/Introduction#Advantages_of_web_applications +--- +<p class="summary"><span class="seoSummary">プログレッシブウェブアプリ(Progressive web apps、PWA)には、以下のセクションにリストされているすべての利点があります。</span></p> + +<p> </p> + +<h2 id="Discoverable" name="Discoverable">発見可能<img alt="" src="https://mdn.mozillademos.org/files/12654/discoverable.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>最終的な目的は、ウェブアプリが検索エンジンでより適切に表現され、公開されやすく、カタログ化とランク付けされ、ブラウザーにメタデータを使用してそれらに特別な機能を提供することです。</p> + +<p>一部の機能は、<a href="http://ogp.me/">Open Graph</a> のような独自の技術によって特定のウェブベースのプラットフォームですでにできるようになっています。 Open Graph は、メタタグを使用して HTML の <code><head></code> で類似のメタデータを指定するための形式を提供します。</p> + +<p>ここで関連するウェブ標準は<a href="/ja/docs/Web/Manifest">ウェブアプリマニフェスト</a>(Web app manifest)です。 これは、名前、アイコン、スプラッシュスクリーン、テーマカラーなどのアプリの機能を JSON 形式のマニフェストファイルで定義します。 これは、アプリ一覧やデバイスのホーム画面などのコンテキストで使用するためのものです。</p> + +<ul> +</ul> + +<h2 id="Installable" name="Installable">インストール可能<img alt="" src="https://mdn.mozillademos.org/files/12656/installable.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>アプリエクスペリエンスの中心的な部分は、ユーザーが自分のホーム画面にアプリアイコンを表示して、タップしてアプリをネイティブコンテナに開くことができることで、基盤となるプラットフォームとうまく統合されていると感じます。</p> + +<p>最新のウェブアプリは、ウェブアプリマニフェスト内で設定されたプロパティや、<a href="/ja/docs/Web/Progressive_web_apps/Add_to_home_screen">ホーム画面に追加</a>と呼ばれる最新のスマートフォンのブラウザーで利用可能な機能を介して、このネイティブアプリの感じを持つことができます。</p> + +<h2 id="Linkable" name="Linkable">リンク可能<img alt="" src="https://mdn.mozillademos.org/files/12658/linkable.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>ウェブの最も強力な機能の1つは、特定の URL でアプリにリンクできることです — アプリストアは不要で、複雑なインストールプロセスも不要です。 これこそがいつものことです。</p> + +<h2 id="Network_independent" name="Network_independent">ネットワーク非依存<img alt="" src="https://mdn.mozillademos.org/files/12660/network-independent.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>最新のウェブアプリは、ネットワークの信頼性が低い場合、または存在しない場合でも機能します。 ネットワークの独立性の背景にある基本的な考え方は、次のことができるようにすることです。</p> + +<ul> + <li>ネットワークにアクセスできない場合でも、サイトを再訪してそのコンテンツを取得する。</li> + <li>接続性が悪い状況でも、ユーザーが以前に少なくとも1回アクセスしたことがある、あらゆる種類のコンテンツを閲覧する。</li> + <li>接続がない状況下でユーザーに見せるものを制御する。</li> +</ul> + +<p>これは技術の組み合わせによって達成されます — ページ要求を制御する<a href="/ja/docs/Web/API/Service_Worker_API">サービスワーカー</a>(オフラインでの保存など)、ネットワーク要求への応答をオフラインで保存するための <a href="/ja/docs/Web/API/Cache">Cache API</a>(サイトアセット(静的なコンテンツ)の保存に非常に便利)、アプリケーションデータをオフラインで格納するための <a href="/ja/docs/Web/API/Web_Storage_API">Web Storage</a> や <a href="/ja/docs/Web/API/IndexedDB_API">IndexedDB</a> などのクライアント側のデータストレージ技術です。</p> + +<h2 id="Progressive" name="Progressive">プログレッシブ<img alt="" src="https://mdn.mozillademos.org/files/12662/progressive.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>最新のウェブアプリは、完全対応のブラウザーには非常にクールなエクスペリエンスを提供し、完全ではない対応のブラウザーには(あまり魅力的ではないが)許容可能なエクスペリエンスを提供するように開発できます。<a href="/ja/docs/Glossary/Progressive_Enhancement"> プログレッシブエンハンスメント</a>(progressive enhancement)などのベストプラクティスを使って、これを長年にわたって行ってきました。</p> + +<h2 id="Re-engageable" name="Re-engageable">再エンゲージ可能<img alt="" src="https://mdn.mozillademos.org/files/12666/re-engageable.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>ネイティブプラットフォームの大きな利点の1つは、アプリを見ていないときやデバイスを使用していないときでも、ユーザーが更新や新しいコンテンツに簡単に再エンゲージ(係り合い)できることです。 最新のウェブアプリでも、新しい技術を使用してこれを実行できます — ページを制御するための<a href="/ja/docs/Web/API/Service_Worker_API/Using_Service_Workers">サービスワーカー</a>(Service Worker)、サービスワーカーを介してサーバーからアプリに直接更新を送信するための <a href="/ja/docs/Web/API/Push_API">Web Push API</a> 、ユーザーがブラウザーを見ていないときにユーザーとのエンゲージを援助するシステム通知を生成するための <a href="/ja/docs/Web/API/Notifications_API">Notifications API</a> といったもの。</p> + +<h2 id="Responsive" name="Responsive">レスポンシブ<img alt="" src="https://mdn.mozillademos.org/files/12650/responsive.svg" style="float: right; height: 40px; width: 38px;"></h2> + +<p>レスポンシブウェブアプリ(Responsive web apps)では、メディアクエリやビューポートなどの技術を使用して、その UI があらゆる形状(デスクトップ、モバイル、タブレット、または次に来るものは何でも)に適合することを確認します。</p> + +<h2 id="Safe" name="Safe">安全<img alt="" src="https://mdn.mozillademos.org/files/12664/safe.svg" style="float: right; height: 47px; width: 38px;"></h2> + +<p>ウェブプラットフォームは、HTTPS を利用してセキュリティを念頭に置いてアプリを開発する限り、スヌーピング(覗き見)を防ぎ、コンテンツが改ざんされていないことを保証する安全な配信メカニズムを提供します。 さらに、PWA が正しい URL にあることを確認することで、PWA の本質を検証できます。 一方、アプリストア内のアプリは、多くの場合1つのもののように見えますが別のものになります(<a href="https://twitter.com/andreasbovens/status/926965095296651264">例</a>)。</p> + +<p> </p> diff --git a/files/ja/web/progressive_web_apps/app_structure/index.html b/files/ja/web/progressive_web_apps/app_structure/index.html new file mode 100644 index 0000000000..7cdac9ed6e --- /dev/null +++ b/files/ja/web/progressive_web_apps/app_structure/index.html @@ -0,0 +1,285 @@ +--- +title: プログレッシブウェブアプリの構造 +slug: Web/Progressive_web_apps/App_structure +tags: + - App shell + - PWAs + - Progressive web apps + - Service Workers + - Streams + - Structure + - js13kGames + - progressive +translation_of: Web/Progressive_web_apps/App_structure +--- +<div>{{PreviousMenuNext("Web/Progressive_web_apps/Introduction", "Web/Progressive_web_apps/Offline_Service_workers", "Web/Progressive_web_apps")}}</div> + +<p class="summary"><span class="seoSummary">PWA の背後にある理論が分かったところで、推奨されるアプリの構造を見てみましょう。まず、 <a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a> アプリの分析、それがなぜそのように構築されているのか、それがもたらす利点について説明します。</span></p> + +<h2 id="Architecture_of_an_app" name="Architecture_of_an_app">アプリのアーキテクチャ</h2> + +<p>ウェブサイトをレンダリングするには、サーバー上とクライアント上の2つのアプローチがあります。どちらにも長所と短所があり、2つのアプローチをある程度組み合わせることができます。</p> + +<ul> + <li>サーバー側レンダリング (Server-side rendering、SSR) は、ウェブサイトがサーバー上でレンダリングされるという意味で、初回の読み込みは速くなりますが、ページ間で移動すると新しい HTML コンテンツをダウンロードする必要があります。これはブラウザーが変わってもうまく動作しますが、ページ間で移動する時間が不利であり、したがって一般的にパフォーマンスが悪くなります。 — ページを読み込むごとに、サーバーへの新しい往復が必要になるからです。</li> + <li>クライアント側レンダリング (Client-side rendering、CSR) を使用すると、ウェブサイトがさまざまなページに移動したときにブラウザー内でほぼ瞬時に更新できますが、初期ダウンロード数が増え、最初はクライアントで余分なレンダリングが必要になります。 ウェブサイトは最初の訪問では遅くなりますが、その後の訪問ではずっと速くなります。</li> +</ul> + +<p>SSR と CSR を組み合わせることで最良の結果が得られます — ウェブサイトをサーバー上にレンダリングし、そのコンテンツをキャッシュしてから、必要に応じてクライアント側でレンダリングを更新することができます。 SSR のおかげで最初のページの読み込みは速く、クライアントは変更された部分だけでページを再レンダリングできるため、ページ間のナビゲーションはスムーズです。</p> + +<p>PWA は好きなアプローチで構築できますが、他のものよりもうまく機能するものもあります。 最も人気のあるアプローチは、 SSR と CSR をまさに上記の方法で組み合わせた「アプリシェル」の概念です。 さらに、今後の記事で詳細に説明し、サンプルアプリで使用する「オフライン優先」の方法論に従います。 <a href="/ja/docs/Web/API/Streams_API">Streams API</a> に関する新しいアプローチもありますが、これについては後で簡単に説明します。</p> + +<h2 id="App_shell" name="App_shell">アプリシェル</h2> + +<p>アプリシェル (App shell) の概念は、最小限のユーザーインターフェイスをできるだけ早く読み込んでからキャッシュすること関係しています。 それで、アプリのすべてのコンテンツを読み込むことで、その後のアクセスでオフラインで利用できるようにします。 こうすることで、次回デバイスからアプリにアクセスしたときに、 UI がすぐにキャッシュから読み込まれ、 (まだキャッシュにない場合) 新しいコンテンツがサーバーから要求されます。</p> + +<p>この構造は高速であり、ローディングスピナーや空白のページではなく、ユーザーが即座に「何か」を見たときにも高速に感じられます。 ネットワーク接続が利用できない場合は、ウェブサイトにオフラインでアクセスすることもできます。</p> + +<p>サーバーから要求される内容とキャッシュから取得される内容を<a href="/ja/docs/Web/API/Service_Worker_API">サービスワーカー</a>で制御できます。 詳細は次の記事で説明します — ここでは構造自体に焦点を当てます。</p> + +<h3 id="Why_should_I_use_it" name="Why_should_I_use_it">なぜそれを使うべきか?</h3> + +<p>このアーキテクチャにより、ウェブサイトはすべての PWA 機能を最大限に活用できます — つまり、アプリシェルをキャッシュし、パフォーマンスを大幅に向上させるように動的コンテンツを管理します。 基本的なシェルに加えて、<a href="/ja/docs/Web/Progressive_web_apps/Add_to_home_screen">ホーム画面への追加</a>や<a href="/ja/docs/Web/API/Push_API">プッシュ通知</a>などの他の機能を追加でき、ユーザーのブラウザーでサポートされていない場合でも、アプリは正常に動作することがわかっているので安全です — これがプログレッシブエンハンスメントの美しさです。</p> + +<p>ウェブサイトは、ウェブのすべての利点を維持しながら、即時の対話と堅実なパフォーマンスを備えたネイティブアプリのように感じられます。</p> + +<h3 id="Being_linkable_progressive_and_responsive_by_design" name="Being_linkable_progressive_and_responsive_by_design">設計によりリンク可能、プログレッシブ、レスポンシブであること</h3> + +<p>PWA の利点を覚えておき、アプリケーションを設計するときには、それらを念頭に置いておくことが重要です。 アプリシェルのアプローチにより、ウェブサイトは次のようになります。</p> + +<ul> + <li>リンク可能: ネイティブアプリのように動作しますが、それでもウェブサイトです — ページ内のリンクをクリックして、共有したい場合は他の人に URL を送信できます。</li> + <li>プログレッシブ: 「古き良き基本的なウェブサイト」から始めて、ブラウザーで利用できるかどうかを検出し、サポートが利用できない場合に発生するエラーを適切に処理しながら、新機能を徐々に追加します。 例えば、サービスワーカーの助けを借りたオフラインモードは、ウェブサイトのエクスペリエンスを向上させるための特別な特徴ですが、それがなくても完全に使用可能です。</li> + <li>レスポンシブ: レスポンシブウェブデザイン (Responsive web design) はプログレッシブウェブアプリにも適用され、どちらも主にモバイルデバイス用です。 ブラウザーを搭載したデバイスは数多くあります — <a href="/ja/docs/Mobile/Viewport_meta_tag">ビューポートメタタグ</a>、<a href="/ja/docs/Web/CSS/Media_Queries/Using_media_queries">CSS メディアクエリ</a>、<a href="/ja/docs/Web/CSS/CSS_Flexible_Box_Layout">フレックスボックス</a>、<a href="/ja/docs/Web/CSS/CSS_Grid_Layout">CSS グリッド</a>などの技術を使用して、さまざまな画面サイズ、ビューポート、ピクセル密度で機能するようにウェブサイトを準備することが重要です。</li> +</ul> + +<h2 id="Different_concept_streams" name="Different_concept_streams">異なるコンセプト: ストリーム</h2> + +<p><a href="/ja/docs/Web/API/Streams_API">Streams API</a> を使用すると、サーバー側またはクライアント側のレンダリングに対するまったく異なるアプローチを実現できます。 サービスワーカーからの少しの助けで、ストリームはコンテンツを解析する方法を大いに改善することができます。</p> + +<p>アプリシェルのモデルでは、ウェブサイトがレンダリングを開始する前にすべてのリソースが利用可能である必要があります。 HTML とは異なり、ブラウザーが実際にデータを既にストリーミング (読み込みながら再生) しているので、いつウェブサイトに要素が読み込まれてレンダリングされるかを見ることができます。 ただし、 JavaScript を「動作可能」にするには、 JavaScript を完全にダウンロードする必要があります。</p> + +<p>Streams API を使用すると、開発者はサーバーからのデータストリーミングに直接アクセスできます — データに操作を実行する場合 (例えば、動画にフィルタを追加する場合など) は、すべてがダウンロードされて BLOB (またはその他) に変換されるのを待つ必要はもうありません — すぐに始めることができます。 それは、きめ細かい制御を提供します — ストリームを開始したり、別のストリームとチェーンしたり、キャンセルしたり、エラーをチェックしたりすることができます。</p> + +<p>理論的には、ストリーミングはより優れたモデルですが、より複雑でもあり、この記事の執筆時点 (2018年3月) では Streams API はまだ開発中であり、主要ブラウザーのいずれでもまだ完全には利用できません。 それが利用可能になると、それはコンテンツを提供する最も速い方法になるでしょう — パフォーマンスの面で利点は巨大になるでしょう。</p> + +<p>実用的な例や詳細については、<a href="/ja/docs/Web/API/Streams_API">Streams API の資料</a>を参照してください。</p> + +<h2 id="Structure_of_our_example_application" name="Structure_of_our_example_application">サンプルアプリの構造</h2> + +<p><a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a> ウェブサイトの構造は非常に単純です。単一の HTML ファイル (<a href="https://github.com/mdn/pwa-examples/blob/master/js13kpwa/index.html">index.html</a>) と基本的な CSS のスタイル付け (<a href="https://github.com/mdn/pwa-examples/blob/master/js13kpwa/style.css">style.css</a>)、いくつかの画像、スクリプト、およびフォントで構成されています。 フォルダー構造は次のようになります。</p> + +<p><img alt="js13kPWA のフォルダー構成" src="https://mdn.mozillademos.org/files/15925/js13kpwa-directory.png" style="border-style: solid; border-width: 1px; display: block; height: 356px; margin: 0px auto; width: 320px;"></p> + +<h3 id="The_HTML" name="The_HTML">HTML</h3> + +<p>HTML の観点から見ると、アプリシェルは content セクション以外のすべてのものです。</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>js13kGames A-Frame entries</title> + <meta name="description" content="A list of A-Frame entries submitted to the js13kGames 2017 competition, used as an example for the MDN articles about Progressive Web Apps."> + <meta name="author" content="end3r"> + <meta name="theme-color" content="#B12A34"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta property="og:image" content="icons/icon-512.png"> + <link rel="shortcut icon" href="favicon.ico"> + <link rel="stylesheet" href="style.css"> + <link rel="manifest" href="js13kpwa.webmanifest"> + <script src="data/games.js" defer></script> + <script src="app.js" defer></script> +</head> +<body> +<header> + <p><a class="logo" href="http://js13kgames.com"><img src="img/js13kgames.png" alt="js13kGames"></a></p> +</header> +<main> + <h1>js13kGames A-Frame entries</h1> + <p class="description">List of games submitted to the <a href="http://js13kgames.com/aframe">A-Frame category</a> in the <a href="http://2017.js13kgames.com">js13kGames 2017</a> competition. You can <a href="https://github.com/mdn/pwa-examples/blob/master/js13kpwa">fork js13kPWA on GitHub</a> to check its source code.</p> + <button id="notifications">Request dummy notifications</button> + <section id="content"> + // コンテンツはここに動的に挿入されます + </section> +</main> +<footer> + <p>© js13kGames 2012-2018, created and maintained by <a href="http://end3r.com">Andrzej Mazur</a> from <a href="http://enclavegames.com">Enclave Games</a>.</p> +</footer> +</body> +</html></pre> + +<p>{{htmlelement("head")}} セクションには、タイトル、説明、 CSS へのリンク、ウェブマニフェスト、ゲームコンテンツの JS ファイル、および <code>app.js</code> (ここで、JavaScript アプリが初期化されます) などの基本的な情報が含まれています。 {{htmlelement("body")}} は、{{htmlelement("header")}} (リンクした画像を含む)、{{htmlelement("main")}} ページ (タイトル、説明、コンテンツの場所)、および {{htmlelement("footer")}} (著作権およびリンク) に分割されています。</p> + +<p>アプリの唯一の仕事は、 js13kGames 2017 コンペティションからすべての A-Frame エントリをリストすることです。 ご覧のとおり、これはごく普通の1ページのウェブサイトです — 重要なのは、実際の PWA 機能の実装に集中できるように、簡単なものを用意することです。</p> + +<h3 id="The_CSS" name="The_CSS">CSS</h3> + +<p>CSS も可能な限りわかりやすくなっています。 つまり、 {{cssxref("@font-face")}} を使用してカスタムフォントを読み込んで使用し、さらに HTML 要素の単純なスタイルを適用します。 全体的なアプローチは、デザインをモバイルデバイス (レスポンシブウェブデザインのアプローチ) とデスクトップデバイスの両方で見栄えよくすることです。</p> + +<h3 id="The_main_app_JavaScript" name="The_main_app_JavaScript">メインアプリの JavaScript</h3> + +<p><code>app.js</code> ファイルは、次の記事で詳しく調べることをいくつか行います。 まず最初に、次のテンプレートに基づいてコンテンツを生成します。</p> + +<pre class="brush: js notranslate">var template = "<article>\n\ + <img src='data/img/SLUG.jpg' alt='NAME'>\n\ + <h3>#POS. NAME</h3>\n\ + <ul>\n\ + <li><span>Author:</span> <strong>AUTHOR</strong></li>\n\ + <li><span>Twitter:</span> <a href='https://twitter.com/TWITTER'>@TWITTER</a></li>\n\ + <li><span>Website:</span> <a href='http://WEBSITE/'>WEBSITE</a></li>\n\ + <li><span>GitHub:</span> <a href='https://GITHUB'>GITHUB</a></li>\n\ + <li><span>More:</span> <a href='http://js13kgames.com/entries/SLUG'>js13kgames.com/entries/SLUG</a></li>\n\ + </ul>\n\ +</article>"; +var content = ''; +for(var i=0; i<games.length; i++) { + var entry = template.replace(/POS/g,(i+1)) + .replace(/SLUG/g,games[i].slug) + .replace(/NAME/g,games[i].name) + .replace(/AUTHOR/g,games[i].author) + .replace(/TWITTER/g,games[i].twitter) + .replace(/WEBSITE/g,games[i].website) + .replace(/GITHUB/g,games[i].github); + entry = entry.replace('<a href=\'http:///\'></a>','-'); + content += entry; +}; +document.getElementById('content').innerHTML = content;</pre> + +<p>次に、サービスワーカーを登録します。</p> + +<pre class="brush: js notranslate">if('serviceWorker' in navigator) { + navigator.serviceWorker.register('/pwa-examples/js13kpwa/sw.js'); +};</pre> + +<p>次のコードブロックは、ボタンがクリックされたときに通知の許可を要求します。</p> + +<pre class="brush: js notranslate">var button = document.getElementById("notifications"); +button.addEventListener('click', function(e) { + Notification.requestPermission().then(function(result) { + if(result === 'granted') { + randomNotification(); + } + }); +});</pre> + +<p>最後のブロックは、ゲームリストからランダムに選択されたアイテムを表示する通知を作成します。</p> + +<pre class="brush: js notranslate">function randomNotification() { + var randomItem = Math.floor(Math.random()*games.length); + var notifTitle = games[randomItem].name; + var notifBody = 'Created by '+games[randomItem].author+'.'; + var notifImg = 'data/img/'+games[randomItem].slug+'.jpg'; + var options = { + body: notifBody, + icon: notifImg + } + var notif = new Notification(notifTitle, options); + setTimeout(randomNotification, 30000); +}</pre> + +<h3 id="The_service_worker" name="The_service_worker">サービスワーカー</h3> + +<p>すばやく見る最後のファイルはサービスワーカーです: <code>sw.js</code> — それは最初に <code>games.js</code> ファイルからデータをインポートします。</p> + +<pre class="brush: js notranslate">self.importScripts('data/games.js');</pre> + +<p>次に、アプリシェルとコンテンツの両方から、キャッシュされるすべてのファイルのリストを作成します。</p> + +<pre class="brush: js notranslate">var cacheName = 'js13kPWA-v1'; +var appShellFiles = [ + '/pwa-examples/js13kpwa/', + '/pwa-examples/js13kpwa/index.html', + '/pwa-examples/js13kpwa/app.js', + '/pwa-examples/js13kpwa/style.css', + '/pwa-examples/js13kpwa/fonts/graduate.eot', + '/pwa-examples/js13kpwa/fonts/graduate.ttf', + '/pwa-examples/js13kpwa/fonts/graduate.woff', + '/pwa-examples/js13kpwa/favicon.ico', + '/pwa-examples/js13kpwa/img/js13kgames.png', + '/pwa-examples/js13kpwa/img/bg.png', + '/pwa-examples/js13kpwa/icons/icon-32.png', + '/pwa-examples/js13kpwa/icons/icon-64.png', + '/pwa-examples/js13kpwa/icons/icon-96.png', + '/pwa-examples/js13kpwa/icons/icon-128.png', + '/pwa-examples/js13kpwa/icons/icon-168.png', + '/pwa-examples/js13kpwa/icons/icon-192.png', + '/pwa-examples/js13kpwa/icons/icon-256.png', + '/pwa-examples/js13kpwa/icons/icon-512.png' +]; +var gamesImages = []; +for(var i=0; i<games.length; i++) { + gamesImages.push('data/img/'+games[i].slug+'.jpg'); +} +var contentToCache = appShellFiles.concat(gamesImages);</pre> + +<p>次のブロックはサービスワーカーをインストールし、上記のリストに含まれるすべてのファイルを実際にキャッシュします。</p> + +<pre class="brush: js notranslate">self.addEventListener('install', function(e) { + console.log('[Service Worker] Install'); + e.waitUntil( + caches.open(cacheName).then(function(cache) { + console.log('[Service Worker] Caching all: app shell and content'); + return cache.addAll(contentToCache); + }) + ); +});</pre> + +<p>最後に、サービスワーカーは、キャッシュからコンテンツが利用できる場合はそれをキャッシュから取得し、オフライン機能を提供します。</p> + +<pre class="brush: js notranslate">self.addEventListener('fetch', function(e) { + e.respondWith( + caches.match(e.request).then(function(r) { + console.log('[Service Worker] Fetching resource: '+e.request.url); + return r || fetch(e.request).then(function(response) { + return caches.open(cacheName).then(function(cache) { + console.log('[Service Worker] Caching new resource: '+e.request.url); + cache.put(e.request, response.clone()); + return response; + }); + }); + }) + ); +});</pre> + +<h3 id="The_JavaScript_data" name="The_JavaScript_data">JavaScript データ</h3> + +<p>ゲームデータは、 JavaScript オブジェクト (<code><a href="https://github.com/mdn/pwa-examples/blob/master/js13kpwa/data/games.js">games.js</a></code>) の形式で <code>data</code> フォルダーにあります。</p> + +<pre class="brush: js notranslate">var games = [ + { + slug: 'lost-in-cyberspace', + name: 'Lost in Cyberspace', + author: 'Zosia and Bartek', + twitter: 'bartaz', + website: '', + github: 'github.com/bartaz/lost-in-cyberspace' + }, + { + slug: 'vernissage', + name: 'Vernissage', + author: 'Platane', + twitter: 'platane_', + website: 'github.com/Platane', + github: 'github.com/Platane/js13k-2017' + }, +// ... + { + slug: 'emma-3d', + name: 'Emma-3D', + author: 'Prateek Roushan', + twitter: '', + website: '', + github: 'github.com/coderprateek/Emma-3D' + } +];</pre> + +<p>すべてのエントリは <code>data/img</code> フォルダーに独自の画像を持っています。 これは JavaScript でコンテンツセクションに読み込まれたコンテンツです。</p> + +<h2 id="Next_up" name="Next_up">次へ</h2> + +<p>次の記事では、サービスワーカーの助けを借りて、オフラインで使用するためにアプリシェルとコンテンツがどのようにキャッシュされるかについて詳しく説明します。</p> + +<p>{{PreviousMenuNext("Web/Progressive_web_apps/Introduction", "Web/Progressive_web_apps/Offline_Service_workers", "Web/Progressive_web_apps")}}</p> + +<p>{{QuickLinksWithSubpages("/en-US/docs/Web/Progressive_web_apps/")}}</p> diff --git a/files/ja/web/progressive_web_apps/index.html b/files/ja/web/progressive_web_apps/index.html new file mode 100644 index 0000000000..9c729f609f --- /dev/null +++ b/files/ja/web/progressive_web_apps/index.html @@ -0,0 +1,107 @@ +--- +title: プログレッシブウェブアプリ +slug: Web/Progressive_web_apps +tags: + - Apps + - Modern web apps + - PWA + - Progressive web apps + - アプリ + - プログレッシブウェブアプリ +translation_of: Web/Progressive_web_apps +--- +<div>{{draft}}</div> + +<p class="summary"><img alt="PWA community logo" src="https://mdn.mozillademos.org/files/16742/pwa.png" style="display: block; float: left; height: 188px; margin: 0px auto; padding-bottom: 1em; padding-right: 2em; width: 350px;"><strong><ruby>プログレッシブウェブアプリ<rp> (</rp><rt>Progressive web apps</rt><rp>) </rp></ruby></strong> (PWA) は、新しいウェブ API と伝統的なプログレッシブな拡張戦略を使用して、クロスプラットフォームのウェブアプリケーションにネイティブアプリと同様の使い勝手をもたらすウェブアプリのことです。プログレッシブウェブアプリは正式な標準ではありませんが、有用なデザインパターンです。 PWA は、特定のウェブ技術や技法の使用を含む、一連のアプリケーション属性を包含しているという点で AJAX や他の同様のパターンに似ていると考えることができます。この一連の文書では、これについて知るために必要なすべてをお伝えします。</p> + +<p>ウェブアプリを PWA と呼ぶには、技術的に言えば、 <a href="/ja/docs/Web/Security/Secure_Contexts">安全なコンテキスト</a> (<strong>{{Glossary("HTTPS")}}</strong>)、1つ以上の<a href="/ja/docs/Web/API/Service_Worker_API">サービスワーカー</a>、<a href="/ja/docs/Web/Manifest">マニフェストファイル</a>を持つべきです。</p> + +<dl> + <dt><a href="/ja/docs/Web/Security/Secure_Contexts">安全なコンテキスト</a> ({{Glossary("HTTPS")}})</dt> + <dd>このウェブアプリケーションは、安全なネットワーク上で提供しなければなりません。安全なサイトにすることは、良い習慣であるだけでなく、特にユーザーが安全な取引を行う必要がある場合には、ウェブアプリケーションを信頼できるサイトとして確立することにもつながります。位置情報やサービスワーカーなどの PWA に関連する機能のほとんどは、アプリが HTTPS を使用して読み込まれた場合にのみ利用できます。</dd> + <dt><a href="/ja/docs/Web/API/Service_Worker_API">サービスワーカー</a></dt> + <dd>サービスワーカーとは、ウェブブラウザーがネットワークのリクエストや資産のキャッシュに介入し、その方法を制御することができるスクリプトのことです。サービスワーカーを使用することで、ウェブ開発者は信頼できる高速なウェブページやオフライン操作を作成することができます。</dd> + <dt><a href="/ja/docs/Web/Manifest">マニフェストファイル</a></dt> + <dd>アプリがユーザーにどのように表示されるかを制御し、プログレッシブウェブアプリを確実に発見できるようにする {{Glossary("JSON")}} ファイルです。アプリの名前、開始 URL、アイコン、その他ウェブサイトをアプリのような形式に変換するために必要なすべての詳細が記述されています。</dd> +</dl> + +<h2 id="PWA_advantages" name="PWA_advantages">PWA の利点</h2> + +<p>PWA は発見でき、インストールでき、リンクでき、ネットワークに依存せず、プログレッシブで、再エンゲージでき、レスポンシブで、安全です。これらが何を意味するのかについては、<a href="/ja/docs/Web/Progressive_web_apps/Advantages">プログレッシブウェブアプリの利点</a>をお読みください。</p> + +<p>PWA の実装方法については、 <a href="/ja/docs/Web/Progressive_web_apps/Developer_guide">PWA 開発者ガイド</a>をお読みください。</p> + +<h2 id="Documentation" name="Documentation">ドキュメント</h2> + +<p><strong><-- 以下のものは一時的な自動生成リストで、すぐに置き換えられます --></strong></p> + +<p>{{LandingPageListSubpages}}</p> + +<div class="blockIndicator warning"> +<p><strong>ここから下は全て旧バージョンのままで、他のコンテンツの全面見直しに合わせて刷新していきます。</strong></p> +</div> + +<h2 id="Core_PWA_guides" name="Core_PWA_guides">基本的な PWA のガイド</h2> + +<p>以下のガイドは PWA を実装するのに必要なことを、単純な例を実行し、すべての部分がどのように動作するかを示します。</p> + +<ol> + <li><a href="/ja/docs/Web/Progressive_web_apps/Introduction">プログレッシブウェブアプリの紹介</a></li> + <li><a href="/ja/docs/Web/Progressive_web_apps/App_structure">プログレッシブウェブアプリの構造</a></li> + <li><a href="/ja/docs/Web/Progressive_web_apps/Offline_Service_workers">サービスワーカーで PWA をオフラインで動作するようにする</a></li> + <li><a href="/ja/docs/Web/Progressive_web_apps/Installable_PWAs">PWA をインストール可能にする方法</a></li> + <li><a href="/ja/docs/Web/Progressive_web_apps/Re-engageable_Notifications_Push">通知とプッシュ通知を使用して PWA を再エンゲージ可能にする方法</a></li> + <li><a href="/ja/docs/Web/Progressive_web_apps/Loading">プログレッシブ読み込み</a></li> +</ol> + +<div class="column-container"> +<div class="column-half"> +<h2 id="Technology_guides" name="Technology_guides">技術ガイド</h2> + +<ul> + <li><a href="/ja/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">クライアント側ストレージ</a> — ウェブストレージ, IndexedDB, サービスワーカーをいつ、どのように使うかを示すとても長いガイド。</li> + <li><a href="/ja/docs/Web/API/ServiceWorker_API/Using_Service_Workers">サービスワーカーの使用</a> — より詳しい Service Worker API のガイド。</li> + <li><a href="/ja/docs/Web/API/IndexedDB_API/Using_IndexedDB">IndexedDB の使用</a> — IndexedDB の基礎、詳しく説明されている。</li> + <li><a href="/ja/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API">Web Storage API の使用</a> — ウェブストレージ API はシンプルにできている。</li> + <li><a class="external external-icon" href="https://developers.google.com/web/updates/2015/11/app-shell" rel="noopener">アプリケーションシェルアーキテクチャによるすばやいウェブアプリの読み込み</a> — App Shell コーディングパターンを使用して、すばやく読み込まれるアプリの作成のガイド。</li> + <li><a href="/ja/docs/Web/API/Push_API/Using_the_Push_API">Push API の使用</a> — Web Push API の背景にある要点を学ぶ。</li> + <li><a href="/ja/docs/Web/API/Using_Web_Notifications">Notifications API の使用</a> — ウェブ通知の簡単な説明。</li> + <li><a href="/ja/docs/Web/Apps/Modern/Responsive/responsive_design_building_blocks">レスポンシブデザインのブロック構成</a> — モダンアプリレイアウトにとって重要なレスポンシブウェブデザインの基本を学ぶ。</li> + <li><a href="/ja/docs/Web/Apps/Modern/Responsive/Mobile_first">モバイルファースト</a> — レスポンシブなアプリケーションを作る時によく、モバイルレイアウトを既定として作って、その上により広いレイアウトを作る意味がある。</li> + <li><a href="/ja/docs/Web/Progressive_web_apps/Add_to_home_screen">ホーム画面追加のためのガイド</a> — アプリをホーム画面に追加 (A2HS) する利点を学ぶ。</li> +</ul> +</div> + +<div class="column-half"> +<h2 id="Tools" name="Tools">ツール</h2> + +<ul> + <li><a class="external external-icon" href="https://localforage.github.io/localForage/" rel="noopener">localForage</a> — クライアントサイドのデータストレージを簡単に扱えるようにする素晴らしいシンプルな JavaScript ライブラリ、これは既定で IndexedDB を使用し、必要に応じて Web SQL/Web Storage にフォールバックする。</li> + <li><a class="external external-icon" href="https://github.com/fxos-components/serviceworkerware" rel="noopener">ServiceWorkerWare</a> — Service Worker の開発を簡単にする Express のようなマイクロフレームワーク。</li> + <li><a class="external external-icon" href="https://github.com/mozilla/oghliner" rel="noopener">oghliner</a> — テンプレートだけではなく、オフラインでウェブアプリケーションを Github Pages にデプロイするツール。</li> + <li><a class="external external-icon" href="https://github.com/GoogleChrome/sw-precache" rel="noopener">sw-precache</a> — 特定のリソースを事前にキャッシュする Service Worker のコードを生成する node のモジュール。</li> + <li><a class="external external-icon" href="https://github.com/GoogleChrome/workbox" rel="noopener">workbox</a> — 気持ち的には、より進んだキャッシングの手法と簡単なプリキャッシュを有するsw-precacheの後継者。</li> + <li><a class="external external-icon" href="https://www.talater.com/upup/" rel="noopener">upup</a> — あなたのサイトが常にあなたのユーザーのために存在するようにする小さなスクリプト。</li> + <li><a class="external external-icon" href="https://serviceworke.rs/" rel="noopener">The service worker cookbook</a> — 一連の素晴らしい Service Worker/プッシュレシピ、オフラインアプリケーションの実装方法を紹介しているが、より多くの機能を持っている。</li> + <li><a href="https://marketplace.visualstudio.com/items?itemName=mayeedwin.vscode-pwa">PWA VS Code extension</a> - VisualStudio コード環境でプログレッシブウェブアプリを構築するために必要な、すべての重要なコードスニペットのコレクションです。</li> +</ul> +</div> +</div> + +<ul> + <li><a href="https://developers.google.com/web/progressive-web-apps">Progressive web apps</a> on Google Developers</li> + <li>Alex Russell による <a href="https://medium.com/@slightlylate/progressive-apps-escaping-tabs-without-losing-our-soul-3b93a8561955#.6czgj0myh">Progressive Web Apps: Escaping Tabs Without Losing Our Soul</a></li> + <li><a href="https://developers.google.com/web/progressive-web-apps/checklist">Progressive Web Apps Check List</a></li> + <li>Google による <a href="https://developers.google.com/web/tools/lighthouse">The Lighthouse Tool</a></li> + <li><a href="https://github.com/angular/mobile-toolkit">Tools for building progressive web apps with Angular</a></li> + <li><a href="https://github.com/codebusking/react-pwa-guide-kit">React PWA Guide Kit</a></li> + <li><a href="https://pokedex.org/">Offline-capable Pokédex web site</a></li> + <li><a href="https://hnpwa.com/">Hacker News readers as Progressive Web Apps</a></li> + <li><a href="https://goingmeta.io/progressive-web-app/">Progressive Web App: Advantages in a nutshell</a></li> + <li><a href="https://ymedialabs.com/progressive-web-apps">Why Progressive Web Apps Are The Future of Mobile Web (2019 Research)</a></li> + <li><a href="https://www.csschopper.com/blog/progressive-web-apps-everything-you-need-to-know/">Progressive Web Apps: Everything You Need To Know</a></li> + <li><a href="https://pwafire.org">Collection of resources, codelabs and tools you need to build PWAs by the team at pwafire.org</a></li> + <li><a href="https://github.com/pwafire/pwadev-tips">Setting up your Progressive Web App Development environment</a></li> +</ul> + +<div>{{QuickLinksWithSubpages("/ja/docs/Web/Progressive_web_apps/")}}</div> diff --git a/files/ja/web/progressive_web_apps/installable_pwas/index.html b/files/ja/web/progressive_web_apps/installable_pwas/index.html new file mode 100644 index 0000000000..da142f4b5a --- /dev/null +++ b/files/ja/web/progressive_web_apps/installable_pwas/index.html @@ -0,0 +1,129 @@ +--- +title: PWA をインストール可能にするには +slug: Web/Progressive_web_apps/Installable_PWAs +tags: + - PWA + - a2hs + - js13kGames + - インストール可能 + - ホーム画面に追加 + - 進歩的ウェブアプリ +translation_of: Web/Progressive_web_apps/Installable_PWAs +--- +<div>{{PreviousMenuNext("Web/Progressive_web_apps/Offline_Service_workers", "Web/Progressive_web_apps/Re-engageable_Notifications_Push", "Web/Progressive_web_apps")}}</div> + +<p class="summary">前回の記事では、サンプルアプリケーション <a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a> が<a href="/ja/docs/Web/API/Service_Worker_API">サービスワーカー</a>によってオフラインで動作する方法を見てきましたが、さらに、対応しているモバイルブラウザーやデスクトップブラウザーでは、ウェブアプリをユーザーがインストールできるようにすることができます。インストールされたウェブアプリは、ネイティブアプリと同様にユーザーが起動することができます。 この記事では、ウェブアプリマニフェストと「ホーム画面に追加」と呼ばれる機能を使用して、これを実現する方法を説明します。</p> + +<p>これらの技術により、ユーザーはブラウザーを開いてからブックマークを使ってサイトに移動したり、 URL を入力したりするのではなく、アプリを端末のホーム画面から直接起動することができます。ウェブアプリは、第一級市民としてネイティブアプリケーションの隣に座ることができます。さらに、アプリを全画面またはスタンドアロン モードで起動するように指定できるため、既定ののブラウザーのユーザーインターフェイスが削除され、よりシームレスでネイティブアプリに近い感覚が得られます。</p> + +<h2 id="Requirements" name="Requirements">要求事項</h2> + +<p>ウェブサイトをインストール可能にするには、以下のものが必要になります。</p> + +<ul> + <li><a href="/ja/docs/Web/Progressive_web_apps/Add_to_home_screen#Manifest">正しくフィールドが入力された</a>ウェブマニフェスト</li> + <li>安全な (HTTPS) ドメインから提供されるウェブサイト</li> + <li>端末上のアプリを表すアイコン</li> + <li>アプリをオフラインで動作させるために登録された<a href="/ja/docs/Web/API/Service_Worker_API">service worker</a> (現時点では Android の Chrome にのみ必要です)</li> +</ul> + +<div class="blockIndicator note"> +<p>現在、サービスワーカーが必要なのは、 Chrome, Edge, Samsung Internet などの Chromium ベースのブラウザーのみです。Firefox を使ってアプリを開発する場合は、 Chromium ベースのブラウザーと互換性を持たせるためにサービスワーカーが必要になるので注意が必要です。</p> +</div> + +<h3 id="The_manifest_file" name="The_manifest_file">マニフェストファイル</h3> + +<p>重要な要素はウェブマニフェストファイルです。 このファイルには、ウェブサイトに関するすべての情報が JSON 形式でリストされます。</p> + +<p>通常、ウェブアプリのルートフォルダーに存在します。これには、アプリのタイトル、 OS 上でアプリを表現するために使用できる様々なサイズのアイコンへのパス (ホーム画面上のアイコン、スタートメニューの項目、デスクトップ上のアイコンなど)、読み込み中画面やスプラッシュ画面で使用する背景色などの有用な情報が含まれています。この情報は、ブラウザーがインストール処理中にウェブアプリを適切に表示したり、モバイル端末のホーム画面などの端末のアプリ起動インターフェイス内で表示したりするために必要です。</p> + +<p><a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a> ウェブアプリの <code>js13kpwa.webmanifest</code> ファイルは、 <code>index.html</code> ファイルの {{HTMLElement("head")}} ブロックに次のコード行を使用して含まれています。</p> + +<pre class="brush: html notranslate"><link rel="manifest" href="js13kpwa.webmanifest"></pre> + +<div class="note"> +<p>過去にマニフェストに使用されてきた一般的な拡張機能がいくつかあります。 <code>manifest.webapp</code> は Firefox OS アプリのマニフェストで一般的でしたが、多くの場合、コンテンツは JSON 構造で編成されているためウェブマニフェストには <code>manifest.json</code> を使用します。 しかし、<code>.webmanifest</code> ファイル形式は <a href="https://w3c.github.io/manifest/">W3C マニフェスト仕様書</a> (英語) で明示的に言及されており、ここでは使用するのはこれです。</p> +</div> + +<p>ファイルの内容は次のようになります。</p> + +<pre class="brush: json notranslate">{ + "name": "js13kGames Progressive Web App", + "short_name": "js13kPWA", + "description": "Progressive Web App that lists games submitted to the A-Frame category in the js13kGames 2017 competition.", + "icons": [ + { + "src": "icons/icon-32.png", + "sizes": "32x32", + "type": "image/png" + }, + // ... + { + "src": "icons/icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "start_url": "/pwa-examples/js13kpwa/index.html", + "display": "fullscreen", + "theme_color": "#B12A34", + "background_color": "#B12A34" +} +</pre> + +<p>ほとんどのフィールドは一目瞭然ですが、念のため、以下のものと同じです。</p> + +<ul> + <li><code>name</code>: ウェブアプリの正式な名前。</li> + <li><code>short_name</code>: ホーム画面に表示する省略した名前。</li> + <li><code>description</code>: アプリが何をするのかを説明する一つ二つの文章。</li> + <li><code>icons</code>: 一連のアイコン情報 — ソース URL、サイズ、種類。 ユーザーの端末に最適なものが選択されるように、少なくともいくつか含めるようにしてください。</li> + <li><code>start_url</code>: アプリの起動時に起動する index 文書。</li> + <li><code>display</code>: アプリの表示方法 — <code>fullscreen</code> (全画面), <code>standalone</code> (スタンドアロン), <code>minimal-ui</code> , <code>browser</code> (ブラウザー) のいずれかです。</li> + <li><code>theme_color</code>: テーマカラー — オペレーティングシステムで使用される UI の基本色です 。</li> + <li><code>background_color</code>: アプリの既定の背景色、インストール中およびスプラッシュ画面で使用します。</li> +</ul> + +<p>最小限のウェブマニフェストには、少なくとも <code>name</code> と、1つ以上のアイコンが定義された <code>icons</code> フィールドがなければなりません。アイコンには、少なくとも <code>src</code>, <code>size</code>, and <code>type</code> がなければなりません。それ以外はすべてオプションですが、<code>description</code>, <code>short_name</code>, <code>start_url</code> フィールドは推奨されます。上記のフィールド以外にも使用できるフィールドがあります。 - 詳細については、必ず<a href="/ja/docs/Web/Manifest">ウェブアプリマニフェストリファレンス</a>を確認してください。</p> + +<h2 id="Add_to_home_screen" name="Add_to_home_screen">ホーム画面に追加</h2> + +<p>「ホーム画面に追加」(Add to home screen、略して a2hs)は、モバイルブラウザーによって実装され、アプリのウェブマニフェストにある情報を取得して、それらを使用して端末のホーム画面上のアプリをアイコンと名前で表す機能です。 これは、上記のように、アプリが必要な要件をすべて満たしている場合にのみ機能します。</p> + +<p>ユーザーがサポートしているモバイルブラウザーで PWA にアクセスすると、アプリを PWA としてインストールすることが可能であることを示す通知 (バナーやダイアログボックスなど) が表示されます。</p> + +<p><img alt="js13kPWA のホーム画面に追加のポップアップ。" src="https://mdn.mozillademos.org/files/15928/js13kpwa-icon.png" style="border-style: solid; border-width: 1px; display: block; height: 640px; margin: 0px auto; width: 360px;"></p> + +<p>ユーザーがインストールを実行する意志を示したら、インストールバナーが表示されます。 そのバナーは、マニフェストファイルからの情報に基づいて、ブラウザーによって自動的に作成されます。例えば、プロンプトにはアプリの名前とアイコンが含まれています。</p> + +<p><img alt="js13kPWA のインストールバナー。" src="https://mdn.mozillademos.org/files/15927/js13kpwa-banner.png" style="border-style: solid; border-width: 1px; display: block; height: 640px; margin: 0px auto; width: 360px;"></p> + +<p>ユーザーがボタンをクリックすると、アプリがどのように表示されるかを示し、間違いなくアプリを追加するかどうかをユーザーに選択させる最後のステップがあります。</p> + +<p><img alt="js13kPWA のホーム画面に追加のポップアップ。" src="https://mdn.mozillademos.org/files/15926/js13kpwa-add.png" style="border-style: solid; border-width: 1px; display: block; height: 640px; margin: 0px auto; width: 360px;"></p> + +<p>確認すると、アプリがホーム画面にインストールされます。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15834/js13kpwa-installed.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>これでユーザーは、端末上の他のアプリケーションと同じようにウェブアプリを起動して使用することができるようになりました。端末やオペレーティングシステムによっては、ウェブアプリのアイコンにウェブアプリであることを示す小さなアイコンが付けられている場合があります。例えば、上のスクリーンショットでは、アプリには小さな Firefox のアイコンが付いており、 Firefox ランタイムを使用するウェブアプリであることを示しています。</p> + +<h3 id="Splash_screen" name="Splash_screen">スプラッシュ画面</h3> + +<p>一部のブラウザーでは、マニフェストの情報からスプラッシュ画面も生成されます。 これは、 PWA が起動され読み込まれている間に表示されます。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15835/js13kpwa-splash.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>この画面の作成には、アイコンとテーマカラーと背景色が使用されます。</p> + +<h2 id="Summary" name="Summary">まとめ</h2> + +<p>この記事では、適切に設定されたウェブマニフェストで PWA をインストール可能にする方法と、その後でブラウザーの「ホーム画面に追加」機能を使って PWA をインストールする方法について学びました。</p> + +<p>a2hs の詳細については、必ず<a href="/ja/docs/Web/Progressive_web_apps/Add_to_home_screen">ホーム画面に追加のガイド</a>をお読みください。 ブラウザーのサポートは現在、Android の Firefox 58 以降、Mobile Chrome および Android Webview 31 以降、および Android の Opera 32 以降に制限されていますが、近い将来に改善されるはずです。</p> + +<p>それでは、PWA パズルの最後のピース、プッシュ通知を使用してユーザーとアナウンスを共有し、ユーザーがアプリに再び参加できるようにする方法に移りましょう。</p> + +<p>{{PreviousMenuNext("Web/Progressive_web_apps/Offline_Service_workers", "Web/Progressive_web_apps/Re-engageable_Notifications_Push", "Web/Progressive_web_apps")}}</p> + +<p>{{QuickLinksWithSubpages("/ja/docs/Web/Progressive_web_apps/")}}</p> diff --git a/files/ja/web/progressive_web_apps/introduction/index.html b/files/ja/web/progressive_web_apps/introduction/index.html new file mode 100644 index 0000000000..3153a7d426 --- /dev/null +++ b/files/ja/web/progressive_web_apps/introduction/index.html @@ -0,0 +1,99 @@ +--- +title: プログレッシブウェブアプリの紹介 +slug: Web/Progressive_web_apps/Introduction +tags: + - Introduction + - PWA + - Progressive web apps + - js13kGames + - progressive + - ウェブマニフェスト + - サービスワーカー + - プログレッシブウェブアプリ +translation_of: Web/Progressive_web_apps/Introduction +--- +<div>{{NextMenu("Web/Progressive_web_apps/App_structure", "Web/Progressive_web_apps")}}</div> + +<p class="summary">この記事では<ruby>プログレッシブウェブアプリ<rp> (</rp><rt>Progressive Web Apps</rt><rp>)</rp></ruby> (PWA) を紹介し、それが何なのか、また普通のウェブアプリよりもどのような利点があるのかを説明します。</p> + +<h2 id="What_is_a_Progressive_Web_App" name="What_is_a_Progressive_Web_App">プログレッシブウェブアプリとは</h2> + +<p>PWA は数々の特定の技術と、ウェブアプリとネイティブアプリの機能の利点を併せ持った標準パターンを使用して開発されたウェブアプリです。</p> + +<p>例えば、ウェブアプリはより見つけやすいものです。— アクセスするのは、アプリケーションをインストールするよりはるかに簡単で手早く、リンクを通してウェブアプリを共有することもできます。</p> + +<p>一方、ネイティブアプリはオペレーティングシステムとより調和するので、ユーザーにもっと継ぎ目のない使い勝手を提供します。ネイティブアプリをインストールするとオフラインで動作し、ユーザーはブラウザーを使ってアプリに移動するのではなく、ホーム画面のアイコンから好きなアプリをタップするだけで簡単にアクセスできます。</p> + +<p>PWA によって、ネイティブアプリの利点を引き継いでウェブアプリケーションを作成できます。</p> + +<p>PWA は新しい概念ではありません。このような考えは、今までも様々なアプローチで検討されてきました。既に、プログレッシブエンハンスメントやレスポンシブデザインを用いてモバイルに適したウェブサイトを作成することができます。オフラインでの動作やアプリケーションとしてのインストールも、数年前に Firefox OS で実現されていました。</p> + +<p>しかし、PWA はウェブを素晴らしいものにする既存の機能を一切排除することなく、これらすべてとそれ以上の機能を提供します。</p> + +<h2 id="What_makes_an_app_a_PWA" name="What_makes_an_app_a_PWA">何がアプリを PWA にするのか</h2> + +<p>前に述べたように、PWA は単一の技術によって成り立っているわけではありません。PWA とはウェブアプリケーションを構築するための新しい哲学を表しており、いくつかの特定のパターンや API、機能を含みます。一見しただけではそのウェブアプリが PWA かを見極めることはできません。ウェブアプリは、特定の要件を満たしているか、あるいは特定の機能を実装している場合に、PWA と見なされます。例えば、オフラインで動作すること、インストールできること、簡単に同期できること、プッシュ通知を送信することができることなどです。</p> + +<p>更に、アプリの完成度をパーセント値で測定するツールもあります (今の所は <a href="https://developers.google.com/web/tools/lighthouse/">Lighthouse</a> が最も有名です)。様々な技術的優位性を実装することでアプリをより進化的(progressive)にすることができ、より高い Lighthouse のスコアを得ることができます。しかし、このスコアは大まかな指標でしかありません。</p> + +<p>ウェブアプリが PWA として見なされるために、いくつかの重要な原則があります。</p> + +<ul> + <li><a href="/ja/Progressive_web_apps/Advantages#Discoverable">Discoverable</a>: コンテンツを検索エンジンで見つけることができる。</li> + <li><a href="/ja/Progressive_web_apps/Advantages#Installable">Installable</a>: アプリは端末のホーム画面に追加できる。</li> + <li><a href="/ja/Progressive_web_apps/Advantages#Linkable">Linkable</a>: URL を送るだけでアプリを共有できる。</li> + <li><a href="/ja/Progressive_web_apps/Advantages#Network_independent">Network independent</a>: オフラインか、あるいは貧弱なネットワーク環境でも使用できる。</li> + <li><a href="/ja/Progressive_web_apps/Advantages#Progressive">Progressive</a>: 古いブラウザーでも基本的な機能は使用でき、最新のブラウザーではすべての機能が使用できる。</li> + <li><a href="/ja/Progressive_web_apps/Advantages#Re-engageable">Re-engageable</a>: 新しいコンテンツがあるときには、通知を送ることができる。</li> + <li><a href="/ja/Progressive_web_apps/Advantages#Responsive">Responsive</a>: 携帯電話やタブレット、ノートパソコン、テレビ、冷蔵庫など、画面とブラウザーを備える全ての端末で使用できる。</li> + <li><a href="/ja/Progressive_web_apps/Advantages#Safe">Safe</a>: アプリからの通信が第三者からの攻撃に対して安全であり、機密情報を保護できる。</li> +</ul> + +<h3 id="Is_it_worth_doing_all_that" name="Is_it_worth_doing_all_that">取り組む価値はありますか?</h3> + +<p>もちろん!基本的な PWA の機能を実装するのに必要な労力は比較的小さく、得られる便益は膨大です。例をあげましょう。</p> + +<ul> + <li>アプリのインストール後、<font color="#0b0115"><a href="/ja/docs/Web/API/Service_Worker_API">Service Worker</a></font> のキャッシュのおかげで読み込み時間が減少する。大切な帯域の利用量も同様。</li> + <li>アプリ更新の際、変更があった内容だけを更新する機能。対照的にネイティブアプリの場合、ほんの小さな変更だとしてもユーザーにアプリケーション全体を再びダウンロードさせてしまう。</li> + <li>ネイティブプラットフォームとよく統合されたルックアンドフィール。例えばホームスクリーンのアプリアイコンや、フルスクリーン動作するアプリなど。</li> + <li>システム通知やプッシュメッセージによるユーザーの再訪問。これはエンゲージユーザーやコンバージョン率の向上に繋がる。</li> +</ul> + +<p>PWA の道を試みて、ネイティブアプリよりもウェブサイトの使い勝手の向上を選択し、その結果として大きな利益を得るに至った企業の成功例は多数あります。<a href="https://www.pwastats.com/">PWA Stats</a> というウェブサイトはこのような便益を示すたくさんの調査を公開しています。</p> + +<p>もっとも有名な成功例は、おそらく <a href="https://stories.flipkart.com/introducing-flipkart-lite/">Flipkart Lite</a> でしょう。インド最大手の e コマースサイトは 2015年に PWA へと作り直され、その結果コンバージョン数が 70%増加しました。<a href="https://m.aliexpress.com/">AliExpress</a> の PWA もまた新規ユーザーのコンバージョン率が 104%向上という、ウェブやネイティブアプリよりも良い結果となりました。このような利益の増加や PWA 転換に必要な労力が比較的少ないことを考えると、PWA の利点は明確です。</p> + +<p>一方では <a href="https://www.couponmoto.com/">couponmoto</a> のような初期段階にあるスタートアップも消費者エンゲージメント促進のため PWA を使い始め、企業の大小問わずユーザーの (再) エンゲージに効果的であることが示されています。</p> + +<p>他にも例を知りたければ <a href="https://pwa.rocks/">pwa.rocks</a> を確認してみてください。特に <a href="https://hnpwa.com/">hnpwa.com</a> のページは注目に値します。これは (よくある TodoMVC アプリの代わりに) Hacker News ウェブサイトの実装例を掲載しており、様々なフロントエンドフレームワークの利用例を見ることができます。</p> + +<p><a href="https://www.pwabuilder.com/">PWABuilder</a> を利用すると、PWA をオンラインで生成することもできます。</p> + +<p>Service Worker - およびプッシュ通知 - に固有の情報を探しているならば、<a href="https://serviceworke.rs/">Service Worker Cookbook</a> も忘れずにチェックしてください。モダンなサイトにおける Service Worker のレシピ集です。</p> + +<p>PWA のアプローチは挑戦する十分な価値があります。あなたのアプリでそれがどう動くのか、ぜひ自身で確認してみてください。</p> + +<h2 id="Browser_support" name="Browser_support">ブラウザーの対応</h2> + +<p>前述のように、PWA は単一の API に依存するのではなく、さまざまなテクノロジーを使用して、可能な限り最高の Web エクスペリエンスを提供するという目標を達成します。<br> + <br> + PWA に必要な重要な要素は、<a href="https://wiki.developer.mozilla.org/ja/docs/Web/API/Service_Worker_API">service worker</a> のサポートです。ありがたいことに、Service Worker は現在、デスクトップとモバイルの<a href="https://jakearchibald.github.io/isserviceworkerready/">すべての主要なブラウザー</a>でサポートされています。<br> + <br> + <a href="https://wiki.developer.mozilla.org/ja/docs/Web/Manifest">Web App Manifest</a> や <a href="https://wiki.developer.mozilla.org/ja/docs/Web/API/Push_API">Push</a>, <a href="https://wiki.developer.mozilla.org/ja/docs/Web/API/Notifications_API">Notifications</a>, <a href="https://wiki.developer.mozilla.org/ja/docs/Web/Progressive_web_apps/Add_to_home_screen">Add to Home Screen</a> などの他の機能も幅広くサポートされています。現在、Safari では、ウェブアプリマニフェストとホーム画面に追加のサポートが制限されており、ウェブプッシュ通知はサポートされていません。ただし、他の主要なブラウザーはこれらすべての機能をサポートしています。<br> + <br> + これらの API の一部は実験的であり、ドキュメントはまだドラフトですが、Flipkart や AliExpress のような成功事例を見ると、ウェブアプリで既に PWA機能の一部を試して実装するよう確信するはずです。<br> + <br> + 何よりも、progressive enhancement rule に従う必要があります。サポートされている場合にのみ、そのような拡張機能を提供するテクノロジーを使用しますが、サポートされていない場合でもアプリの基本機能を提供します。この方法で誰もが使用できるようになりますが、最新のブラウザーを使用するユーザーは PWA機能をさらに活用できます。</p> + +<h2 id="An_example_application" name="An_example_application">アプリケーションの例</h2> + +<p>このシリーズの記事では、 <a href="http://2017.js13kgames.com/">js13kGames 2017</a> コンペティションの <a href="http://js13kgames.com/aframe">A-Frame category</a> に提出されたゲームに関する情報をリストする、非常にシンプルなウェブサイトのソースコードを調べます。ウェブサイトの実際のコンテンツについて考える必要はありません。主なポイントは、自分のプロジェクトで PWA機能を使用する方法を学ぶことです。<br> + <br> + オンラインバージョンは <a href="https://mdn.github.io/pwa-examples/js13kpwa/">mdn.github.io/pwa-examples/js13kpwa</a> (<a href="https://github.com/mdn/pwa-examples/tree/master/js13kpwa">ソースコードも参照</a> )で見つけることができます。これについては、次のいくつかの記事で詳しく説明します。<br> + <br> + それでは、このシリーズの第2部に移り、サンプルアプリの構造を見ていきましょう。</p> + +<p>{{NextMenu("Web/Progressive_web_apps/App_structure", "Web/Progressive_web_apps")}}</p> + +<div>{{QuickLinksWithSubpages("/ja/docs/Web/Progressive_web_apps/")}}</div> diff --git a/files/ja/web/progressive_web_apps/loading/index.html b/files/ja/web/progressive_web_apps/loading/index.html new file mode 100644 index 0000000000..0e7733d524 --- /dev/null +++ b/files/ja/web/progressive_web_apps/loading/index.html @@ -0,0 +1,155 @@ +--- +title: プログレッシブ読み込み +slug: Web/Progressive_web_apps/Loading +tags: + - Loading + - PWA + - Progressive web apps + - js13kGames + - progressive +translation_of: Web/Progressive_web_apps/Loading +--- +<div>{{PreviousMenu("Web/Progressive_web_apps/Re-engageable_Notifications_Push", "Web/Progressive_web_apps")}}</div> + +<p class="summary">前回の記事では、<a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA</a> の例をプログレッシブウェブアプリケーションにするのに役立つ API について説明しました — <a href="/ja/docs/Web/Progressive_web_apps/Offline_Service_workers">サービスワーカー</a>、<a href="/ja/docs/Web/Progressive_web_apps/Installable_PWAs">ウェブマニフェスト</a>、<a href="/ja/docs/Web/Progressive_web_apps/Re-engageable_Notifications_Push">通知、およびプッシュ</a>です。 この記事では、リソースを徐々に読み込せて、アプリのパフォーマンスをさらに向上させます。</p> + +<h2 id="First_meaningful_paint" name="First_meaningful_paint">First meaningful paint — 最初の意味のあるペイント</h2> + +<p>できるだけ早く意味のあるものをユーザーに提供することが重要です — ページが読み込まれるのを待つ時間が長いほど、すべてが完了するのを待つ前にユーザーが離れる可能性が大きくなります。 少なくとも見たいページの基本的なビューだけでなく、最終的により多くのコンテンツが読み込まれる場所にプレースホルダーを表示することもできるはずです。</p> + +<p>これはプログレッシブ読み込み (progressive loading) によっても達成できます — <a href="https://ja.wikipedia.org/wiki/%E9%81%85%E5%BB%B6%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF">遅延読み込み</a> (Lazy loading) としても知られています。 これは、できるだけ多くのリソース (HTML、CSS、JavaScript) の読み込みを遅らせること、そして最初のエクスペリエンスに本当に必要なものだけをすぐに読み込むことです。</p> + +<h2 id="Bundling_versus_splitting" name="Bundling_versus_splitting">バンドリングと分割</h2> + +<p>多くの訪問者はウェブサイトのすべての単一ページを通過するわけではありません、それでも通常のアプローチは持っているすべての機能を一つの大きなファイルに束ねることです。 <code>bundle.js</code> ファイルは数メガバイトになる可能性があり、単一の <code>style.css</code> の束には、基本的な CSS 構造定義から、(モバイル、タブレット、デスクトップ、印刷専用など)サイトのすべてのバージョンで可能なすべてのスタイルまですべてを含めることができます。</p> + +<p>すべての情報をたくさんの小さなファイルではなく1つのファイルとして読み込むほうが速いのですが、最初にユーザーがすべてを必要としていない場合は、重要なものだけを読み込み、必要に応じて他のリソースを管理できます。</p> + +<h2 id="Render-blocking_resources" name="Render-blocking_resources">レンダリングをブロックするリソース</h2> + +<p>バンドリングは問題です — ブラウザーはレンダリングされた結果を画面に表示する前に、HTML、CSS、および JavaScript を読み込む必要があるためです。 最初のウェブサイトへのアクセスから読み込みが完了するまでの数秒間に、ユーザーは空白のページを見ますが、これは悪いエクスペリエンスです。</p> + +<p>これを修正するために、例えば、JavaScript ファイルに次のように <code>defer</code> を追加することができます。</p> + +<pre class="brush: html"><script src="app.js" defer></script> +</pre> + +<p>それらは文書自体が解析された<em>後</em>にダウンロードされて実行されるので、それは HTML 構造のレンダリングをブロックしません。 CSS ファイルを分割して次のようにメディアタイプを追加することもできます。</p> + +<pre class="brush: html"><link rel="stylesheet" href="style.css"> +<link rel="stylesheet" href="print.css" media="print"> +</pre> + +<p>これは、条件が満たされた場合にのみそれらを読み込むようブラウザーに指示します。</p> + +<p>js13kPWA デモアプリでは、CSS はそれらをどのように読み込むかに関して特別な規則なしで単一のファイルにすべてを残すのに十分に単純です。 さらに進んで、<code>style.css</code> から <code>index.html</code> の <code><head></code> 内の <code><style></code> タグにすべてを移動することもできます — これによりパフォーマンスがさらに向上しますが、例を読みやすくするために、このアプローチもスキップします。</p> + +<h2 id="Images" name="Images">画像</h2> + +<p>JavaScript と CSS 以外にも、ウェブサイトには多くの画像が含まれているでしょう。 HTML に {{htmlelement("img")}} 要素を含めると、最初にウェブサイトにアクセスしたときに、参照されているすべての画像が取得されてダウンロードされます。 サイトの準備が整ったことをアナウンスする前にダウンロードするメガバイトの画像データを持っているのは珍しいことではありませんが、これもまたパフォーマンスに対する悪い認識を生み出します。 サイトを閲覧する最初の段階で、可能な限り最高の品質のすべての画像を必要とするわけではありません。</p> + +<p>これは最適化することができます。 まず第一に、<a href="https://tinypng.com/">TinyPNG</a> に似たツールやサービスを使うべきで、それはあまり品質を変えずに画像のファイルサイズを減らすでしょう。 その点を過ぎていれば、JavaScript を使って画像の読み込みを最適化することを考え始めることができます。 以下で説明します。</p> + +<h3 id="Placeholder_image" name="Placeholder_image">プレースホルダー画像</h3> + +<p><code><img></code> 要素の <code>src</code> 属性で参照されるゲームのすべてのスクリーンショットを自動的にダウンロードするようにする代わりに、JavaScript で選択的に実行できます。 js13kPWA アプリは代わりにプレースホルダー画像を使用し、これは小さくて軽量です。 一方、ターゲット画像への最終パスは次のように <code>data-src</code> 属性に格納されます。</p> + +<pre class="brush: html"><img src='data/img/placeholder.png' data-src='data/img/SLUG.jpg' alt='NAME'> +</pre> + +<p>これらの画像は、サイトが HTML 構造の構築を完了した<em>後</em>に JavaScript で読み込まれます。 プレースホルダー画像は元の画像と同じ方法で拡大縮小されるため、同じスペースを占有し、画像の読み込み時にレイアウトが再描画されることはありません。</p> + +<h3 id="Loading_via_JavaScript" name="Loading_via_JavaScript">JavaScript による読み込み</h3> + +<p><code>app.js</code> ファイルは <code>data-src</code> 属性を次のように処理します。</p> + +<pre class="brush: js">let imagesToLoad = document.querySelectorAll('img[data-src]'); +const loadImages = (image) => { + image.setAttribute('src', image.getAttribute('data-src')); + image.onload = () => { + image.removeAttribute('data-src'); + }; +};</pre> + +<p><code>imagesToLoad</code> 変数にはすべての画像への参照が含まれ、<code>loadImages</code> 関数はパスを <code>data-src</code> から <code>src</code> に移動します。 各画像が実際に読み込まれると、もう必要ではなくなったので、<code>data-src</code> 属性を削除します。 それから次のように各画像をループして読み込みます。</p> + +<pre class="brush: js">imagesToLoad.forEach((img) => { + loadImages(img); +});</pre> + +<h3 id="Blur_in_CSS" name="Blur_in_CSS">CSS でのぼかし</h3> + +<p>プロセス全体を視覚的により魅力的にするために、プレースホルダーは CSS で、ぼかしています。</p> + +<p><img alt="js13kPWA アプリのプレースホルダー画像のスクリーンショット" src="https://mdn.mozillademos.org/files/15992/js13kpwa-placeholders.png" style="height: 684px; width: 675px;"></p> + +<p>最初にぼかしを付けて画像をレンダリングするので、シャープな画像に遷移することができます。</p> + +<pre class="brush: css">article img[data-src] { + filter: blur(0.2em); +} + +article img { + filter: blur(0em); + transition: filter 0.5s; +}</pre> + +<p>これにより、0.5秒以内にぼかし効果が取り除かれます。 これは、「読み込み」効果としては十分に効果的です。</p> + +<h2 id="Loading_on_demand" name="Loading_on_demand">オンデマンドで読み込む</h2> + +<p>上のセクションで説明した画像読み込みメカニズムは問題なく動作します — HTML 構造をレンダリングした後に画像を読み込むし、その過程で素晴らしい遷移効果を適用します。 問題はユーザーがページを読み込んでも最初の2つか3つしか見えないにもかかわらず、まだ<em>すべて</em>の画像を一度に読み込むことです。</p> + +<p>この問題は新しい <a href="/ja/docs/Web/API/Intersection_Observer_API">Intersection Observer API</a> で解決できます — これを使用すると、ビューポートに表示されたときにのみ画像が読み込まれるようになります。</p> + +<h3 id="Intersection_Observer" name="Intersection_Observer">Intersection Observer</h3> + +<p>これは、以前に動作していた例に対するプログレッシブエンハンスメントです — <a href="/ja/docs/Web/API/Intersection_Observer_API">Intersection Observer</a>(交差監視)は、ユーザーが下にスクロールしたときにのみターゲット画像を読み込んで、ビューポートに表示させるようにします。</p> + +<p>関連するコードは次のようになります。</p> + +<pre class="brush: js">if('IntersectionObserver' in window) { + const observer = new IntersectionObserver((items, observer) => { + items.forEach((item) => { + if(item.isIntersecting) { + loadImages(item.target); + observer.unobserve(item.target); + } + }); + }); + imagesToLoad.forEach((img) => { + observer.observe(img); + }); +} else { + imagesToLoad.forEach((img) => { + loadImages(img); + }); +}</pre> + +<p>{{domxref("IntersectionObserver")}} オブジェクトがサポートされている場合、アプリはその新しいインスタンスを作成します。 パラメータとして渡される関数は、1つ以上の <code>items</code> が <code>observer</code> と交差している(つまり、ビューポート内に表示されている)場合を処理します。 それぞれの場合を繰り返してそれに応じて反応することができます — 画像が見えるときは、正しい画像を読み込み、監視する必要がなくなるので監視を中止します。</p> + +<p>プログレッシブエンハンスメントについての前述の説明をもう一度繰り返しましょう。 このコードは、Intersection Observer がサポートされているかどうかにかかわらずアプリが機能するように作成されています。 されていない場合は、先ほど説明したより基本的な方法を使用して画像を読み込みます。</p> + +<h2 id="Improvements" name="Improvements">改良点</h2> + +<p>読み込み時間を最適化するには多くの方法があり、この例ではそのうちの1つのアプローチのみを検討していることを忘れないでください。 JavaScript を使わずに動作させることでアプリをより安全なものにすることができます — {{htmlelement("noscript")}} を使用して既に割り当てられた最後の <code>src</code> で画像を表示するか、{{htmlelement("a")}} 要素でターゲット画像を指す <code><img></code> タグをラップすることでユーザーは必要に応じてクリックしてアクセスできます。</p> + +<p>アプリ自体は JavaScript に依存しているので、これを行いません — それがないと、ゲームのリストが読み込まれず、サービスワーカーのコードも実行されません。</p> + +<p>画像だけでなく、詳しい説明とリンクからなる完全な項目を読み込むように読み込み処理を書き直すことができます。 これは無限スクロールのように機能します — ユーザーがページを下にスクロールしたときにだけリストの項目を読み込みます。 そうすれば、初期の HTML 構造は最小限になり、読み込み時間はさらに短くなり、パフォーマンス上の利点もさらに大きくなります。</p> + +<h2 id="Conclusion" name="Conclusion">まとめ</h2> + +<p>最初に読み込むファイルが少ない、モジュールに分割される小さいファイル、プレースホルダーを使用する、さらにオンデマンドでより多くのコンテンツを読み込む — これは初期読み込み時間を短縮するのに役立ち、アプリ作成者にメリットをもたらし、ユーザーにスムーズなエクスペリエンスを提供します。</p> + +<p>プログレッシブエンハンスメントのアプローチを忘れないでください — デバイスやプラットフォームに関係なく使用可能な製品を提供しますが、最新のブラウザーを使用しているユーザーにはエクスペリエンスを豊かなものにするようにしてください。</p> + +<h2 id="Final_thoughts" name="Final_thoughts">最終的な考え</h2> + +<p>このチュートリアルのシリーズではこれですべてです — <a href="https://github.com/mdn/pwa-examples/tree/master/js13kpwa">js13kPWA サンプルアプリのソースコード</a>を調べて、<a href="/ja/docs/Web/Progressive_web_apps/Introduction">紹介</a>、<a href="/ja/docs/Web/Progressive_web_apps/App_structure">PWA の構造</a>、<a href="/ja/docs/Web/Progressive_web_apps/Offline_Service_workers">サービスワーカーでのオフライン可用性</a>、<a href="/ja/docs/Web/Progressive_web_apps/Installable_PWAs">インストール可能な PWA</a>、そして最後に<a href="/ja/docs/Web/Progressive_web_apps/Re-engageable_Notifications_Push">通知</a>など、プログレッシブウェブアプリ機能の使用方法について学びました。 また、<a href="https://serviceworke.rs/">サービスワーカークックブック</a>(英語)の助けを借りてプッシュを説明しました。 そしてこの記事では、<a href="/ja/docs/Web/API/Intersection_Observer_API">Intersection Observer API</a> を利用した興味深い例を含めて、プログレッシブ読み込みの概念を調べました。</p> + +<p>コードを試したり、PWA 機能を使用して既存のアプリを拡張したり、まったく新しいものを自分で作成したりしてください。 PWA は通常のウェブアプリよりも大きな利点をもたらします。</p> + +<p>{{PreviousMenu("Web/Progressive_web_apps/Re-engageable_Notifications_Push", "Web/Progressive_web_apps")}}</p> + +<p>{{QuickLinksWithSubpages("/ja/docs/Web/Progressive_web_apps/")}}</p> diff --git a/files/ja/web/progressive_web_apps/offline_service_workers/index.html b/files/ja/web/progressive_web_apps/offline_service_workers/index.html new file mode 100644 index 0000000000..8bd2abdb81 --- /dev/null +++ b/files/ja/web/progressive_web_apps/offline_service_workers/index.html @@ -0,0 +1,208 @@ +--- +title: サービスワーカーで PWA をオフラインで動作させる +slug: Web/Progressive_web_apps/Offline_Service_workers +tags: + - Offline + - PWAs + - Progressive web apps + - Service Workers + - js13kGames + - progressive +translation_of: Web/Progressive_web_apps/Offline_Service_workers +--- +<div>{{PreviousMenuNext("Web/Progressive_web_apps/App_structure", "Web/Progressive_web_apps/Installable_PWAs", "Web/Progressive_web_apps")}}</div> + +<p class="summary"><span class="seoSummary">js13kPWA の構造と、基本シェルが起動し実行させる様子を見てきたので、サービスワーカーを使用したオフライン機能の実装方法を見てみましょう。 この記事では、 <a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA の例</a> (<a href="https://github.com/mdn/pwa-examples/tree/master/js13kpwa">ソースコードはこちら</a>) で使用されている実現方法を見てみましょう。 どのようにオフライン機能を追加するのかを学習します。</span></p> + +<h2 id="Service_workers_explained" name="Service_workers_explained">サービスワーカーの説明</h2> + +<p>サービスワーカー(Service Workers)は、ブラウザーとネットワーク間の仮想プロキシです。 これらはついにフロントエンド開発者が長年にわたって苦労してきた問題を修正します — 最も注目に値するのは、ウェブサイトのアセットを適切にキャッシュし、ユーザーのデバイスがオフラインのときにそれらを利用できるようにする方法です。</p> + +<p>これらは、ページのメインの JavaScript コードとは別のスレッドで実行され、DOM 構造にアクセスすることはできません。 これは、従来のウェブプログラミングとは異なるアプローチを取り入れています — API はノンブロッキングで、異なるコンテキスト間で通信を送受信できます。 あなたはサービスワーカーに取り組むべき何かを与え、約束(<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>)ベースのアプローチを使用して準備ができているときはいつでも結果を受け取ることができます。</p> + +<p>通知の処理、別のスレッドでの大量の計算など、オフライン機能を提供するだけではありません。 サービスワーカーは、ネットワーク要求を制御したり、それらを変更したり、キャッシュから取得したカスタム応答を提供したり、応答を完全に合成したりできるので、非常に強力です。</p> + +<h3 id="Security" name="Security">セキュリティ</h3> + +<p>サービスワーカーは非常に強力であるため、安全なコンテキスト(HTTPS を意味する)でしか実行できません。 コードを本番環境に移行する前に最初に試してみたい場合は、いつでも localhost でテストするか GitHub Pages を設定することができます。 どちらも HTTPS をサポートしています。</p> + +<h2 id="Offline_First" name="Offline_First">オフライン優先</h2> + +<p>「オフライン優先」または「キャッシュ優先」のパターンは、コンテンツをユーザーに提供するための最も一般的な戦略です。 リソースがキャッシュされてオフラインで利用可能な場合は、サーバーからダウンロードする前に最初にそれを返します。 まだキャッシュに入っていない場合は、ダウンロードして将来の使用に備えてキャッシュします。</p> + +<h2 id="Progressive_in_PWA" name="Progressive_in_PWA">PWA における「プログレッシブ」</h2> + +<p>プログレッシブエンハンスメントとして適切に実装されている場合、サービスワーカーは、オフラインサポートを提供することで API をサポートする最新のブラウザーを使用しているユーザーにメリットをもたらすことができますが、従来のブラウザを使用しているユーザーにとっては何もだめになりません。</p> + +<h2 id="Service_workers_in_the_js13kPWA_app" name="Service_workers_in_the_js13kPWA_app">js13kPWA アプリのサービスワーカー</h2> + +<p>十分な理論 — いくつかのソースコードを見てみましょう!</p> + +<h3 id="Registering_the_Service_Worker" name="Registering_the_Service_Worker">サービスワーカーの登録</h3> + +<p>app.js ファイルで、新しいサービスワーカーを登録するコードを見ることから始めます。</p> + +<p><strong>注</strong> : ここでは <a href="http://es6-features.org/">es6</a> の<strong>アロー関数</strong>の構文をサービスワーカーの実装に使用しています。</p> + +<pre class="brush: js notranslate">if('serviceWorker' in navigator) { + navigator.serviceWorker.register('./pwa-examples/js13kpwa/sw.js'); +};</pre> + +<p><a href="/ja/docs/Web/API/Service_Worker_API">Service Worker API</a> をブラウザーがサポートしている場合は、{{domxref("ServiceWorkerContainer.register()")}} メソッドを使用してサイトに対して登録します。 その内容は <code>sw.js</code> ファイルにあり、登録が成功した後に実行できます。 これが <code>app.js</code> ファイルの中にある唯一のサービスワーカーのコードで、それ以外のサービスワーカー固有のものはすべて <code>sw.js</code> ファイル自体にあります。</p> + +<h3 id="Lifecycle_of_a_Service_Worker" name="Lifecycle_of_a_Service_Worker">サービスワーカーのライフサイクル</h3> + +<p>登録が完了すると、<code>sw.js</code> ファイルが自動的にダウンロードされてからインストールされ、最後にアクティブになります。</p> + +<h4 id="Installation" name="Installation">インストール</h4> + +<p>API を使用すると、関心のある重要なイベントのイベントリスナーを追加できます — 最初のものは <code>install</code> イベントです。</p> + +<pre class="brush: js notranslate">self.addEventListener('install', (e) => { + console.log('[Service Worker] Install'); +});</pre> + +<p><code>install</code> リスナーで、キャッシュを初期化し、オフラインで使用するためにファイルをキャッシュに追加することができます。 js13kPWA アプリはまさにそれを行います。</p> + +<p>まず、キャッシュ名を格納するための変数が作成され、アプリシェル(app shell)のファイルが1つの配列にリストされます。</p> + +<pre class="brush: js notranslate">var cacheName = 'js13kPWA-v1'; +var appShellFiles = [ + '/pwa-examples/js13kpwa/', + '/pwa-examples/js13kpwa/index.html', + '/pwa-examples/js13kpwa/app.js', + '/pwa-examples/js13kpwa/style.css', + '/pwa-examples/js13kpwa/fonts/graduate.eot', + '/pwa-examples/js13kpwa/fonts/graduate.ttf', + '/pwa-examples/js13kpwa/fonts/graduate.woff', + '/pwa-examples/js13kpwa/favicon.ico', + '/pwa-examples/js13kpwa/img/js13kgames.png', + '/pwa-examples/js13kpwa/img/bg.png', + '/pwa-examples/js13kpwa/icons/icon-32.png', + '/pwa-examples/js13kpwa/icons/icon-64.png', + '/pwa-examples/js13kpwa/icons/icon-96.png', + '/pwa-examples/js13kpwa/icons/icon-128.png', + '/pwa-examples/js13kpwa/icons/icon-168.png', + '/pwa-examples/js13kpwa/icons/icon-192.png', + '/pwa-examples/js13kpwa/icons/icon-256.png', + '/pwa-examples/js13kpwa/icons/icon-512.png' +];</pre> + +<p>次に、<code>data/games.js</code> ファイルからのコンテンツとともにロードされる画像へのリンクが2番目の配列に生成されます。 その後、両方の配列は {{jsxref("Array.prototype.concat()")}} 関数を使ってマージされます。</p> + +<pre class="brush: js notranslate">var gamesImages = []; +for(var i=0; i<games.length; i++) { + gamesImages.push('data/img/'+games[i].slug+'.jpg'); +} +var contentToCache = appShellFiles.concat(gamesImages);</pre> + +<p>それから、<code>install</code> イベント自体を管理できます。</p> + +<pre class="brush: js notranslate">self.addEventListener('install', (e) => { + console.log('[Service Worker] Install'); + e.waitUntil( + caches.open(cacheName).then((cache) => { + console.log('[Service Worker] Caching all: app shell and content'); + return cache.addAll(contentToCache); + }) + ); +});</pre> + +<p>ここで説明が必要なことが2つあります — {{domxref("ExtendableEvent.waitUntil")}} が行うことと、{{domxref("Cache","caches")}} オブジェクトとは何か。</p> + +<p>サービスワーカーは、<code>waitUntil</code> 内のコードが実行されるまでインストールされません。 それは約束(promise)を返します — インストールにはしばらく時間がかかるかもしれないので完了するまで待つこのアプローチが必要です。</p> + +<p><code>caches</code> は特定のサービスワーカーの範囲内でデータの保存を可能にする特別な {{domxref("CacheStorage")}} オブジェクトです — <a href="/ja/docs/Web/API/Web_Storage_API">ウェブストレージ</a>は同期的であるため、ウェブストレージへの保存は機能しません。 サービスワーカーでは、代わりに Cache API を使用します。</p> + +<p>ここでは、指定した名前でキャッシュを開き、アプリが使用するすべてのファイルをキャッシュに追加するので、次回のロード時に利用可能になります(要求 URL で識別されます)。</p> + +<h4 id="Activation" name="Activation">アクティベーション</h4> + +<p><code>activate</code> イベントもあり、これは <code>install</code> と同じ方法で使用されます。 このイベントは通常、不要になったファイルを削除し、一般的にアプリの後にクリーンアップするために使用されます。 私たちのアプリでそれをする必要はないので、それをスキップします。</p> + +<h3 id="Responding_to_fetches" name="Responding_to_fetches">フェッチへの応答</h3> + +<p>また、自由に使える <code>fetch</code> イベントもあり、これは HTTP 要求がアプリから発するたびに発生します。 これは要求を傍受してカスタム応答でそれらに応答することを可能にするので非常に便利です。 これは簡単な使用例です。</p> + +<pre class="brush: js notranslate">self.addEventListener('fetch', (e) => { + console.log('[Service Worker] Fetched resource '+e.request.url); +});</pre> + +<p>応答は望むものなら何でも構いません — 要求されたファイル、そのキャッシュされたコピー、または特定のことを実行する JavaScript コードの一部 — 可能性は無限大です。</p> + +<p>このサンプルアプリでは、リソースが実際にキャッシュ内にある限り、ネットワークではなくキャッシュからコンテンツを提供します。 アプリがオンラインかオフラインかに関係なく、これを行います。 ファイルがキャッシュにない場合、アプリはそれを提供する前にまずそこに追加します。</p> + +<pre class="brush: js notranslate">self.addEventListener('fetch', (e) => { + e.respondWith( + caches.match(e.request).then((r) => { + console.log('[Service Worker] Fetching resource: '+e.request.url); + return r || fetch(e.request).then((response) => { + return caches.open(cacheName).then((cache) => { + console.log('[Service Worker] Caching new resource: '+e.request.url); + cache.put(e.request, response.clone()); + return response; + }); + }); + }) + ); +});</pre> + +<p>ここでは、キャッシュ内のリソースを見つけ、存在する場合は応答を返そうとする関数を使用して、<code>fetch</code> イベントに応答します。 存在しない場合は、別のフェッチ要求を使用してネットワークからそれをフェッチし、次に応答がキャッシュに格納されるので、次に要求されたときに応答が使用可能になります。</p> + +<p>{{domxref("FetchEvent.respondWith")}} メソッドが制御を引き継ぎます — これは、アプリとネットワークの間のプロキシサーバーとして機能する部分です。 これにより、すべての要求に対して、必要な応答を返すことができます — サービスワーカーによって準備され、キャッシュから取得され、必要に応じて変更された。</p> + +<p>それでおしまい! 私たちのアプリはインストール時にそのリソースをキャッシュしてキャッシュからのフェッチでそれらを提供しているので、ユーザーがオフラインであっても機能します。 追加されるたびに新しいコンテンツもキャッシュします。</p> + +<h2 id="Updates" name="Updates">更新</h2> + +<p>まだカバーしておくべき1つのポイントがあります — 新しいアセットを含むアプリの新しいバージョンが利用可能になったときにどのようにサービスワーカーをアップグレードするのでしょうか? これには、キャッシュ名のバージョン番号が重要です。</p> + +<pre class="brush: js notranslate">var cacheName = 'js13kPWA-v1';</pre> + +<p>これが v2 に更新されるとき、新しいキャッシュに(新しいファイルを含む)すべてのファイルを追加することができます。</p> + +<pre class="brush: js notranslate">contentToCache.push('/pwa-examples/js13kpwa/icons/icon-32.png'); + +// ... + +self.addEventListener('install', (e) => { + e.waitUntil( + caches.open('js13kPWA-v2').then((cache) => { + return cache.addAll(contentToCache); + }) + ); +});</pre> + +<p>新しいサービスワーカーがバックグラウンドでインストールされ、前のバージョン(v1)はそれを使用するページがなくなるまで正しく動作します — 新しいサービスワーカーがアクティブになり、古いページからページの管理を引き継ぎます。</p> + +<h2 id="Clearing_the_cache" name="Clearing_the_cache">キャッシュのクリア</h2> + +<p>スキップした <code>activate</code> イベントを覚えていますか? これは、不要になった古いキャッシュを消去するために使用できます。</p> + +<pre class="brush: js notranslate">self.addEventListener('activate', (e) => { + e.waitUntil( + caches.keys().then((keyList) => { + return Promise.all(keyList.map((key) => { + if(key !== cacheName) { + return caches.delete(key); + } + })); + }) + ); +});</pre> + +<p>これにより、必要なファイルだけがキャッシュに保存されるので、ゴミが残ることはありません — <a href="/ja/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria">ブラウザーで利用可能なキャッシュスペースは限られている</a>ので、後で自分でクリーンアップすることをお勧めします。</p> + +<h2 id="Other_use_cases" name="Other_use_cases">その他のユースケース</h2> + +<p>サービスワーカーが提供する機能は、キャッシュからファイルを提供することだけではありません。 大量の計算が必要な場合は、メインスレッドからそれらをオフロードしてワーカーで実行し、使用可能になったらすぐに結果を受け取ることができます。 パフォーマンス面では、今は必要ではないが近い将来にある可能性があるリソースをプリフェッチすることができるため、実際にそれらのリソースが必要な場合はアプリの速度が速くなります。</p> + +<h2 id="Summary" name="Summary">まとめ</h2> + +<p>この記事では、PWA をサービスワーカーとオフラインで連携させる方法について簡単に説明しました。 <a href="/ja/docs/Web/API/Service_Worker_API">Service Worker API</a> の背後にある概念と、それをより詳細に使用する方法についてもっと知りたい場合は、さらに詳しい資料をチェックしてください。</p> + +<p><a href="/ja/docs/Web/API/Push_API">プッシュ通知</a>を処理するときにもサービスワーカーを使用します — これについては後の記事で説明します。</p> + +<p>{{PreviousMenuNext("Web/Progressive_web_apps/App_structure", "Web/Progressive_web_apps/Installable_PWAs", "Web/Progressive_web_apps")}}</p> + +<div>{{QuickLinksWithSubpages("/ja/docs/Web/Progressive_web_apps/")}}</div> diff --git a/files/ja/web/progressive_web_apps/re-engageable_notifications_push/index.html b/files/ja/web/progressive_web_apps/re-engageable_notifications_push/index.html new file mode 100644 index 0000000000..9ff8b62ef9 --- /dev/null +++ b/files/ja/web/progressive_web_apps/re-engageable_notifications_push/index.html @@ -0,0 +1,249 @@ +--- +title: 通知とプッシュを利用して PWA を再エンゲージ可能にするには +slug: Web/Progressive_web_apps/Re-engageable_Notifications_Push +tags: + - Notifications + - PWAs + - Progressive web apps + - Push + - js13kGames + - progressive +translation_of: Web/Progressive_web_apps/Re-engageable_Notifications_Push +--- +<div>{{PreviousMenuNext("Web/Progressive_web_apps/Installable_PWAs", "Web/Progressive_web_apps/Loading", "Web/Progressive_web_apps")}}</div> + +<p class="summary"><span class="seoSummary">アプリのコンテンツをキャッシュできるようにしてオフラインで動作させるのは、すばらしい機能です。 ユーザーがホーム画面にウェブアプリをインストールできるようにすることは、もっと良いことです。 しかし、ユーザーの操作のみに頼らず、プッシュメッセージと通知を使用すれば、さらに自動的に再エンゲージを行い新しいコンテンツが利用できるようになるたびに配信することができるようになります。</span></p> + +<h2 id="Two_APIs_one_goal" name="Two_APIs_one_goal">二つの API と一つの目標</h2> + +<p><a href="/ja/docs/Web/API/Push_API">Push API</a> と <a href="/ja/docs/Web/API/Notifications_API">Notifications API</a> は2つの別々の API ですが、アプリで魅力的な機能を提供したい場合には、それらは一緒にうまく機能します。 プッシュは、クライアント側の介入なしにサーバーからアプリに新しいコンテンツを配信するために使用され、その操作はアプリのサービスワーカーによって処理されます。 サービスワーカーは、通知を使用して新しい情報をユーザーに表示するか、少なくとも何かが更新されたときにアラートすることができます。</p> + +<p>それらはサービスワーカーと同じようにブラウザーウィンドウの外側で機能するため、アプリのページにフォーカスが合っていないときや閉じているときにも更新をプッシュして通知を表示できます。</p> + +<h2 id="Notifications" name="Notifications">通知</h2> + +<p>通知(notifications)から始めましょう — プッシュがなくても機能しますが、それらを組み合わせると非常に便利です。 はじめはそれらを個別に見てみましょう。</p> + +<h3 id="Request_permission" name="Request_permission">パーミッションの要求</h3> + +<p>通知を表示するには、まずパーミッション(permission)を要求する必要があります。 ただちに通知を表示する代わりに、次のようにユーザーがボタンをクリックして要求したときにポップアップを表示することをお勧めします。</p> + +<pre class="brush: js notranslate">var button = document.getElementById("notifications"); +button.addEventListener('click', function(e) { + Notification.requestPermission().then(function(result) { + if(result === 'granted') { + randomNotification(); + } + }); +});</pre> + +<p>これは、次のようにオペレーティングシステム独自の通知サービスを使ったポップアップを表示します。</p> + +<p><img alt="Notification of js13kPWA." src="https://mdn.mozillademos.org/files/15930/js13kpwa-notification.png" style="display: block; height: 640px; margin: 0px auto; width: 360px;"></p> + +<p>ユーザーが通知を受け取ることを確認すると、アプリはそれらを表示できます。 ユーザー操作の結果は、デフォルト(<code>default</code>)、許可(<code>granted</code>)、または拒否(<code>denied</code>)になります。 ユーザーが後で選択する場合はデフォルトの選択肢が選択され、ユーザーがそれぞれ「はい」または「いいえ」をクリックすると他の2つが設定されます。</p> + +<p>承認されると、パーミッションは通知とプッシュの両方に機能します。</p> + +<h3 id="Create_a_notification" name="Create_a_notification">通知の作成</h3> + +<p>サンプルアプリでは、利用可能なデータから通知を作成します — ゲームはランダムに選択され、選択されたものがコンテンツと共に通知を送ります — それは次のようにゲームの名前をタイトルとして設定し、本文で作者に言及し、そしてアイコンとして画像を表示します。</p> + +<pre class="brush: js notranslate">function randomNotification() { + var randomItem = Math.floor(Math.random()*games.length); + var notifTitle = games[randomItem].name; + var notifBody = 'Created by '+games[randomItem].author+'.'; + var notifImg = 'data/img/'+games[randomItem].slug+'.jpg'; + var options = { + body: notifBody, + icon: notifImg + } + var notif = new Notification(notifTitle, options); + setTimeout(randomNotification, 30000); +}</pre> + +<p>迷惑すぎてユーザーによって無効にされるまで、新しいランダム通知が30秒ごとに作成されます — 実際のアプリの場合、通知はそれほど頻繁ではなく、より便利であるべきです。 Notifications API の利点は、オペレーティングシステムの通知機能を使用することです。 つまり、ウェブアプリを見ていなくてもユーザーに通知を表示でき、その通知はネイティブアプリで表示されるものと似ています。</p> + +<h2 id="Push" name="Push">プッシュ</h2> + +<p>プッシュは通知よりも複雑です — データをアプリに送り返すサーバーを購読(subscribe)する必要があります。 アプリのサービスワーカーはプッシュサーバーからデータを受け取ります。 このデータは通知システム、または必要に応じて別のメカニズムを使用して表示できます。</p> + +<p>技術はまだ非常に初期段階にあります — いくつかの実用的な例は Google Cloud Messaging プラットフォームを使用しますが、<a href="https://blog.mozilla.org/services/2016/08/23/sending-vapid-identified-webpush-notifications-via-mozillas-push-service/">VAPID</a>(Voluntary Application Server Identification、自発的アプリケーションサーバー識別)をサポートするように書き直されています。 <a href="https://serviceworke.rs/push-payload.html">サービスワーカークックブックの例</a>(英語)を調べたり、<a href="https://firebase.google.com/">Firebase</a> を使用してプッシュメッセージングサーバーをセットアップしたり、(例えば Node.js を使用して)独自のサーバーを構築したりすることができます。</p> + +<p>前述のように、プッシュメッセージを受信できるようにするには、サービスワーカーが必要です。 その基本については、<a href="/ja/docs/Web/Progressive_web_apps/Offline_Service_workers">サービスワーカーで PWA をオフラインで動作させる</a>の記事で既に説明しています。 サービスワーカーの内部には、プッシュサービス購読機構(push service subscription mechanism)が作成されています。</p> + +<pre class="brush: js notranslate">registration.pushManager.getSubscription() .then( /* ... */ );</pre> + +<p>ユーザーが購読すると、サーバーからプッシュ通知を受け取ることができます。</p> + +<p>サーバー側からは、セキュリティ上の理由からプロセス全体を公開鍵と秘密鍵で暗号化する必要があります — アプリを使用してセキュリティ保護されていないプッシュメッセージをだれでも送信できるようにするのは恐ろしい考えです。 サーバーのセキュリティ保護の詳細については、<a href="https://jrconlin.github.io/WebPushDataTestPage/">ウェブプッシュデータ暗号化テストページ</a>(英語)を参照してください。 サーバーは、ユーザーが購読したときに受信したすべての情報を保存するので、メッセージは後で必要なときに送信できます。</p> + +<p>プッシュメッセージを受信するために、次のようにサービスワーカーファイルの {{domxref("ServiceWorkerGlobalScope/push_event", "push")}} イベントを監視できます。</p> + +<pre class="brush: js notranslate">self.addEventListener('push', function(e) { /* ... */ });</pre> + +<p>データを取得してすぐにユーザーへの通知として表示できます。 これは、例えば、何かをユーザーに思い出させるために使用したり、アプリで利用可能な新しいコンテンツについてユーザーに知らせたりするために使用できます。</p> + +<h3 id="Push_example" name="Push_example">プッシュの例</h3> + +<p>プッシュにはサーバー部分が機能する必要があるため、静的ファイルのみのホスティングを提供する GitHub Pages でホスティングされる js13kPWA の例に含めることはできません。 それはすべて<a href="https://serviceworke.rs/">サービスワーカークックブック</a>(英語)で説明されています — <a href="https://serviceworke.rs/push-payload.html">Push Payload Demo</a> を参照してください。</p> + +<p>このデモは3つのファイルで構成されています。</p> + +<ul> + <li><a href="https://github.com/mozilla/serviceworker-cookbook/blob/master/push-payload/index.js">index.js</a> — アプリのソースコードが含まれています。</li> + <li><a href="https://github.com/mozilla/serviceworker-cookbook/blob/master/push-payload/server.js">server.js</a> — サーバー部分が含まれています(Node.js で書かれています)。</li> + <li><a href="https://github.com/mozilla/serviceworker-cookbook/blob/master/push-payload/service-worker.js">service-worker.js</a> — サービスワーカー固有のコードが含まれています。</li> +</ul> + +<p>これらすべてを探りましょう。</p> + +<h4 id="index.js" name="index.js">index.js</h4> + +<p><code>index.js</code> ファイルは、次のようにサービスワーカーを登録することから始まります。</p> + +<pre class="brush: js notranslate">navigator.serviceWorker.register('service-worker.js') +.then(function(registration) { + return registration.pushManager.getSubscription() + .then(async function(subscription) { + // registration part + }); +}) +.then(function(subscription) { + // subscription part +});</pre> + +<p><a href="https://mdn.github.io/pwa-examples/js13kpwa/">js13kPWA デモ</a>で見たサービスワーカーよりも少し複雑です。 この特定のケースでは、登録後、登録オブジェクト(registration object)を使用して購読し、次に結果として得られた購読オブジェクト(subscription object)を使用してプロセス全体を完了します。</p> + +<p>登録部分(registration part)では、コードは次のようになります。</p> + +<pre class="brush: js notranslate">if(subscription) { + return subscription; +}</pre> + +<p>ユーザーが既に購読している場合は、購読オブジェクトを返して購読部分(subscription part)に移ります。 そうでない場合は、次のように新しい購読を初期化します。</p> + +<pre class="brush: js notranslate">const response = await fetch('./vapidPublicKey'); +const vapidPublicKey = await response.text(); +const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);</pre> + +<p>アプリはサーバーの公開鍵を取得してレスポンスをテキストに変換します。 それから Uint8Array に変換する必要があります(Chrome をサポートするため)。 VAPID キーの詳細については、<a href="https://blog.mozilla.org/services/2016/08/23/sending-vapid-identified-webpush-notifications-via-mozillas-push-service/">VAPID で識別した WebPush 通知を Mozilla のプッシュサービス経由で送信する</a>(英語)のブログ投稿を読むことができます。</p> + +<p>アプリは {{domxref("PushManager")}} を使用して新しいユーザーの購読をすることができます。 {{domxref("PushManager.subscribe()")}} メソッドに渡される2つのオプションがあります — 1つ目は <code>userVisibleOnly:true</code> で、これはユーザーに送信されたすべての通知が表示されることを意味します。 2つ目は <code>applicationServerKey</code> で、これには、取得と変換に成功した VAPID キーが含まれます。</p> + +<pre class="brush: js notranslate">return registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: convertedVapidKey +});</pre> + +<p>それでは購読部分(subscription part)に移りましょう — アプリは最初に Fetch を使って購読の詳細を JSON としてサーバーに送ります。</p> + +<pre class="brush: js notranslate">fetch('./register', { + method: 'post', + headers: { + 'Content-type': 'application/json' + }, + body: JSON.stringify({ + subscription: subscription + }), +});</pre> + +<p>次に、[Request sending a notification!(通知の送信依頼)] ボタンの {{domxref("GlobalEventHandlers.onclick","onclick")}} 関数を定義します。</p> + +<pre class="brush: js notranslate">document.getElementById('doIt').onclick = function() { + const payload = document.getElementById('notification-payload').value; + const delay = document.getElementById('notification-delay').value; + const ttl = document.getElementById('notification-ttl').value; + + fetch('./sendNotification', { + method: 'post', + headers: { + 'Content-type': 'application/json' + }, + body: JSON.stringify({ + subscription: subscription, + payload: payload, + delay: delay, + ttl: ttl, + }), + }); +};</pre> + +<p>このボタンがクリックされると、<code>fetch</code> はサーバーに与えられたパラメータで通知を送るように要求します — <code>payload</code> は通知に表示されるテキストで、<code>delay</code> は通知が表示されるまでの遅延を秒単位で定義し、<code>ttl</code> は指定された期間サーバー上で通知を利用できるようにする存続時間(time-to-live)の設定で、これも秒単位で定義します。</p> + +<p>それでは、次の JavaScript ファイルに進みましょう。</p> + +<h4 id="server.js" name="server.js">server.js</h4> + +<p>サーバー部分は Node.js で書かれており、適切な場所にホストする必要があります。 これは、まったく別の記事の主題です。 ここでは大まかな概要のみを説明します。</p> + +<p><a href="https://www.npmjs.com/package/web-push">web-push モジュール</a>(英語)は VAPID キーを設定するために使用され、それらがまだ利用できない場合は必要に応じて生成します。</p> + +<pre class="brush: js notranslate">const webPush = require('web-push'); + +if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) { + console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+ + "environment variables. You can use the following ones:"); + console.log(webPush.generateVAPIDKeys()); + return; +} + +webPush.setVapidDetails( + 'https://serviceworke.rs/', + process.env.VAPID_PUBLIC_KEY, + process.env.VAPID_PRIVATE_KEY +); +</pre> + +<p>次に、モジュールはアプリが処理する必要があるすべてのルートを定義してエクスポートします — VAPID 公開鍵の取得、登録、そして通知の送信です。 使用されている <code>index.js</code> ファイルの変数(<code>payload</code>、<code>delay</code>、および <code>ttl</code>)を見ることができます。</p> + +<pre class="brush: js notranslate">module.exports = function(app, route) { + app.get(route + 'vapidPublicKey', function(req, res) { + res.send(process.env.VAPID_PUBLIC_KEY); + }); + + app.post(route + 'register', function(req, res) { + + res.sendStatus(201); + }); + + app.post(route + 'sendNotification', function(req, res) { + const subscription = req.body.subscription; + const payload = req.body.payload; + const options = { + TTL: req.body.ttl + }; + + setTimeout(function() { + webPush.sendNotification(subscription, payload, options) + .then(function() { + res.sendStatus(201); + }) + .catch(function(error) { + console.log(error); + res.sendStatus(500); + }); + }, req.body.delay * 1000); + }); +};</pre> + +<h4 id="service-worker.js" name="service-worker.js">service-worker.js</h4> + +<p>最後に取り上げるファイルは、サービスワーカーです。</p> + +<pre class="brush: js notranslate">self.addEventListener('push', function(event) { + const payload = event.data ? event.data.text() : 'no payload'; + event.waitUntil( + self.registration.showNotification('ServiceWorker Cookbook', { + body: payload, + }) + ); +});</pre> + +<p>{{domxref("ServiceWorkerGlobalScope/push_event", "push")}} イベントのリスナーを追加し、データから取得したテキストからなる <code>payload</code> 変数を作成し(またはデータが空の場合に使用する文字列を作成し)、通知がユーザーに表示されるまで待ちます。</p> + +<p>それらがどのように処理されるかを知りたい場合は、<a href="https://serviceworke.rs/">サービスワーカークックブック</a>(英語)の残りの例を調べてください — <a href="https://github.com/mozilla/serviceworker-cookbook/">完全なソースコードは GitHub で入手できます</a>。 一般的な使い方だけでなく、ウェブプッシュ、キャッシュ戦略、パフォーマンス、オフラインでの作業など、多数の実用的な例があります。</p> + +<p>{{PreviousMenuNext("Web/Progressive_web_apps/Installable_PWAs", "Web/Progressive_web_apps/Loading", "Web/Progressive_web_apps")}}</p> + +<div>{{QuickLinksWithSubpages("/ja/docs/Web/Progressive_web_apps/")}}</div> diff --git a/files/ja/web/progressive_web_apps/responsive/media_types/index.html b/files/ja/web/progressive_web_apps/responsive/media_types/index.html new file mode 100644 index 0000000000..9f1d90396e --- /dev/null +++ b/files/ja/web/progressive_web_apps/responsive/media_types/index.html @@ -0,0 +1,405 @@ +--- +title: メディア +slug: Web/Progressive_web_apps/Responsive/Media_types +tags: + - CSS + - Example + - Guide + - Intermediate + - NeedsMarkupWork + - NeedsUpdate + - Web + - ガイド + - 中級者 +translation_of: Web/Progressive_web_apps/Responsive/Media_types +--- +<div>{{QuickLinksWithSubpages("/ja/docs/Web/Progressive_web_apps/Responsive/")}}</div> + +<p class="summary">これは <a href="/ja/docs/Web/Guide/CSS/Getting_Started">CSS の第一歩</a>チュートリアル第14章で、第1部の最終章です。このチュートリアルの多くのページでは、 CSS プロパティや値と、そのコンテンツを表示する方法を指定するための使い方に焦点を当てていました。</p> + +<h2 class="clearLeft" id="Information_Media" name="Information_Media">メディアについて</h2> + +<p>CSS の目的は、コンテンツがどのようにユーザーに表示されるのかを指定することです。この表示には複数の表現形式をとることができます。</p> + +<p>例えば、おそらくあなたはこれをディスプレイ付きの端末で読んでいるでしょう。しかし、大画面に映して多くの人に読んでもらいたいと思うこともありますし、印刷したいと思ってう場合もあるでしょう。これらの様々なメディアには、それぞれ異なる特性があります。 CSS はメディアの種類に応じてコンテンツを提示する機能を持っています。</p> + +<p>あるメディア種別に特有の規則を定義するには、 {{CSSxRef("@media")}} に続けてメディア種別を記述し、さらに続けて波括弧の中に規則を記述します。</p> + +<div class="tuto_example"> +<h4 class="tuto_type" id="Example" name="Example">例</h4> + +<p>あるウェブサイトの文書に、主要なサイトメニューを含むナビゲーション領域が設けられているとします。</p> + +<p>マークアップ言語では、ナビゲーション領域の親要素は <strong>id</strong> <code>nav-area</code> を持っています ({{HTMLVersionInline(5)}} では、これは <strong>id</strong> 属性を持つ {{HTMLElement("div")}} 要素での代わりに、{{HTMLElement("nav")}} 要素でマークアップできます)。</p> + +<p>文書を印刷するときにはナビゲーション領域は無意味ですから、この CSS (下記) では、文書を印刷する際にはナビゲーション領域を削除します。</p> + +<pre class="brush:css">@media print { + #nav-area {display: none;} + } +</pre> +</div> + +<p>よく知られたメディア種別には次のようなものがあります。</p> + +<table class="standard-table"> + <tbody> + <tr> + <td><code>screen</code></td> + <td>端末のカラーディスプレイ</td> + </tr> + <tr> + <td><code>print</code></td> + <td>ページ単位に印刷されるメディア</td> + </tr> + <tr> + <td style="padding-right: 1em;"><code>projection</code></td> + <td>プロジェクター</td> + </tr> + <tr> + <td><code>all</code></td> + <td>すべてのメディア (既定値)</td> + </tr> + </tbody> +</table> + +<div class="tuto_details"> +<h4 class="tuto_type" id="More_details" name="More_details">より詳しく</h4> + +<p>ある規則の集合にメディア種別を定義する方法は、他にもあります。</p> + +<p>文書のマークアップ言語によっては、スタイルシートが文書にリンクされたときに、メディア種別を定義できるものがあります。例えば、 HTML では <code>LINK</code> 要素の <code>media</code> 属性を使ってメディア種別を指定することができます。</p> + +<p>CSS ではスタイルシートの初めに {{CSSxRef("@import")}} を使って、 URL から他のスタイルシートを読み込むことができ、オプションとしてメディア種別を指定することができます。</p> + +<p>これらは、様々なメディア種別のスタイル付け規則を異なるファイルに分離する方法です。</p> + +<p>メディア種別の完全な説明は、 CSS 仕様書の <a href="http://www.w3.org/TR/CSS21/media.html">Media</a> をご覧ください。</p> + +<p>{{CSSxRef("display")}} プロパティのその他の利用例は、このチュートリアルの後で登場する <a href="/ja/docs/Web/Guide/CSS/Getting_Started/XML_data">XML データ</a> のページにあります。</p> +</div> + +<h3 id="Printing" name="Printing">印刷</h3> + +<p>CSS には、印刷や、一般のページ付けされたメディアに特有の対応があります。</p> + +<p>{{CSSxRef("@page")}} 規則で、ページマージンを設定できます。両面印刷には、マージンを <code>@page:left</code> と <code>@page:right</code> で別々に指定できます。</p> + +<p>印刷メディアでは通常、インチ (<code>in</code>) や ポイント (<code>pt</code> = 1/72 inch)、センチメートル (<code>cm</code>) や ミリメートル (<code>mm</code>) など、適切な単位を使います。フォントの大きさにあわせるために em (<code>em</code>) を使ったり、パーセント値 (<code>%</code>) を使ったりするのも同様に適切です。</p> + +<p>ページ境界における文書の内容の分割方法を、 {{CSSxRef("page-break-before")}}, {{CSSxRef("page-break-after")}}, {{CSSxRef("page-break-inside")}} プロパティを使って制御することができます。</p> + +<div class="tuto_example"> +<h4 class="tuto_type" id="Example_2" name="Example_2">例</h4> + +<p>次の規則はページの四辺の余白を1インチに設定します。</p> + +<pre class="brush:css">@page {margin: 1in;} +</pre> + +<p>次の規則は、すべての <small>H1</small> 要素が確実に新しいページで始まるようにします。</p> + +<pre class="brush:css">h1 {page-break-before: always;} +</pre> +</div> + +<div class="tuto_details"> +<h4 class="tuto_type" id="More_details_2" name="More_details_2">さらに詳しく</h4> + +<p>ページ付メディアへの CSS の対応の詳細は、 CSS 仕様書の <a href="http://www.w3.org/TR/CSS21/page.html">Paged media</a> をご覧ください。</p> + +<p>CSS の他の機能と同様に、印刷はブラウザーの選択とその設定に依存します。例えば、 Mozilla ブラウザーでは、印刷用に既定の余白、ヘッダー、フッターが用意されています。印刷される書式を完全に制御することはできないことを覚えておいてください。印刷時にすべてのユーザーのブラウザーの選択や設定を予測することは不可能です。</p> +</div> + +<h3 id="User_interfaces" name="User_interfaces">ユーザーインターフェイス</h3> + +<p>CSS は、コンピューターのディスプレイのようなユーザーインターフェイスを持つ端末のために、特別なプロパティを持っています。これらのプロパティは、ユーザーが作業するインターフェイスの近哲の表示方法を動的に変更することができます。</p> + +<p>5つの特別なセレクターがあります。</p> + +<table class="standard-table"> + <tbody> + <tr> + <td><strong>セレクター</strong></td> + <td><strong>選択対象</strong></td> + </tr> + <tr> + <td><code>E{{CSSxRef(":hover")}}</code></td> + <td>ポインターが上にあるすべての E 要素</td> + </tr> + <tr> + <td><code>E{{CSSxRef(":focus")}}</code></td> + <td>キーボードフォーカスを持つすべての E 要素</td> + </tr> + <tr> + <td><code>E{{CSSxRef(":active")}}</code></td> + <td>現在のユーザーの行動に関係する E 要素</td> + </tr> + <tr> + <td><code>E{{CSSxRef(":link")}}</code></td> + <td>ユーザーが未訪問の URL へのハイパーリンクのある E 要素</td> + </tr> + <tr> + <td><code>E{{CSSxRef(":visited")}}</code></td> + <td>ユーザーが訪問済みの URL へのハイパーリンクのある E 要素</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>注: </strong>:visited セレクターで獲得できる情報は {{gecko("2.0")}} で制限されました。詳細については<a href="/ja/docs/Web/CSS/Privacy_and_the_:visited_selector">プライバシーと :visited セレクター</a>をご覧ください。</p> +</div> + +<p>{{CSSxRef("cursor")}} プロパティは、ポインターの形を定義します。よく使われる形は以下のとおりです。マウスを以下のリストの項目上に置いて、あなたのブラウザーで実際に使われるポインターの形を見てみてください。</p> + +<table class="standard-table"> + <thead> + <tr> + <td><strong>セレクター</strong></td> + <td><strong>選択対象</strong></td> + </tr> + </thead> + <tbody> + <tr style="cursor: pointer;"> + <td><code>pointer</code></td> + <td>リンクを示します</td> + </tr> + <tr style="cursor: wait;"> + <td><code>wait</code></td> + <td>プログラムが入力を受け付けられないことを示します</td> + </tr> + <tr style="cursor: progress;"> + <td><code>progress</code></td> + <td>プログラムが動作しているが、入力が受付可能であることを示します</td> + </tr> + <tr style="cursor: default;"> + <td><code>default</code></td> + <td>既定値 (通常は矢印)</td> + </tr> + </tbody> +</table> + +<p>{{CSSxRef("outline")}} プロパティは、キーボードフォーカスを表すためによく使われる輪郭を作ります。その値は {{CSSxRef("border")}} プロパティに似ていますが、特定の辺だけには定義できない点が異なります。</p> + +<p>ユーザーインターフェイスの他のいくつかの機能は、通常の方法で、属性を使って提供されます。例えば、利用不能、もしくは読み取り専用の要素は <strong>disabled</strong> 属性または <strong>readonly</strong> 属性を持ちます。セレクターは、他の属性と同じく、 <code>[disabled]</code> や <code>[readonly]</code> のように角括弧を使ってこれらの属性を定義することができます。</p> + +<div class="tuto_example"> +<h4 class="tuto_type" id="Example_3" name="Example_3">例</h4> + +<p>次の規則は、ユーザー操作に対し、動的に変化するようなボタンのスタイルを定義します。</p> + +<pre class="brush:css">.green-button { + background-color:#cec; + color:#black; + border:2px outset #cec; + padding: 5px 10px; + } + +.green-button[disabled] { + background-color:#cdc; + color:#777; + } + +.green-button:active, .green-button.active { + border-style: inset; + } +</pre> + +<pre class="brush:html"><table> + <tbody> + <tr> + <td><button class="green-button" disabled>Click me</button></td> + <td><button class="green-button">Click me</button></td> + <td><button class="green-button active">Click me</button></td> + </tr> + <tr style="line-height:25%;"> + <td>&nbsp;</td> + </tr> + <tr style="font-style:italic;"> + <td>disabled</td> + <td>normal</td> + <td>active</td> + </tr> + </tbody> +</table> +</pre> + +<h4 id="Live_Sample" name="Live_Sample"><strong>ライブ例</strong></h4> + +<p>{{ EmbedLiveSample('User_interfaces', '', '', '', 'Web/Apps/Progressive/Responsive/Media_types') }}</p> + +<p>フル機能を持つボタンでは、デフォルトならボタンの周囲に濃い輪郭線を描き、キーボードフォーカスを受けるとボタン表面に点線の輪郭線を描きます。ポインターを上に置いたときのホバー効果も持っているかもしれません。</p> +</div> + +<div class="tuto_details"> +<h4 class="tuto_type" id="More_details_3" name="More_details_3">さらに詳しく</h4> + +<p>CSS におけるユーザーインターフェイスについての詳細は、 CSS 仕様書の <a href="http://www.w3.org/TR/CSS21/ui.html">User interface</a> をご覧ください。</p> +このチュートリアルのパートIIでは、 Mozilla のユーザーインターフェイスのためのマークアップ言語の例があります。 + + +</div> + +<h2 id="Action_Printing_a_document" name="Action_Printing_a_document">実習: 文書を印刷する</h2> + +<div class="note"> +<p><strong>注:</strong> CSS カウンターを使ったページ番号の印刷は Firefox でのみ動作します。仕様書では動作が定義されているか、他のブラウザーで対応するかどうかは不明確です。 <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=774830">issue filed with Chromium</a> を参照してください。</p> +</div> + +<ol> + <li>新しい HTML 文書 <code>doc4.html</code> を作成してください。次の内容をコピー&ペーストしてください。 + + <pre class="brush:html"><!DOCTYPE html> +<html> + <head> + <title>Print sample</title> + <link rel="stylesheet" href="style4.css"> + </head> + <body> + <h1>Section A</h1> + <p>This is the first section...</p> + <h1>Section B</h1> + <p>This is the second section...</p> + <div id="print-head"> + Heading for paged media + </div> + <div id="print-foot"> + Page: + </div> +</body> +</html> +</pre> + </li> + <li>新しいスタイルシート <code>style4.css</code> を作成してください。次の内容をコピー&ペーストしてください。 + <pre class="brush:css">/*** Print sample ***/ + +/* defaults for screen */ +#print-head, +#print-foot { + display: none; + } + +/* print only */ +@media print { + +h1 { + page-break-before: always; + padding-top: 2em; + } + +h1:first-child { + page-break-before: avoid; + counter-reset: page; + } + +#print-head { + display: block; + position: fixed; + top: 0pt; + left:0pt; + right: 0pt; + + font-size: 200%; + text-align: center; + } + +#print-foot { + display: block; + position: fixed; + bottom: 0pt; + right: 0pt; + + font-size: 200%; + } + +#print-foot:after { + content: counter(page); + counter-increment: page; + } + +} /* end print only */ +</pre> + </li> + <li>ブラウザーで文書を見てみましょう。お使いのブラウザーの既定のスタイルが使われています。</li> + <li>文書を印刷 (または印刷プレビュー) してください。スタイルシートは各セクションをページにわけ、各ページにヘッダーとフッターを追加します。お使いのブラウザーがカウンターをサポートしていれば、フッターにページ番号を追加します。 + <table> + <tbody> + <tr> + <td> + <table style="border: 2px outset #3366bb; padding: 1em;"> + <tbody> + <tr> + <td> + <table style="margin-right: 2em; width: 15em;"> + <tbody> + <tr> + <td> + <div style="font-size: 110%; text-align: center; margin-bottom: .5em;">Heading for paged media</div> + + <div style="font-size: 150%; font-weight: bold;">Section A</div> + + <div style="font-size: 75%;">This is the first section...</div> + + <div style="font-size: 150%; text-align: right; margin-top: 12em;">Page: 1</div> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + <td> + <table style="border: 2px outset #3366bb; padding: 1em;"> + <tbody> + <tr> + <td> + <table style="margin-right: 2em; width: 15em;"> + <tbody> + <tr> + <td> + <div style="font-size: 110%; text-align: center; margin-bottom: .5em;">Heading for paged media</div> + + <div style="font-size: 150%; font-weight: bold;">Section B</div> + + <div style="font-size: 75%;">This is the second section...</div> + + <div style="font-size: 150%; text-align: right; margin-top: 12em;">Page: 2</div> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </li> +</ol> + +<table style="background-color: #fffff4; border: 1px solid #3366bb; padding: 1em; width: 100%;"> + <caption> + <h4 id="Challenges" name="Challenges"><strong>チャレンジ</strong></h4> + </caption> + <tbody> + <tr> + <td>印刷に特化したスタイルの規則を、別の CSS ファイルに移してください。 + <p>リファレンスの {{CSSxRef("@import")}} のページを読み、あなたの <code>style4.css</code> スタイルシートに、新しい印刷用のCSS ファイルをインポートする詳しい方法を見つけてください。</p> + + <p>ポインターが上にあるときに、見出しを青く変えるようにしてください。</p> + </td> + </tr> + </tbody> +</table> + +<p><a href="/ja/docs/Web/Guide/CSS/Getting_Started/Challenge_solutions#Media">チャレンジの解答を見る。</a></p> + +<h2 id="What_next" name="What_next">さて次は?</h2> + +<p>このページに、理解しづらい点や、意見がありましたら <a href="/Talk:ja/CSS/Getting_Started/Media">Discussion</a> ページに投稿してください。</p> + +<p>これまでに、このチュートリアルのすべてのスタイル規則はファイル内に定義されてきました。規則とその値は固定されています。次のページでは、プログラミング言語 <strong><a href="/ja/docs/Web/Guide/CSS/Getting_Started/JavaScript">JavaScript</a></strong> を使った、規則の動的な変更方法について述べます。</p> |