Chrome 73(3/14)にMacOSでのProgressive Web Apps(PWA)対応、ダークモード対応、Signed HTTP Exchangesへの対応などの新機能が追加があり、主要プラットフォームすべてでPWAの実行環境が整う形となりました。


Progressive Web Apps(PWA)とは?

一言でいうと「アプリのようなウェブサイト」のことで、アイコンがあったり、スプラッシュスクリーンがあったり、システム的にはプッシュ通知やオフライン機能が使える部分を併せ持つ「ウェブサイト」でネイティブアプリに近いWebアプリとなります。


App Shellモデルの特徴として、以下があります。
・高速:ロードが速い。Service Workerを使いスムーズに動く。
・プログレッシブ(進歩的):どこでも、どんなデバイスにも対応できる。モダンブラウザーに対応している。
・接続状態に依存しない:オフラインでも、接続環境が悪くても動く。接続が弱かったり不安定だったりする場合でも、接続変更の影響が低減される。
・エンゲージメント:PWAはホーム画面に表示でき、プッシュ通知機能を使えるため、ユーザーの再エンゲージメントする可能性は通常のWebサイトより高い。

実際にPWAに対応したソースを見てみます。

公式サイトより引用

◆App Shell の HTML の例

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>App Shellの例</title>
  <link rel="manifest" href="/manifest.json">
  <title>App Shell</title>
  <link rel="stylesheet" type="text/css" href="styles/inline.css">
</head>
<body>
  <header class="header">
    <h1 class="header__title">App Shell</h1>
  </header>
  <nav class="nav">
  ...
  </nav>
  <main class="main">
  ...
  </main>
  <div class="dialog-container">
  ...
  </div>
  <div class="loader">
    <!-- Show a spinner or placeholders for content -->
  </div>
  <script src="app.js" async></script>
  <script>
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js').then(function(registration) {
      // Registration was successful
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }).catch(function(err) {
      // registration failed 
      console.log('ServiceWorker registration failed: ', err);
    });
  }
  </script>
</body>
</html>
[/info]

◆静的リソースをキャッシュする例(sw.js)
var filesToCache = [
  '/css/styles.css',
  '/js/scripts.js',
  '/images/logo.svg',
  '/offline.html’,
  '/’,
];
self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
  e.waitUntil(
    caches.open(cacheName).then(function(cache) {
      console.log('[ServiceWorker] Caching app shell');
      return cache.addAll(filesToCache);
    })
  );
});
[/info]

ポイントは、
・UIの「骨子」となる HTML と CSSがあり、HTMLにはナビゲーションとコンテンツのプレースホルダが備わっている。
 →インフラストラクチャと UI をデータから切り離している。
・ウェブアプリが開かれたときに、すぐにページのレイアウトのみが表示されるよう、最初の読み込みはできる限りシンプルしている。

 →App Shellに関連したCSSをインライン化することによりロードを高速化することもあるようです。
・ナビゲーションと UI のロジックを処理する外部 JavaScript ファイル(app.js)にIndexed DB などのストレージ メカニズムを使用して、サーバーから取得した情報を表示してローカルで保存するためのコードがある。
・オフライン機能を有効にするためのウェブアプリマニフェストとService Workerをロードしている。
 →Service Worker を使用することで、すべての UI とインフラストラクチャはローカルにキャッシュしている。

ちなみに、ServiceWorkerとは、

Webページの裏側で働く独立したJavaScript環境で、Service Workerが一度Webページからインストールされると、Webページとは独立したライフサイクルの中で動作します。

たとえば、オフライン状態でも、Webページを表示していたタブが閉じていても、必要があればService Workerが作動します。

 

ServiceWorkerについて詳しく知りたい方は、下記を参照してください。
https://developer.mozilla.org/ja/docs/Web/API/ServiceWorker_API/Using_Service_Workers

 

Webアプリも年々進化していき、ユーザにとって利用しやすい環境となってきていますね!

 

今月の帰社日は、『神楽坂 創彩割烹 清水』。

 

古民家を改築した古民家割烹で、店内の雰囲気は非常に良いです。
柑橘系の香りで苦みが印象的な東京クラフトビールが食事と合っていました。
 

本鮪 桜鯛 筍眼張 本山葵 藻塩

 

桜鱒の木の芽利久焼き

 

桜海老と野沢菜の炊き込み飯

 

白子の玉地蒸し

 

久しぶりに落ち着いたひとときを過ごせました。

 

Java 12 (OpenJDK12)の Schedule を見る限り、2019/03/19にリリースを予定されています。

リリース内容を注目してみると
Features
JEP 189:Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)
JEP 230:Microbenchmark Suite
JEP 325:Switch Expressions (Preview)
JEP 334:JVM Constants API
JEP 340:One AArch64 Port, Not Two
JEP 341:Default CDS Archives
JEP 344:Abortable Mixed Collections for G1
JEP 346:Promptly Return Unused Committed Memory from G1

この中でプログラムに直接関係しているのは、JEP 325くらいでしょうか。

■JEP 325:Switch Expressions (Preview)
Switch文が拡張されて、
caseに複数の値を指定が可能になり、アロー構文を使うことでbreakが不要になり可読性が良くなりました。(これはいいですね!)
また、式として使えるようになりました。

[Java 12以前]
int numLetters;
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        numLetters = 6;
        break;
    case TUESDAY:
        numLetters = 7;
        break;
    case THURSDAY:
    case SATURDAY:
        numLetters = 8;
        break;
    case WEDNESDAY:
        numLetters = 9;
        break;
    default:
        throw new IllegalStateException("Wat: " + day);
}

[Java 12以降]
int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};

それ以外のAPIの強化として、

■CompactNumberFormat[javadoc]
大きな数値を、10,000→1万とか10Kで表記する機能です。(どこでつかうんだろう?)
var cnf = NumberFormat.getCompactNumberInstance();
cnf.format(10000); // 1万
cnf.format(10000_0000); // 1億



■Collectors.teeing(Collector, Collector, BiFunction)[javadoc]
ふたつのCollectorの結果を結び付けます。(これは使えるかも?)

例えば、空文字列を省いて①カンマ区切りにして、更に最終的な②要素数を取得する方法ですが、
通常は、1回のStreamでは解決できないが対応できるようになりました。
Streamtream.of("aaa", "", "bbb", "ccc")
    .filter(Predicate.not(String::isEmpty))
        .collect(Collectors.teeing(Collectors.joining(","), Collectors.counting(),Map::entry));
// aaa,bbb,ccc=3

他のAPI追加分が知りたければ、下記を参照して下さい!
http://download.eclipselab.org/jdkdiff/V11/V12/index.html