みなさん、こんにちは。開発本部のエンジニアの舘野です。先日、社内勉強会「TechLunch」で Badging API について発表したので、その内容を紹介させていただきます。 Badging API とは Badging API とは、ネイティブアプリのアプリアイコン上に表示されるバッジと同様に、ウェブアプリのアイコン上にバッジを表示することができる Web API です。 ネイティブアプリで可能なこと全てをウェブアプリでも可能にすることを目指す、 Fugu というプロジェクトで実現に向けて動いている API の 1 つで、Chrome 73 から Origin Trials として利用可能になっています。Origin Trials とは、試験的に特定の開発者に限定して API を利用できるようにする仕組みのことで、正式リリース前に API に対する有用なフィードバックを受け取ることができるものです。 この API の最新の概要や仕様については、 WICG が Github に Badging API のリポジトリ を用意しているので、そこで確認することができます。 WICG(The Web Incubator Community Group)は、先進的なウェブ技術について検討するコミュニティグループで、W3C のグループの 1 つです。 提案されている API のインターフェースは、現時点(2019/08/14)では以下のようになっています。 badging/explainer.md at main · w3c/badging Badging API. Contribute to w3c/badging development by creating an account on GitHub. github.com Badge を window オブジェクトのメンバとして持つ Badge には 2 つのメソッドが存在する Badge.set() Badge.clear() Badge.set(5) のように set() に整数を渡してバッジ上に数字を表示する 単に Badge.set() で呼び出すとフラグとしてバッジを表示する Badge.set(5, { scope: ‘/baz’ }) のようにオプションを渡して特定のスコープ配下で表示されるように指定できる オプションでスコープが指定されてない場合、スコープは / になる ローカル環境で試す 実際にどのような形でバッジを表示できるかを確認するために、今回はローカル環境(macOS 10.14、Chrome76)で試してみました。 API 自体は非常にシンプルなので、PWA のアプリを用意してインストールするだけで簡単に試すことができます。 インストールされていないウェブアプリでも、タブの favicon 上やブックマークアイコン上にバッジを表示することも議論されているようですが、今のところインストール済みのウェブアプリでしかバッジは表示されません。 最初に API を利用可能な状態にする必要がありますが、上述の通り API 自体が現在 Origin Trials の段階なので、Origin Trials の利用申請を行うかローカル環境であれば chrome://flags で実験的な機能を有効にする(#enable-experimental-web-platform-features)かのいずれかを行う必要があります。 今回はローカル環境で試すだけなので、chrome://flags から enable-experimental-web-platform-features を有効にしておきます。 実験的な機能を利用可能にしたことで Badging API 自体は利用可能になりますが、 window.Badge として利用可能になっているのではなく、Origin Trials の段階では Badge ではなく ExperimentalBadge として提供されています。 次に、サンプルのプロジェクトを用意して webpack-dev-server でローカルサーバを用意します。 $ yarn init $ yarn add --dev webpack webpack-cli webpack-dev-server html-webpack-plugin copy-webpack-plugin webpack-dev-server でローカルサーバが見れる状態になるように webpack.config.js に設定を記述します。 const path = require ( "path" ); const HtmlWwebpackPlugin = require ( "html-webpack-plugin" ); module . exports = { mode: "development" , devServer: { https: true , }, entry: { app: [ "./src/js/app.js" ], }, output: { path: path . resolve ( __dirname , "./dist" ), }, plugins: [ new HtmlWwebpackPlugin ({ template: "src/index.html" , }), ], }; 次に manifest.json を用意します。manifest.json は、そのアプリがどういったものか、また、インストールした時にどのように振る舞うかをブラウザに伝えるための設定ファイルになります。 https://app-manifest.firebaseapp.com/ のようなサービスで manifest.json とアイコンを各種サイズ自動生成できるので、今回はこのサービスで生成します。 { "name" : "badging-api-playground" , "short_name" : "badge" , "theme_color" : "#5B5CFD" , "background_color" : "#5B5CFD" , "display" : "standalone" , "orientation" : "portrait" , "prefer_related_applications" : false , "Scope" : "/" , "start_url" : "/" , "icons" : [ { "src" : "images/icons/icon-72x72.png" , "sizes" : "72x72" , "type" : "image/png" }, { "src" : "images/icons/icon-96x96.png" , "sizes" : "96x96" , "type" : "image/png" }, { "src" : "images/icons/icon-128x128.png" , "sizes" : "128x128" , "type" : "image/png" }, { "src" : "images/icons/icon-144x144.png" , "sizes" : "144x144" , "type" : "image/png" }, …. ], "splash_pages" : null } webpack.config.js の方に manifest.json をローカルサーバで配信されるように設定を追加しておきます。 const path = require('path') const HtmlWwebpackPlugin = require('html-webpack-plugin') + const CopyPlugin = require('copy-webpack-plugin') module.exports = { …. plugins: [ …. + new CopyPlugin([ + { + from: 'src/manifest.json', + to: '', + }, + { + from: 'src/images/icons', + to: 'images/icons/' + }, + ]), ], } ここまでで Chrome の Application タブから manifest.json が認識されいてることが確認できますが、インストール可能な状態にはなっていません。 アプリをインストール可能な状態にするには いくつかの基準 があり、service worker が必要になります。今回は Workbox の webpack プラグインで対応します。 yarn add --dev workbox-webpack-plugin workbox には GenerateSW と injectManifest の 2 つのモードがあり、今回はどちらでも問題ないかと思いますが injectManifest モードを利用します。 const path = require('path') const HtmlWwebpackPlugin = require('html-webpack-plugin') const CopyPlugin = require('copy-webpack-plugin') + const { InjectManifest } = require('workbox-webpack-plugin') module.exports = { …. plugins: [ …. + new InjectManifest({ + swSrc: path.resolve(__dirname, 'src/sw.js'), + }), ], } app.js の方で service worker の登録がされるように記述しておきます。 if ( "serviceWorker" in navigator ) { window . addEventListener ( "load" , () => { navigator . serviceWorker . register ( "./sw.js" ) . then (( res ) => { console . log ( res ); }) . catch (( err ) => { console . error ( err ); }); }); } service worker の対応が済むとインストール可能なアプリの基準を満たすので、Chrome76 ではアドレスバーにオムニボックスが表示され、そこからインストールが可能になっています。 インストールすると Launchpad にアプリアイコンが表示されたので、実際に Badge API を試してみます。 window.ExperimentalBadge.set() を呼び出すと、フラグとしてバッジがつきます。 window.ExperimentalBadge.set(1) のように引数に数値を入れて呼び出すと、バッジは数字が入った状態で表示されます。 window.ExperimentalBadge.clear() でバッジがクリアされ、元のアプリアイコンだけの状態に戻ります。 非常に簡単ではありますが、このようにしてウェブアプリのアイコンにバッジをつけられることが確認できました。 なお、このサンプルプロジェクトは https://github.com/makotot/badging-api-playground にあげてあります。 まとめ 近い将来正式リリースされる可能性が高い API を試すことで、今後ウェブアプリでどのようなことが実現可能になっていくかの一端を垣間見ることができました。 API 自体が Origin Trial の段階で、ブラウザのタブの favicon 上やブックマークアイコン上に表示したいケースであったり、バッジはどこまでの範囲で適用するべきかのスコープの問題であったり、最終的にどのような形に仕様が整理されるかまだ明確ではない部分もあります。 最終的にどのように課題が解決されていくか注目したいと思います。