Medley Developer Blog

株式会社メドレーのエンジニア・デザイナーによるブログです

社内勉強会TechLunchで Badging API について発表しました

みなさん、こんにちは。開発本部のエンジニアの舘野です。先日、社内勉強会「TechLunch」で Badging API について発表したので、その内容を紹介させていただきます。

Badging API とは

Badging API とは、ネイティブアプリのアプリアイコン上に表示されるバッジと同様に、ウェブアプリのアイコン上にバッジを表示することができる Web API です。

 

ネイティブアプリで可能なこと全てをウェブアプリでも可能にすることを目指す、Fugu というプロジェクトで実現に向けて動いている API の1つで、Chrome 73 から Origin Trials として利用可能になっています。Origin Trials とは、試験的に特定の開発者に限定してAPIを利用できるようにする仕組みのことで、正式リリース前にAPIに対する有用なフィードバックを受け取ることができるものです。

 

このAPIの最新の概要や仕様については、 WICGGithubBadging APIのリポジトリを用意しているので、そこで確認することができます。

WICG(The Web Incubator Community Group)は、先進的なウェブ技術について検討するコミュニティグループで、W3Cのグループの1つです。

提案されている API のインターフェースは、現時点(2019/08/14)では以下のようになっています。

 

https://github.com/WICG/badging/blob/master/explainer.md#the-api

 

  • Badgewindowオブジェクトのメンバとして持つ
  • 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)かのいずれかを行う必要があります。

 f:id:medley_inc:20190827173844p:plain

今回はローカル環境で試すだけなので、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が認識されいてることが確認できますが、インストール可能な状態にはなっていません。

f:id:medley_inc:20190826185511p:plain

アプリをインストール可能な状態にするには いくつかの基準 があり、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ではアドレスバーにオムニボックスが表示され、そこからインストールが可能になっています。

f:id:medley_inc:20190826185538p:plain

f:id:medley_inc:20190826185554p:plain

インストールするとLaunchpadにアプリアイコンが表示されたので、実際にBadge APIを試してみます。

window.ExperimentalBadge.set()を呼び出すと、フラグとしてバッジがつきます。

f:id:medley_inc:20190826185622p:plain

window.ExperimentalBadge.set(1)のように引数に数値を入れて呼び出すと、バッジは数字が入った状態で表示されます。

f:id:medley_inc:20190826185641p:plain

window.ExperimentalBadge.clear()でバッジがクリアされ、元のアプリアイコンだけの状態に戻ります。

f:id:medley_inc:20190826185653p:plain

非常に簡単ではありますが、このようにしてウェブアプリのアイコンにバッジをつけられることが確認できました。

なお、このサンプルプロジェクトは https://github.com/makotot/badging-api-playground にあげてあります。

 

まとめ

近い将来正式リリースされる可能性が高いAPIを試すことで、今後ウェブアプリでどのようなことが実現可能になっていくかの一端を垣間見ることができました。

 

API自体がOrigin Trialの段階で、ブラウザのタブのfavicon上やブックマークアイコン上に表示したいケースであったり、バッジはどこまでの範囲で適用するべきかのスコープの問題であったり、最終的にどのような形に仕様が整理されるかまだ明確ではない部分もあります。

 

最終的にどのように課題が解決されていくか注目したいと思います。