WWDC Quick Look 💓 By SwiftGGTeam
What's new for web developers

What's new for web developers

元の動画を見る

ハイライト

Safari 13.1 および Safari 14 では、Web 開発者が Web アニメーション、ResizeObserver、非同期クリップボード、CSS シャドウ パーツ、WebP、HDR メディア、最新の JavaScript 構文、App Clip Web サイト バナーを追加できるようになり、Web サイト、ホーム画面 Web アプリ、および埋め込み WebKit コンテンツをネイティブ プラットフォーム エクスペリエンスに近づけることができます。

主要内容

Web 開発者の日常的な問題は、ブラウザー、ホーム画面 Web アプリ、およびアプリ内 WebView の同じページ セットのパフォーマンスの一貫性のなさから発生することがよくあります。 2020 年のセッションは当初から相互運用性に焦点を当てていました。Safari は今年、Service Worker、XHR + Fetch、ポインタ イベント、CSS、SVG、WebAssembly などの領域をカバーする 140,000 件の新しい Web プラットフォーム テストに合格しました。

パフォーマンスも表裏一体です。 Safari 14 では、未訪問の Web サイトを開く速度が 13%、最近アクセスした Web ページを開く速度が 42%、アドレス バーが最近アクセスした Web ページを開く速度が 52% 速くなります。インスタント バックではより多くのページをキャッシュでき、スクロールの CPU 使用率が 3 分の 1 に削減され、IndexedDB の操作が最大 10 倍高速になります。まずページが高速になり、その後、後続の API でより多くのインタラクションを処理できる余地が生まれます。

その後、Apple はアップデートを複数の行に分割しました。Web API により、ページでアニメーションの制御、要素のサイズの監視、クリップボードへのアクセス、コンポーネントのカプセル化が可能になります。 CSS の更新により、タイポグラフィ、フォント、セレクターが大規模サイトのニーズに近づきます。メディアは完全な WebP、HDR、リモート再生、ピクチャ イン ピクチャ、および HLS メタデータを更新します。 JavaScript の更新により、BigInt、null 値のマージ、オプションのチェーン、論理割り当て、パブリック クラス フィールド、およびreplaceAll

これは単一のフレームワークの発表イベントではありません。これは、Safari と WebKit の移行チェックリストに似ています。まず、ポリフィル、ライブラリ、またはプラットフォーム固有の機能でサポートされているページの部分を見つけて、それらを標準 Web API に 1 つずつ置き換えます。既存の Web サイトの場合、最も実用的な利点は、作成する互換性コードの量を減らし、同時に Safari、iOS、iPadOS、macOS でのエクスペリエンスを統合できることです。

詳細

1. Web API はページレベルの応答からコンポーネントレベルの応答に移行します

(04:22) Web アニメーション API は Safari 13.1 で利用できます。これにより、要素プロパティのセットを手動で変更することなく、JavaScript で CSS アニメーションとトランジションを直接作成および制御できるようになります。セッションの例は、WebKit ロゴをクリックしたときにコンパス ポインターを再度回転させることです。

// Web Animations API Code Example

let needle = document.getElementById("needle");
let logo = document.getElementById("logo");
logo.addEventListener("click", () => {
    needle.animate({
        transform: [
            "rotateX(35deg) rotateZ(13deg)",
            "rotateX(35deg) rotateZ(733deg)",
        ],
        easing: ["ease-out"],
    }, 800);
});

キーポイント:

  • getElementById("needle")そしてgetElementById("logo")アニメーションによって制御される要素とクリックをトリガーする要素をそれぞれ取得します。
  • addEventListener("click", ...)アニメーションを実際のユーザー インタラクションに結び付けます。
  • needle.animate(...)から直接記述されたキーフレーム オブジェクトと継続時間を受け取ります。transform別の人にtransform変化します。
  • easing: ["ease-out"]スピンの始まりを速くし、終わりをソフトにします。
  • 800アニメーションの継続時間 (ミリ秒単位) です。

(06:43) ResizeObserver は、もう 1 つの一般的な問題点を解決します。コンポーネントは、ビューポートの変更によって狭くなるだけでなく、エディター、サイドバー、または子要素の変更によってサイズが変わる可能性もあります。 Safari 13.1 でサポートされると、ページはコンテナーの幅を監視し、コンテナーの状態に応じて CSS クラスを切り替えることができます。

// Resize Observer Example

let formatPanelObserver = new ResizeObserver((entries) => {
    entries.forEach((entry) => {
        let container = entry.target;
        container.classList.toggle("small", entry.contentRect.width < 175);
   }
});

formatPanelObserver.observe(document.getElementById("format-panel"));

キーポイント:

  • new ResizeObserver(...)コールバックが変更エントリを受け取るサイズ オブザーバーを作成します。
  • entries.forEach(...)サイズを変更する要素を 1 つずつ処理します。
  • entry.targetコンテナが監視されています。
  • entry.contentRect.width < 175コンテナ自体の幅を使用して、コンテナが小さいサイズの状態に入ったかどうかを判断します。
  • classList.toggle("small", ...)幅判定結果をCSSに同期します。
  • observe(document.getElementById("format-panel"))実際に表示される書式設定ツールバーを指定します。

(08:22) 非同期クリップボード API は Safari 13.1 で利用できます。システム クリップボードを非同期に読み書きできるため、クリップボード アクセス中にページがブロックされるのを防ぎます。プレーン テキストのショートカット メソッドがあり、呼び出しにはセキュリティ コンテキストとユーザーの対話も必要です。

// Programmatic copy
copyButtonElement.addEventListener("click", (event) => {
    navigator.clipboard.writeText("Plain text to copy.").then(() => {
       // Successful copy
    }, () => {
       // Copy failed
    });
});

// Programmatic paste
pasteButtonElement.addEventListener("click", (event) => {
    navigator.clipboard.readText().then((clipText) => {
        document.querySelector(".editor").innerText += clipText);
    });
});

キーポイント:

  • ボタン上にコピー&ペーストが配置されますclickユーザー対話要件を満たすハンドラー。
  • navigator.clipboard.writeText(...)プレーンテキストを書きます。
  • then2 つのコールバックは、コピーの成功と失敗をそれぞれ処理します。
  • navigator.clipboard.readText()プレーンテキストのクリップボードの内容を読み取ります。
  • document.querySelector(".editor").innerText += clipText読み取ったテキストをエディタに追加します。

2. Web コンポーネントは制御可能な外部スタイル エントリを獲得します

(10:36) Safari は長い間 Web コンポーネントをサポートしてきました。 2020 年のアップデートの焦点は、コンポーネント作成者とページ作成者の役割分担をより明確にすることです。コンポーネントの作成者は内部構造に責任を負い、ページの作成者は明示的に公開されている部分のスタイルのみを設定します。

let template = document.getElementById("format-button");
window.customElements.define(template.id, class extends HTMLElement {
    constructor() {
        super();

        this.attachShadow({mode: "open"});
        let newButtonElement = template.content.cloneNode(true);

        let parts = newButtonElement.querySelectorAll("span");
        parts[0].textContent = this.getAttribute("data-icon");
        parts[1].textContent = this.textContent;

        this.shadowRoot.appendChild(newButtonElement);
        this.addEventListener("click", this.handleClick.bind(this));
    }
});

キーポイント:

  • template.idカスタム要素の登録名として使用されます。
  • コンポーネントクラスの継承HTMLElement、最初にコンストラクターを呼び出しますsuper()
  • attachShadow({mode: "open"})シャドウルートを作成します。
  • template.content.cloneNode(true)テンプレートの内容をコピーします。
  • querySelectorAll("span")アイコンとラベルの入力可能な 2 つの位置を見つけます。
  • getAttribute("data-icon")そしてthis.textContentページ マークアップ内のデータをコンポーネントに配置します。
  • appendChild処理された DOM フラグメントをシャドウ ルートに置きます。
  • 最後の行は、クリック イベントをコンポーネント自体にバインドします。handleClick

12:30)CSS Shadow Parts 让组件作者把可样式化的内部节点用 partそれをマークしてください。ページは完全な Shadow DOM 構造を知る必要はなく、これらの名前付きエントリのみに依存します。

<template id="format-button">
    <button class="format">
        <span part="icon" class="icon"></span>
        <span part="label" class="label"></span>
    </button>
</template>

キーポイント:

  • <template id="format-button">まだコンポーネントテンプレートです。
  • part="icon"ページ作成者が個別にスタイルを設定できるようにアイコン領域を公開します。
  • part="label"テキスト領域を公開します。
  • 内部ボタン構造はコンポーネントによって引き続き保持され、ページ作成者はコンポーネントによって公開されるスタイル ポイントのみに触れます。

(12:38) ページの作成者はその後、::part(...)これらのパブリック ウィジェットを選択して、さまざまな書式設定ボタンに視覚的な手がかりを追加します。

#bold::part(icon) {
    color: var(--formatting-button-icon-color);
    font-weight: bold;
}

#italic::part(icon) {
    color: var(--formatting-button-icon-color);
    font-style: italic;
}

#underline::part(icon) {
    color: var(--formatting-button-icon-color);
    text-decoration: underline;
}

キーポイント:

  • #bold::part(icon)太字ボタンの公開されたアイコン ウィジェットのみをスタイル設定します。
  • var(--formatting-button-icon-color)引き続きページのテーマによって色を制御します。
  • font-weight: boldfont-style: italictext-decoration: underlineボタンの意味を個別にマップします。
  • これらのルールでは、ページ作成者がコンポーネント内の完全な DOM に侵入する必要はありません。

3. CSS の更新はフォント、改行、セレクターの複雑さに重点を置いています

(14:32) WebKit はシステム フォント ファミリを追加します。system-uiプラットフォームに適した UI フォントにマップします。ui-serifニューヨークに相当する、ui-monospaceSFモノに対応し、ui-roundedSF Roundedに対応します。 Web アプリをより自然に、システム インターフェイスに近づけることができます。

font-family: system-ui;
font-family: ui-sans-serif;
font-family: ui-serif;
font-family: ui-monospace;
font-family: ui-rounded;

キーポイント:

  • system-uiこれは、ユニバーサル システム UI フォント エントリです。
  • ui-sans-serifApple プラットフォームでは San Francisco などのインターフェイス フォントを使用します。
  • ui-serifコンテンツ領域での使用に適したシステムセリフフォント。
  • ui-monospaceコードや等幅コンテンツに適しています。
  • ui-rounded丸みを帯びたフォント スタイルが必要なインターフェイスに適しています。

16:43line-break: anywhere狭いコンテナ内で長いテクニカル文字列を処理するために使用されます。オーバーフローする前の文字位置で改行できるため、API 名、コマンド、または長い識別子によってレイアウトが崩れるのを防ぎます。

code {
    line-break: anywhere;
}

キーポイント:

  • ルールは直接作用しますcode要素について。
  • line-break: anywhere改行をより積極的に検索できるようになります。
  • トランスクリプトのシナリオは、Web Inspector コマンド ライン API ドキュメントの長い構文により、空行とリスト項目の水平オーバーフローが発生するというものです。

18:02:is()リピートセレクターを短くします。セッションでは、タイトルが隣接している場合に上部マージンを削除する例を使用します。もともと、大量のh1 + h2h1 + h3組み合わせをマージできるようになりました。

h1, h2, h3, h4, h5, h6 {
    margin-top: 3em;
}

:is(h1, h2, h3, h4, h5, h6) + :is(h1, h2, h3, h4, h5, h6) {
    margin-top: 0;
}

キーポイント:

  • 最初のルールは、デフォルトの上部スペースをすべての見出しに追加します。
  • :is(h1, h2, h3, h4, h5, h6)あらゆるレベルのタイトルに一致します。
  • 真ん中+前のタイトルの直後に次のタイトルが続くことを示します。
  • 2 番目のルールは、連続するタイトル間の上部の間隔をゼロにします。

19:07:where()マッチング方法は似ていますが、マッチング結果の特異性は常にゼロです。これは、デフォルトのスタイルを記述し、後続のルールを簡単にオーバーライドできるようにするのに適しています。

:where(.intro, .pullquote, #hero) + p {
    text-transform: uppercase;
}
h2 + p,
h3 + p,
h4 + p,
h5 + p,
h6 + p {
    text-transform: none;
}

キーポイント:

  • :where(.intro, .pullquote, #hero) + pこれらの要素に続く段落と一致します。
  • :where()自身の特異性をゼロに戻します。
  • フォローアップh2 + p到着h6 + pルールは、以前のデフォルトの大文字をオーバーライドできます。
  • これで解決しました:is()計算には最も高い特異性が含まれるため、カバーすることが困難な状況。

4. メディアの更新には、画像形式、レイアウトの安定性、ビデオ制御が含まれます

(19:53) Safari 14 と iOS 14 は WebP をサポートします。 WebP は、JPEG に近い非可逆圧縮、PNG に似た可逆圧縮を提供でき、透明性とアニメーションもサポートします。着陸時に使用可能picture段階的なフォールバックを実行します。

<picture>
  <source srcset="example.webp" type="image/webp">
  <img src="example.jpg" alt="Example Image">
</picture>

キーポイント:

  • <picture>ブラウザーに複数のリソース候補の中から利用可能な形式を選択させます。
  • <source type="image/webp">WebP バージョンが利用可能です。
  • <img src="example.jpg">これは、WebP がサポートされていない場合のフォールバックです。
  • トランスクリプトによって提供される同じ品質の例では、WebP 非可逆画像は JPEG と比較して 41% 節約され、可逆画像は PNG と比較して 33% 節約されます。

(21:19) Safari 13.1 および iOS 13.4 の WebKit は、widthそしてheightプロパティ計算のデフォルトのアスペクト比。開発者がサイズを追加すると、ブラウザーは画像が読み込まれる前にスペースを予約できるため、レイアウトのジッターが軽減されます。

<img src="MexicoCity.png" width="560" height="747">

キーポイント:

  • src画像リソースを指します。
  • width="560"そしてheight="747"オリジナルサイズでご利用いただけます。
  • WebKit は、これら 2 つのプロパティを使用してデフォルトのアスペクト比を計算します。
  • 画像がダウンロードされていない場合でも、ページは適切なスペースを保持できます。

(22:42) macOS の Safari 14 は、Web ページでの HDR ビデオをサポートします。開発者は、CSS メディア クエリまたは JavaScript を使用して、ハイ ダイナミック レンジの表示機能を検出し、拡張コンテンツを配信できます。

<style>
@media only screen (dynamic-range: high) {
    /* HDR-only CSS rules */
}
</style>

<script>
if (window.matchMedia("dynamic-range: high")) {
    // HDR-specific JavaScript
}
</script>

キーポイント:

  • @media only screen (dynamic-range: high)スタイルを HDR 表示シーンに限定します。
  • JavaScript サイドパスwindow.matchMedia("dynamic-range: high")同様のテストを実行します。
  • Transcript の提案は、段階的な拡張です。HDR 機能が利用可能な場合は対応するコンテンツを提供し、HDR 機能が利用できない場合は通常のエクスペリエンスを維持します。

(23:19) リモート再生 API は、カスタム Web メディア プレーヤーに標準のリモート再生入り口を提供します。接続されているテレビ、スピーカー、AirPlay デバイスにオーディオまたはビデオを送信できます。

<video id="videoElement" src="https://site.example/video.mp4"></video>
<button id="deviceButton">Send video to a remote device</button>

<script>
    let videoElement = document.getElementById("videoElement");
    let deviceButton = document.getElementById("deviceButton");
    deviceButton.addEventListener("click", (event) => {
        videoElement.remote.prompt().then(updateRemotePlaybackState);
    });
</script>

キーポイント:

  • <video>リモートで再生されるメディア要素です。
  • <button>カスタムプレーヤーのデバイス選択ボタンです。
  • getElementByIdビデオとボタンをそれぞれ取得します。
  • ボタンをクリックした後に呼び出されますvideoElement.remote.prompt()デバイスの選択プロセスを開きます。
  • then(updateRemotePlaybackState)選択結果が返された後、再生ステータスを更新します。

5. 新しい JavaScript 構文により、防御的な定型コードが削減されます

(27:11) Safari 14 は BigInt をサポートします。これは、暗号化でよく見られる、JavaScript の安全な最大整数を超える整数のシナリオで使用されます。特別な注意事項: セッション操作を通常の数値と混合したり、直接使用したりすることはできません。JSON.stringifyシリアル化を行います。

let bigInt = BigInt(Number.MAX_SAFE_INTEGER);
// 9007199254740991n

console.log(8n / 2n);
// 4n

console.log(9n / 2n);
// 4n

キーポイント:

  • BigInt(Number.MAX_SAFE_INTEGER)BigInt 値を作成します。
  • 出力内nBigInt リテラルを表します。
  • 8n / 2n得る4n
  • 9n / 2nも得ます4nBigInt の除算では小数部分が切り捨てられるためです。

(28:02) null 値合体演算子は以下をチェックします。nullそしてundefined。それは保持しますfalse、空の文字列、および0このタイプの有効な値は、フォーム、プロファイル、構成オブジェクトの処理に適しています。

class Person {
    constructor(firstName, lastName, age) {
        this.firstName = firstName ?? "Unknown";
        this.lastName = lastName ?? "Unknown";
        this.age = age ?? NaN;
   }
}

console.log(new Person());
// { firstName: "Unknown", lastName: "Unknown", age: NaN }

console.log(new Person(false, false, true));
// { firstName: false, lastName: false, age: true }

console.log(new Person("John", "", 0));
// { firstName: "John", lastName: "", age: 0 }

console.log(new Person("John", "Appleseed", 42));
// { firstName: "John", lastName: "Appleseed", age: 42 }

キーポイント:

  • コンストラクターが受け取るfirstNamelastNameそしてage
  • ??左側にあるのは、nullまたはundefined右側のデフォルト値のみを使用してください。
  • new Person()デフォルトの名前を取得し、NaN年。
  • false、空の文字列、0は保持され、誤って交換されることはありません。

(29:41) オプションの連鎖演算子を使用すると、プロパティ、インデックス、およびメソッド アクセスであまり明示的ではないガードを作成できます。次の登録関数は、存在しない可能性のあるものに直接アクセスします。person

class Person {
    constructor(firstName, lastName, age) {
        this.firstName = firstName ?? "Unknown";
        this.lastName = lastName ?? "Unknown";
        this.age = age ?? NaN;
        this.name = { firstName: this.firstName, lastName: this.lastName };
  }
}

function register(person) {
    // With optional chaining
    console.log(person?.name.firstName);
}

register(new Person());
􀆊 undefined

register(new Person("John", "Appleseed"));
􀆊 "John"

キーポイント:

  • Personコンストラクターは、引き続き null マージを使用してデフォルトのフィールドを提供します。
  • this.nameネストされたモニカを保存します。
  • register(person)内部で使用person?.name.firstNameネストされたプロパティにアクセスします。
  • register(new Person())安全に輸出できるundefined
  • 完全な名前が渡された場合、出力"John"

(30:52) 論理代入演算子は、チェックと代入を組み合わせたものです。セッション用??=左側にのみ次のように表示されますnullまたはundefinedデフォルトの内容が書き込まれます。

a &&= b // and assignment operator
a ||= b // or assignment operator
a ??= b // nullish assignment operator

// Nullish coalescing approach
element.innerHTML = element.innerHTML ?? "Hello World!"

// Logical assignment operator
element.innerHTML ??= "Hello World!"

キーポイント:

  • &&=||=??=それぞれ論理 AND、論理 OR、NULL 値のマージ割り当てに対応します。
  • 通常のnull値マージ書き込みメソッドが書き換えられますelement.innerHTML割り当て。
  • element.innerHTML ??= "Hello World!"デフォルトの文字列は、現在の値が null の場合にのみ書き込まれます。
  • トランスクリプト 左側の式は 1 回だけ評価されることを強調します。

重要ポイント

  • コンポーネントに適応したコメント エディターを作成: ツールバーがエディター コンテナーの幅に応じてテキスト ラベルを自動的に折りたたむようにします。実行する価値がある理由: ResizeObserver は要素自体のサイズを監視し、グローバル ウィンドウ幅に依存しません。開始方法: エディターのツールバーのコンテナーを観察し、しきい値を下回ったときにコンテナーを切り替えます。smallクラスを作成し、CSS を使用してラベルを非表示にします。

  • 安全なリッチ テキストの貼り付けボタンをコンテンツ サイトに追加: ユーザーがトリガーした貼り付けエントリを CMS、フォーラム、またはナレッジ ベース エディターに追加します。実行する価値がある理由: Async Clipboard API はクリップボードを非同期に読み取ることができ、トランスクリプトには、画像やリッチ テキストなどの複数のアイテム タイプがサポートされていることも示されています。開始方法: まずは使ってみるreadText()プレーン テキスト パスを作成し、リッチ HTML を明示的なボタン インタラクションに貼り付けます。

  • デザイン システム コンポーネントをテーマ設定可能な Web コンポーネントに開く: 内部構造はコンポーネントによって維持され、ビジネス ページは調整されるだけです。iconlabelその他の公共部分。実行する価値がある理由: CSS シャドウ パーツを使用すると、ページ作成者がシャドウ DOM の詳細に依存することなく、コンポーネント作成者がスタイル可能な境界を宣言できます。開始方法: テンプレート内にテーマ対応ノードを追加しますpart、次にページの例を提供します::part(...)ルール。

  • 画像を多用するページの読み込みバウンスとボリュームを削減: フォト アルバム、製品リスト、記事の表紙フローに適しています。実行する価値がある理由: WebP は画像サイズの縮小をサポートしています。widthそしてheightプロパティは、WebKit に画像用のスペースを予約するように指示します。開始方法: 画像用に 2 セットの WebP リソースと JPEG リソースを生成し、次を使用します。picture出力形式のフォールバック、およびimgサイズ属性を保持します。

  • カスタム ビデオ プレーヤーのシステム メディア エントリを完了します: リモート再生ボタンとピクチャー イン ピクチャー ボタンを教育、会議の再生、またはライブ ブロードキャスト サイトに追加します。実行する価値がある理由: Remote Playback API と Picture in Picture API はどちらもユーザーの操作を必要とするため、プレーヤー コントロールに組み込むのに適しています。始め方:まず与える<video>カスタムボタンを作成して個別に呼び出すremote.prompt()そしてrequestPictureInPicture()

関連セッション

  • Safari Web Extensions について — 10663 最後に、引き続き Safari Web Extensions を表示することをお勧めします。このセッションでは、拡張機能の作成、移行、リリースのプロセスについて説明します。
  • Web Inspector の新機能 - 10663 Web Inspector のアニメーションとデバッグ機能については何度も言及されていますが、2020 年のツールの更新についてはさらに詳しく説明されています。
  • WKWebView の機能強化をご覧ください — 10663 Web サイトと WebKit コンテンツについては、アプリ内の WKWebView のスクリプト、エクスポート、およびプライバシー機能について引き続き説明します。
  • Web 用の Face ID と Touch ID について - 10663 Click to Web Authentication API to support Face ID と Touch ID、10670 では完全なログイン プロセスについて説明します。
  • AR Quick Look でオンライン ショッピング - 10663 のプラットフォーム統合セクションでは AR Quick Look ショッピング バナーについて言及し、10604 ではこの e コマース エクスペリエンスについて詳しく説明しています。

コメント

GitHub Issues · utterances