面白Web API 100連発
この発表のゴール
現代のウェブブラウザの目指している方向性について紹介する
モダンブラウザで使える最新の面白便利APIを紹介する
ちゃんと仕様に入りそうなもの(Googleの力技で…も含む)
(前半の各ベンダの話はpastak.icon個人の見解を含みます)
次ではない
フロントエンドなんでも相談室
前提知識のコーナー
"WebAPI"とは何を指すのか、標準化について
Ecma InternationalにてECMA-262という規格番号
Array、Number、ES modules、async-await、class、globalThis等々JS自体の言語機能の仕様はここにある
HTML/DOM/CSS
今はwhatwgのLiving Standardなものが標準仕様 JavaScriptに含まれていないFetchやStorage、WebRTCやその他諸々はこっちで策定
FetchはAbort出来るが、PromiseはAbort出来ないのはAbortはFetchの仕様だから
DOM側のPromiseに入れようとしてたが、ESと乖離するので回避された結果
Web Incubator Community Group
W3C内のコミュニティグループの1つ
Web標準に新しいAPIを取り入れるための議論、仕様提案から普及の支援を目的にしたコミュニティ
現在のChromeで使える先進的な多くのAPIはここで議論され草案が作成されている段階のものが多い
2020/8/17現在約140のテーマがある
https://gyazo.com/418ba9ccc441284d55b20f6909a71930 https://wicg.io/
Webブラウザが内包しているHTMLエンジンやJavaScriptエンジンはそれぞれこれらの仕様を基に機能を実装している
V8に実装されたESの機能はnodeでも当然使える
一方で、commonjsのrequireはESで標準化されたりはしなかったし、今ブラウザに載っているStreamsの仕様はwhatwgにある(つまりnodeとは異なる) 現在のWebまたはウェブブラウザの立ち位置について
モダンなウェブブラウザ
ES modulesサポート
ネイティブ async-await
Fetch / ServiceWorker
LocalStorage / IndexedDB
WebRTC
...etc
Appleは正直よく分からないが、あんまりやる気は無さそう
AppStore経済圏
ServiceWorker / PWAへの追随の遅さ
一方でESには積極的に見える
いくつかのAPIのSafariへの搭載は拒否している(後述)
Chrome (/w MSEdge) が結果的にWebが持つ機能と仕様、その実装を牛耳っている
WICGで提案されているものの多くがChromiumチームからの提案でChromiumには載っていて、Origin Trialなどでフィールドレビューされているものが多くある
それらはWebを勿論快適にするだろうとは思うものの、Chromiumの先進的なプロセス分離とサンドボックスを利用したPortalsなど他のブラウザが本当に追随できるのかという点で懐疑的でもある 実際この資料で紹介する最新のAPIも全てChromeに載っているものである…
ううううう
(Googleが)目指している方向性
そのための強力なセキュリティ機構やサンドボックス
モバイルを念頭に置いたウェブサイト表示の最適化
低レイヤー化
WebUSB / Web NFC / Web Bluetooth
コラム: プライバシーとトラッキング
AppleとMozillaはユーザートラッキングの拒否/プライバシー保護に積極的
Safari: ITP / Storageの7日間キャップ
Firefox: ETP (ITPのFx版。ブラックリストに載っているドメインからはUAが取れない等)
Googleはアドセンスやアナリティクスとの上手い兼ね合いを成立させたそう
Cookieの代替を探す方向がありつつも足並みは揃ってない
GDPRのような法律サイドからの圧力もある
3rd Party Cookieの締め出し
Safariは3rd をParty Cookie保存しない
SameSite Cookieの導入
Storage Access API
chrome://flags/#storage-access-api
3rd Partry Cookieに代わる取り組み
本題に入ります
実際にNotaで使えそうなブラウザのAPIをいくつか紹介します
事前アンケートからペンタブレットやCSSなどのキーワードがあったのでその辺からも拾っています
今日は主に既に勧告になっているものやWICGで議論されていて、1つ以上のブラウザで実装されているもの(一部例外を除く)について話します
API紹介のコーナー
お品書き
Async Clipboard
Streams API
Virtual Keyboard
ペンを扱うAPI
content-visibility
Promiseが返ってくるので、非同期に使えるクリップボードAPI
navigator.clipboard.readText()
navigator.clipboard.read()
navigator.clipboard.writeText()
navigator.clipboard.write()
モダンブラウザで共通して書き込めるのは image/pngと text/plain
image/jpgのissue
Streams API chrome.iconfirefox.iconsafari.icon
ReadableStream / WritableStream / TransformStream
ReadableStreamは全てのモダンブラウザで利用可能
例: FetchのResponse.bodyはReadableStream
ReadableStreamは合成可能
Fetchで受けたReadableStreamの前後に新たなReadableStreamを合成する
code: stream-fetch.js
const startFetch = caches.match('/shell-start.cbd594dfa81d.inc');
const endFetch = caches.match('/shell-end.cbd594dfa81d.inc');
const middleFetch = fetch(url).then(response => {
if (!response.ok && response.status != 404) {
return caches.match('/error.ba6821d4f751.inc');
}
return response;
}).catch(err => caches.match('/offline.d989ddb2d13b.inc'));
function pushStream(stream) {
const reader = stream.getReader();
return reader.read().then(function process(result) {
if (result.done) return;
controller.enqueue(result.value);
return reader.read().then(process);
});
}
startFetch
.then(response => pushStream(response.body))
.then(() => middleFetch)
.then(response => pushStream(response.body))
.then(() => endFetch)
.then(response => pushStream(response.body))
.then(() => controller.close());
}
ReadableStreamの作り方
new ReadableStream
code: stream.js
const stream = new ReadableStream({
start(controller) {
interval = setInterval(() => {
let string = randomChars();
controller.enqueue(string);
if (Math.random > 0.95) controller.close()
}, 100);
},
cancel() {
clearInterval(interval);
}
});
WebRTCなどから作る
MediaStreamから変換する
HTMLCanvasElement.captureStream
MediaRecorder
TextEncoderで Uint8Array を得る
Workerとのやり取りに使う(Chrome flag: enable-experimental-web-platform-features)
StreamsをpostMessage出来るようにする目論見がある
https://gyazo.com/f9a6c8a94e409dc54478fb5bbe9560c6
改行区切りとかでWorkerにメッセージを送り続けることが可能
ChromeではFetchのRequest.bodyにもReadableStreamが使えるようになった(Chrome 85b /w flag: enable-experimental-web-platform-features)
HTTPのレイヤで使えるので、Proxyとかも考えるとちょっと楽
Virtual Keyboard
主にSurface上のMSEdgeを意識してVirtual Keyboardを適切に扱うためのAPI提案
上手くいくとiOSのキーボードも同じように扱える期待は高い
https://gyazo.com/942243619126420daf518741e7de6c97
こういうことが出来るようになる予定
code: sample.js
window.navigator.virtualKeyboard.overlaysContent = true;
navigator.virtualKeyboard.addEventListener("geometrychange", (evt) => {
let { width, height } = evt.boundingRect;
if( width !== 0 && height !== 0 ) {
console.log('virtual keyboard is now visible!')
}
document.querySelector(".search-box").style.bottom = ${height + 15}px;
});
code: sample.css
.search-box {
position: absolute;
bottom: env(keyboard-inset-bottom);
}
ペンを扱うAPI chrome.iconfirefox.iconsafari.icon
TouchEvent.touches: Touch[]
touch.touchType: 種類が取れる
direct, stylus
Touch.azimuthAngle / Touch.altitudeAngle: 向き
https://gyazo.com/c9409b0e09515713f828e7aaa27867e2
Touch.force: 圧力(0 - 1) float
PointerEvent.touchType === 'pen': ペンかどうか
touch, mouse
PointerEvent.pressure: 圧力(0 - 1) float
PointerEvent.twist: 角度(0 - 359)
Surface Pro penやApple Pencilなどのペン自体のイベントを扱えるようにするAPIの提案
penbuttonclick, penbuttondblclick
penbuttonpressandhold: ボタンが押したままのときは消しゴムにするとか
pendockchange: dockに格納されたらお絵かきのモードを切り替えるとか
Chrome 85より利用可能
https://gyazo.com/96fea1fc34515e08fbb6029edee676ab
content-visibility: autoを指定して要素をchunk分割することでレンダリングを最適化できる
https://gyazo.com/b4e03ce1e1323b1dea6aaf6df40deddc
containのlayout, style, paintが当たってるのと同じになり、画面外のものはsizeも含む
contain-intrinsic-sizeでplaceholderのようにサイズを指定できる
display: none: rendering stateが破棄されるので、再度表示する際には新規にレンダリングするのと同じコストがかかる
visibility: hidden: rendering stateは維持されるが、子要素含めてドキュメント上に残り、またblockスペースは維持される
content-visibility: hidden-matchable
Chrome 85よりflag付きで利用可能
まとめ
ざっと名前だけだと60以上のブラウザで使えるAPIを紹介しました
この中のもののいくつかが全てのモダンブラウザで使えるようになるかは…
モダンブラウザだと色々出来るので積極的に使っていきましょう
Chromeでしか動かないものも多いが…
UAで判別せずにfeature detectionしよう
Slackの#frontendで常に紹介したりしているので覗いてみてください
追記コーナー
ブコメなどでの反応へ返答
"Web API"はGoogle Maps APIなどのようなウェブサービスが提供することでJavaScriptのAPIのことは指さないのではないか
例えば、MDNでもWeb APIsとしてここで紹介したようなJavaScriptやCSSなどで利用可能なAPIの一覧が記載されています。まぁややこしいという意見は受け入れますが、そう呼ばれているので仕方ないですね…