Cybozu Frontend Monthly #7

タイトル画像

イベント概要

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

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

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

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

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

zennのpublicationにてウィークリーのまとめも投稿していますので、ぜひこちらもご覧ください。 https://zenn.dev/p/cybozu_frontend

開催日

2021年01月26日

イベントページ

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

配信URL

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

メンバー


コンテンツ

JavaScript アンケート周り

両方とも 2020 年の流れを把握するのに使えそうです。

State of JS は、ビルドが esbuild や sbowpack、フレームワークは引き続き svelte に興味持ってる人が多かったです。 しかし実際に使用してるものは、webpack などになっており、新しいものはまだプロダクションで使用するには踏み込めない印象。 各項目で色々な人が 2020 年の個人的ベストを紹介してるのが面白かった、changesetsInsomniaRedwoodなど知らないものを知れました。

2020 JavaScript Rising Stars は、あくまでスター数なので State of JS 2020 と見比べて世間がどこに注目しているか照らし合わせるとよさそうです。 各セクションで説明もあるので、なぜスター数が増えたのかもわかりやすいです。


Don’t Use Inverted Color Cues on Toggle Buttons

トグルボタンでボタンの文字色と背景色を反転させた ON・OFF ボタンを作りがちだが、 色のコントラスト比が同じになるのでどちらが ON で OFF なのかわからず誤操作が増えがちなので気をつけなはれや、という内容。 ブログの画像を見ると分かりやすいですが、色の反転の代わりに奥行きで ON/OFF を表現するといいよとのことです。 最近、tailwind.css を使っていて悪い例と同じようなことをしていたので、タイムリーで参考になりました。


Classi にフロントエンドエキスパートチームを作った話

Classi さんがフロントエンドエキスパートチームを作った話。 弊チームを参考にしてくれたとのことで、私達の活動が界隈に影響を与えられていると思うと嬉しいですね。

記事中ではFrontendOpsについて触れており、フロントエンドの運用が開発者だけの関心事ではなく、チーム全員にとって重要であると説明しています。 今後ますますフロントエンドの運用は重要な関心事となっていくと思いますので、弊フロントエンドエキスパートチームとしても真摯に向き合って行きたいです。


Front-End Performance Checklist 2021 — Smashing Magazine

パフォーマンスに関するチェックリストです。
77 個のチェックリストがありますが、長大なので挫折しそうな人はサマライズされている PDF 版 を読んでみて気になるところは記事の方を読んでみるのが良いかと思います。

記事の最後にはQuic Winsとして 1 時間で改善できる 17 個のことを記事中からピックアップされているので、まずはこれからはじめるのも良さそうです。
個人的には「パフォーマンスの文化を作る」が最初に来ているところがいいと思いました。

パフォーマンスに関連する話で今月知ったものもあわせて紹介しておきます。

この記事の中でも CoreWebVitals を使って計測する話があり、DevTools で計測したり、Chrome 拡張を使っている人が多いと思いますが、Chrome 90 からは Experimental ですが Chrome 本体でもメトリクスを常に監視できるようになるようです。
AddyOsmani.com - A Performance Heads-Up Display (HUD) for Chrome

JS のサイズについては、モダンブラウザで使える JS の構文を使うことでバンドルサイズを減らせると紹介されています。
JS のネイティブに置き換えることでどれくらいバンドルサイズを減らせるかをチェックするツールがあるので、試してみるといいかもしれません。
EStimator.dev: the modern JavaScript savings calculator


Agenda for the 80th meeting of Ecma TC39

TC39 の1月のミーティングのアジェンダです。25 日~28 日にかけて行われます。

このミーティングでは多くのプロポーザルについての議論が行われる予定です。

Intl 系(ECMA402)のプロポーザル

新しい構文を追加するプロポーザル

新しい API を追加するプロポーザル

その他

数が多くて全部は紹介しきれないので、僕が個人的に気になったもの、多くの JavaScript 開発者にとって影響が大きそうなもの、かつステージが進みそうなものを紹介していきます。

Class static initilization Blocks for Stage 3

https://github.com/tc39/proposal-class-static-block

これは、クラスのスタティックプロパティの初期化を行うことができるブロックの構文を導入するプロポーザルです。

今のクラスの仕様だと、何かしらの外部の計算に依存してスタティックプロパティを決定したいとき、クラスの中だけでは不可能でした。

class C {
  static x = ...;
  static y;
}

try {
  const obj = doSomething(C.x);
  C.y = obj.y;
} catch {
  // doSomething が失敗したときのフォールバック
  C.y = ...;
}

このプロポーザルで追加するクラススタティックブロックを使うと、このような処理をクラス内のブロックに書くことができます。

class C {
  static x = ...;
  static y;
  static {
    try {
      const obj = doSomething(this.x);
      this.y = obj.y;
    } catch {
      this.y = ...;
    }
  }
}

JS Module Blocks for Stage 2

https://github.com/tc39/proposal-js-module-blocks

ちょっと前のマンスリーでも紹介しました。

インラインでモジュールを定義できる新しい式の構文を導入するプロポーザル。

const moduleBlock = module {
  export let y = 1;
}
let moduleExports = await import(moduleBlock);
assert(moduleExports.y === 1);

module 式で作ったモジュールは、Worker コンストラクタにそのまま渡すことができます。

let workerCode = module {
  onmessage = function({data}) {
    let mod = await import(data);
    postMessage(mod.fn());
  }
};

let worker = new Worker(workerCode, {type: "module"});
worker.onmessage = ({data}) => alert(data);
worker.postMessage(module { export function fn() { return "hello!" } });

著者のツイートからすでにステージ 2 にあがっているようです。

do expression for Stage 2

https://github.com/bakkot/do-expressions-v2

長らく Stage 1 のままだった do expression です。

ブロックの中で最後の評価されたものが式の結果になります。また、変数のスコープは do のブロックの中で閉じます。

let x = do {
  let tmp = f();
  tmp * tmp + 1;
};

読みにくいネストした三項演算子の代わりに if else で書けるようになります。

let x = do {
  if (foo()) {
    f();
  } else if (bar()) {
    g();
  } else {
    h();
  }
};

特に、JSX などの中に書くと便利です。

return (
  <nav>
    <Home />
    {do {
      if (loggedIn) {
        <LogoutButton />;
      } else {
        <LoginButton />;
      }
    }}
  </nav>
);

Relative indexing method

https://github.com/tc39/proposal-relative-indexing-method

Array.prototype.at のことです。

配列の後ろから要素を取得するのが楽になります。

const arr = ["a", "b", "c", "d"];
arr.at(0); // "a"
arr.at(1); // "b"
arr.at(-1); // "d"

JSON modules for Stage 3

https://github.com/tc39/proposal-json-modules

JSON を JavaScript からモジュールとして読み込むときの挙動についての仕様です。

もともとは、Import Assertionsの一部でしたが別の仕様として切り出されました。

ブラウザ上では JSON modules を使う場合は、セキュリティ上の都合から Import Assertions の構文を使って import する必要があります。

import json from "./foo.json" assert { type: "json" };
import("foo.json", { assert: { type: "json" } });

ただ、これはブラウザ特有のセキュリティの問題なので、JSON modules を import するときにアサートを必須にするかどうかは各ランタイムに委ねられています(Import Assertions の構文を解釈できる必要はある)。

次のような JSON を考えます。

{
  "foo": "ふー",
  "bar": "ばー"
}

これを JavaScript から import するときは default export として解釈します。

import json from "./foobar.json";

console.log(json.foo); // ふー
console.log(json.bar); // ばー

JSON のキーには JavaScript の識別子として妥当でないものを使用できるため、named export はサポートされていません。

{
  "32": "さんじゅうに"
}
// 数字は識別子として認められていない
import { 32 } from "numbers.json";

Enabling Popups - MicrosoftEdge/MSEdgeExplainers

以前の Frontend Monthlyで ”Enabling Custom Control UI” というプロポーザルを紹介したんですが、その続編みたいなプロポーザルです。 といってもその後の動向を熱心にウォッチしてたわけではなく、例によって Edge の PM のツイート から知りました。

概要

<button aria-haspopup="true" aria-controls="menuPopup" id="menuButton">
  Menu
</button>
<popup id="menuPopup" role="menu" anchor="menuButton">
  <!-- Markup for menuitems goes here -->
</popup>
document.getElementById("menuButton").addEventListener("click", () => {
  document.getElementById("menuPopup").show();
});

面白いと思ったポイントいくつか


How We Improved SmashingMag Performance

一行まとめ

JAMStack 上で React を使って構築した Web サイトのパフォーマンスを最適化し、Core Web Vitals のメトリクスを改善した手法の話。

序文

Web パフォーマンスについての話の多くはオーバーホールから始まる。 一方で、時間経過による機能追加の結果コードの断片化やサードパーティスクリプトの読み込み高速化のための “fourth-party” スクリプトが入ってしまう。

実際、smashing 社もパフォーマンスへの目標をしばしば忘れていた結果、Lighthouse スコアがボロボロになっていた。

That’s Where We Were

対象サービス(おそらくブログ)は JAMStack 上で Hugo + React を用いて構築されている。 記事のビルドには 6 分近く掛かり、CSS の注入、Webpack のコード分割、広告・昨日の動的挿入 RSS 生成、エッジに配信するための AB テスト等のビルドプロセスが走っていた。

Identifying Bottlenecks

ボトルネックを特定するためにいくつかのパフォーマンス評価を実施した。

LCP の結果、5-9 月あたりからパフォーマンスの悪化が見られた。 この時期はナビゲーションバーのリリースを実施していたことから、この指標からボトルネックを特定するのは容易だった。

サービスのリクエストマップを調べた当初は特に問題はなさそうだった。 しかし、特定の条件下で DOM のサイズが爆発的に大きくなることを発見した。 主要なページのみを計測対象とした結果発見できていなかったが、埋め込み等が多く用いられている記事を計測した際は膨大なリクエストが行き来していることがわかった。

やったこと

どうなったか


Upgrading DevTools’ architecture to the modern web

2020 年の Chrome DevSummit の動画で、Chrome DevTools が取り組んだアーキテクチャの移行についての動画。

取り組んだもの

DevTools は、大規模で歴史の長い Web アプリケーションなので、それらの移行をどのように進めたのか、移行での学びなどがまとまってる。 移行の計画・実施・管理の 3 つについて説明されていて、とても参考になるものが多かったです。


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

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