Cybozu Frontend Monthly #4

イベント概要

サイボウズフロントエンドマンスリーは、サイボウズ社内で行っているフロントエンド情報共有会「フロントエンドウィークリー」の公開版です。

その月に気になったフロントエンドの情報を、サイボウズのフロントエンドエキスパートチームのメンバーが共有していきます。

このイベントのハッシュタグは #サイボウズフロントエンドマンスリー です。

※フロントエンドウィークリーとは

毎週火曜の 17:00 〜 18:00 で社内向けに行っているフロントエンドの気になる記事を紹介する会です。2016年3月15日から行われています。
ハッシュタグ #サイボウズフロントエンドウィークリー で実況しています。

開催日

2020年10月27日

イベントページ

https://cybozu.connpass.com/event/192820/

配信URL

https://www.youtube.com/watch?v=q6ReR_ClFrg

タイムテーブル

07:50 - 08:00配信開始
08:00 - 08:05オープニング
08:05 - 08:55本編
08:55 - 09:00クロージング

メンバー

ゲスト


紹介記事

Introducing Cloudflare Browser Isolation beta

  • 共有者: @zaki___yama

Cloudflare が Browser Isolation 機能をリリース。 現在はベータ版で、 こちらの waitlist から申し込む必要があります。

記事を一通り読んだ後に気が付きましたが、1 月頃にもこのあたりの話が公式ブログから出てました。
Cloudflare とリモートブラウザー分離
ここで紹介されているものが遂にベータリリースしましたよ、という趣旨のようです。

Browser Isolation とは

ブラウザをエンドユーザーの端末ではなくクラウド上の VM で走らせるサービス。
これ自体は Cloudflare 独自のものではなく、類似のソリューションは以前からもあったようです(知らなかった)。

https://www.proofpoint.com/jp/products/advanced-threat-protection/browser-isolation
https://www.asgent.co.jp/products/web-isolation.html

従来の Browser Isolation の課題

Isolation のアプローチ
  • 多くの Isolation サービスは以下の 2 つのアプローチのいずれかを採用しているが、どちらも欠点がありブラウザの利便性や柔軟性を損ねている

    1. リモートブラウザのウィンドウをキャプチャし、画像としてエンドユーザーに送る
    2. → 遅い。フォームのテキストボックスへの入力など基本的なことを行うのも難しくしている
    3. DOM 再構築。web ページを unpack し、中身を調べ、問題なければ repack してユーザーに送る
    4. → 脅威を見逃したり、多くの場合まだ動作する形での repack に失敗する
ネットワーク

ユーザーの入力をリモートのデータセンターまで送信し、結果をディスプレイに戻すというやり取りが発生する。 ローカルと同じ体験を提供するためにはこれがミリ秒単位で行われる必要がある

Cloudflare Browser Isolation での解決

Isolation のアプローチ

↑ で挙げた 1, 2 のいずれでもないアプローチ方式を採用。 画像のピクセル情報を送信する代わりに、ブラウザの描画コマンドを送信する。

このあたりは冒頭にも書いた日本語の方のブログが詳しい。

(画像は記事より引用: https://blog.cloudflare.com/content/images/2020/01/image5-10.png)

S2 Systems NVR テクノロジーは、リモート Chromium ブラウザーの Skia 描画コマンド ❶ をインターセプトし、トークン化して圧縮してから、ネットワーク経由で暗号化して ❷、ユーザーエンドポイントのデスクトップ上またはモバイルデバイス上でローカルで実行されている HTML5 対応 Web ブラウザー ❸(Chrome、Firefox、Safari など)に送信します。NVR によってキャプチャされた Skia API コマンドは、ラスタライズ化される前のものです。つまり、非常にコンパクトです。

ネットワーク

Cloudflare が所有している世界 200 都市に広がるデータセンターを利用してこのソリューションを提供するので、ミリ秒単位での通信が可能。


LibSass is Deprecated

  • 共有者: @b4h0_c4t

LibSass が非推奨になった話。

重要なポイントは以下の通り

  • 新しいプロジェクトではDartSassを推奨
  • 既存のプロジェクトも計画的な DartSass への移行を推奨
  • 今後新機能に対応する予定はない
  • Node Sass も含め、主要なバグやセキュリティ・最新の Node.js との互換性対応は無期限で継続される。

現状の実装では、min() max()などの一部 PlainCSS や Sass module system をサポートしておらず、DartSass との兼ね合いを鑑みて LibSass 側を非推奨にしたらしい。

無期限にメンテナンスを続けると言っているが、コアチーム側は強く DartSass への移行を強調しているため、使っている人は早めに移行を始めた方が良さそう。


Svelte Summit | Rich Harris: Futuristic Web Development

  • 共有者: @toshi__toma

10/18 に Svelte のオンラインカンファレンス「Svelte Summit」が開催された。 その中の「Rich Harris: Futuristic Web Development」が面白かったので紹介。

Rich Harris: Futuristic Web Development

  • 主に Svelte の今後の開発環境についての話
  • ※ 公式の発表でもないし、保証するわけではない
  • Svelte ベースの Web アプリケーションフレームワーク Sapper(React でいう Next.js)の v1 がリリースされることはない
  • Sapper の代わりに、 @sveltejs/kitを開発してる(まだプライベートリポジトリ)
  • 途中からは、@sveltejs/kit を使ったアプリ開発のデモ
  • Rollup ではなく、Snowpackを使った開発になる
  • adapter という仕組みがあって、それでビルドの出力を変更できる

    • node, static, Netlify、その他メジャーな Faas をサポートする予定

あと、今月から Monthly で新機能やバグフィックスなどを紹介する "What's new in Svelte" シリーズが始まった。

What's new in Svelte: October 2020


React v17.0.1

  • 共有者: @koh110

アップデート内容としては IE11 でクラッシュする問題を修正しただけです。

Ref: https://github.com/facebook/react/pull/20071

Array.fill は IE11 で動かないのでその修正。

- return new Array(TotalLanes).fill(initial);
+ const laneMap = [];
+ for (let i = 0; i < TotalLanes; i++) {
+   laneMap.push(initial);
+ }
+ return laneMap;

面白いと思ったのは、配列の初期化方法によってパフォーマンスが変わるので new Array(length) を避けたこと。 https://v8.dev/blog/elements-kinds#avoid-creating-holes

// これはよくない
const array = new Array(3);
array[0] = "a";
array[1] = "b";
array[2] = "c";

// 初期化するならこのほうがよい
const array = ["a", "b", "c"];

// 初期化する要素数がわからないときは push を使う
const array = [];
array.push(someValue);
array.push(someOtherValue);

https://v8.dev/blog/elements-kinds#packed-vs.-holey-kinds

  • 配列の要素には PACKED_ELEMENTS(連続する要素)HOLEY_ELEMENTS(穴あき要素) がある
  • PACKED のほうが HOLEY より配列操作が効率的
  • 途中で配列に要素を飛ばし挿入すると PACKED から HOLEY になる(不可逆)

知らなかったので記事中にある配列のアクセス方法などをそれぞれ試してみた。通常の使い方であればほぼ誤差レベル。(記事中にも記載がある) https://gist.github.com/koh110/13e3e8432b0abad9501b551e46e30b3f

(記事中では途中に重い if 文などがある場合にパフォーマンス issue が出るらしい。検証コードがうまく書けない)

検証コードを見る限りでは new Array().map でよさそうに見えてしまうが、なにか見落としているような気がする。

Ref:

PACKED_ELEMENTS について Holy Array について babel での同様の議論

new Array(n) は常に HOLEY_ELEMENTS を生成するように読み取れる。

初期生成時の速度については触れていないので、途中の配列操作があった場合に PACKED_ELEMENTS のままにできるようにしたいという意味合いなら納得できる。 TypeScript じゃないので生成された配列の使い方を強制できないので、効果がどこまであるかと考えると初期生成のコストで切り分ける余地はありな気がする。(今回は長さ 31 の固定長配列なので多分誤差)

メモリの使用量に差が出るかと思ったけど、fill のほうが少し少ない(誤差程度) https://gist.github.com/koh110/4c77dbebccfc074ac7bb1764423d6803

V8 の開発者曰く心配するほどの差ではない。

「Don't optimize for V8, let V8 optimize for you!」

Ref: PACKED の確認の仕方

本筋とはずれるが、Holy Array についてのブログにあるように中身が実質的に DICTIONARY_ELEMENTS になってしまうような配列の場合、JSON.stringify でメモリ使用が跳ね上がってしまうのはうっかりやってしまいそうで怖いですよね。

const arr = []
arra[0] = 0
arra[1] = 1
arra[2] = 2
JSON.stringify(arr)
// [0,1,2]

arr[9999] = 'evil'
JSON.stringify(arr)

// [0,1,2,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null...

Chrome87 CSS 論理プロパティの追加

  • 共有者: @narirou

Chrome87 で CSS 論理プロパティのショートハンド記法が使用できるようになりました。

CSS 論理プロパティ(Logical Property)は、読む方向が異なる国際言語に対して利用できる、レイアウト制御の値です。端的にいうと、margin、padding の新しい設定方法です。

これまでの marginpadding は、画面表示の上下右左という概念で出来ていましたが、この設定方法だとm読む方向が異なる言語で異なる CSS を当てる必要が出てきます。

(画像は記事より引用: https://webdev.imgix.net/logical-property-shorthands/block-and-inline-visual.png)

そこで検討されたのが、CSS 論理プロパティです。このプロパティでは、上下左右という概念ではなく、ボックスモデルの読み始め読み終わりをもとに、レイアウトの設定を入れることができます。

p {
  margin-inline-start: 0px;
  margin-inline-end: 0px;
  margin-block-start: 1em;
  margin-block-end: 1em;
}

そして今回、先週リリースされた Chrome87 で、ショートハンド記法が使用できるようになりました。

p {
  margin-block: 1em;
}

現在はサポートされていないブラウザも多いので、本番に出すときはまだ@supports の CSS at-rule を使用して記述する必要があります。 web でこれまで書いてきたレイアウト方法に大きな変化が来るので、特に多言語対応を行っているサイトは認識しておくと良いかと思います。


ブラウザでプッシュ通知許可に制限がかかり、不正な場合サイトにペナルティが与えられます

  • 共有者: @narirou

Web プッシュの通知ダイアログ、様々なサイトで掲出されて鬱陶しいなと思っていましたが、Chromium が対策に乗り出します。

セーフブラウジングをしているのに通知許可を申請したり、通知許可を強要する UI を使用している場合に、不正なサイトのフラグが立てられます。

ブロックされる 30 日前に Search Console 上に通知が届き、対処されない場合は Chromium で通知ダイアログが表示されなくなります。

サイトを管理しているひとは気をつけたほうがいいでしょう。


Node v15.0.0 (Current) | Node.js

  • 共有者: @shisama_

10/20 に Node.js v15 がリリースされました!大きな変更も多いです。

  • npm 7
  • V8 v8.6 ES2021 の機能追加

    • Promise.any and AggregateError
    • String.prototype.replaceAll
    • Logical assignment operators
  • Web Crypto API の追加
  • AbortController の追加
  • EventTarget の追加
  • Unhandled Rejections が発生したときエラーになるように変更(終了ステータスが 1 に変わる)
  • QUIC の実験的実装
  • timers/promises の追加
  • stream/promises の追加
  • require('assert').strict を require('assert/strict') で読み込む
  • require('dns').promises を require('dns/promises') で読み込む
  • file URL の仕様追随

日本語記事


3 things about CSS variables you might not know

  • 共有者: nakajmg
  • CSS variables についてのお話

    • var() で undefined な変数を使用したときどうなるか
    • フォールバックの動作
    • DevTools まわり

などを解説している。

undefined な変数を使用した時

  • undefined な変数を使用しても読み込み/解析/レンダリングを妨げない
  • 変数はカスケーディングされる
  • 継承されるプロパティの場合は継承された値が使われる
  • 継承されないプロパティの場合は初期値が使われる
.my-class {
  border: 1px solid var(--undefined-value);
  color: var(--undefined-value);
}
  • border は継承されないので表示されない
  • color は継承されるので祖先をたどって値を探す

フォールバックの動作

  • var() にはフォールバック機能がある
  • var() は入れ子にできる
color: var(--theme-color, red);
  • --theme-color が見つからなければ red が適用される
  • CSS variables を使ってカスタマイズできるようなコンポーネントに使えるかも?
color: var(--foo, var(--bar, var(--baz, var(--are, var(--you, var(--crazy)))));

DevTools まわり

  • 変数名がオートコンプリートされる
  • var() にマウスオーバーすると最終的な値が確認できる
  • 変数名が色の名前の場合に色見本が表示される

    • その値が色として使われるかどうか関係なく

Meet Face ID and Touch ID for the Web

  • 共有者: pirosikick

WWDC 2020 のMeet Face ID and Touch ID for the webの記事版。動画よりもコード多めで詳細に解説。図は動画のほうが多いので、動画もおすすめ。

  • Web Authn API のオプションと Safari 上の UI がどう紐づくか
  • 仕様と違う点

    • Touch ID/Face ID を使った Web Authn API の呼び出しはユーザージェスチャーが必要
    • 互換性のため、Touch ID/Face ID 以外を使った Web Authn API の呼び出しはユーザージェスチャーが不要
    • ユーザージェスチャーとは
    • touchend, click, doubleclick等のイベントのコールバック内
    • 上記のコールバック内から呼び出した XHR、Fetch API のコールバック内
    • Readable Stream はまだ未対応
  • Apple Anonymous Attestation について

iPhone ユーザーにとってポピュラーな Face ID が Web で使えることで Web Authn の普及が進みそうと思いました。


Webpack 5 release (2020-10-10)

  • 共有者: @__sakito__

参照:Webpack 5 release (2020-10-10)

10/10 に webpack 5 がリリースされました 🎉

webpack 5 のリリースは行われたが、まだバグが多くあり、webpack で使用する loader や plugin は対応が追いついていません。
パッとwebpack 5 関連の Issueを眺めるだけでも、まだ多くの問題があることがわかります。
なので、webpack 5 を使用するのは安全にいきたければ 1,2 ヶ月ほど待ってもよいと思います。 いまはこのバグ対応によりすでに webpack のバージョンは 5.2.0 になっています。

webpack-dev-server

現在の webpack-dev-server は webpack v5 対応のバージョンががまだリリースされてないので、動かないケースが何点かあります。

webpack-cli

webpack v5 対応のためv4 のリリースはされていますが、上記でも書いている通り、webpack dev server と組み合わせるとバグがあります。

webpack cli v4 から webpack-dev-server の起動をwebpack serveコマンドに統合するようになっています。 webpack serve コマンドの案内を促すエラー文の実装

新機能としてwebpack --analyzeコマンドで、webpack-bundle-analyzerを使用して、各モジュールのバンドルサイズを可視化することができるローカルサーバーを立ち上げることができます。便利。

主な変更点

https://webpack.js.org/blog/2020-10-10-webpack-5-release/#major-changes-removals

このような変更点があります。

  • 永続的なキャッシング
  • TS の対応で@types/webpackが不要になり、import { WebpackOptionsNormalized } from 'webpack'; で型を import できるようになった。(ファイル名を webpack.config.ts にする必要がある)
  • Tree Shaking の最適化が入りバンドルサイズ縮小に期待できる
  • CommonJs の Tree Shaking 対応
  • css の chunk が可能になった(MiniCssExtractPlugin使用時にできる)

ここでは特に大きな破壊的変更を 2 つほど紹介します。

Node.js の polyfill を自動で挿入しなくなった

webpack を使用すれば、Node.js のコードをクライアントサイドで使用し、自動で polyfill を挿入してくれていました。

今後 webpack は Web で動作するコードに焦点を当てていくため、Node.js の polyfill がバンドルに含まれ、結果的にバンドルサイズがデカくなくることを望まないようになったので、 自動で polyfill を挿入しなくなります。

polyfill を挿入したい場合はwebpack/node-libs-browserを参照して、自前で挿入する必要があります。 また、クライアントサイドで Node.js に依存したパッケージを使用している場合は、パッケージの対応を待つか、フロントエンド互換のあるパッケージに変更する必要があります。

global,__filename,__dirnameも webpack の設定でデフォルトfalseに変更されるので、使用したい場合は明示的に変更する必要があります。

デフォルトランタイムが一部 ES2015 になった

webpack が生成するコードが一部 ES2015 になったので、明示的に es5 への対応が必要になりました。 browserslist のサポートが含まれたので、browserslist の設定 or webpack の設定を変える、2つの選択肢があります。

  • webpack の設定

webpack.config.js

module.exports = {
  target: ['web','es5']
};
  • browserslist の設定

.browserslistrc

last 1 version
ie >= 11

package.json

  "browserslist": [
    "last 1 version",
    "> 1%",
    "ie >= 11"
  ]

(宣伝) フロントエンドエキスパートチームで WEB+DB PRESS Vol.119 の特集記事を執筆しました

WEB+DB PRESS Vol.119 にサイボウズのフロントエンドエキスパートチームのメンバーで「フロントエンド脱レガシー 長く愛されるプロダクトをさらに改善していくために」というタイトルで特集記事を寄稿しました。

フロントエンドエキスパートチームについて

https://speakerdeck.com/cybozuinsideout/frontendexpert-team