Frontend Weekly 2024-05-02
React v18.3、Bun v1.1.5、Remix Single Fetchなどについて紹介する。
React v18.3
2024年4月25日、React v19 Betaの公開に合わせて、React v18.3も公開されました。
Upgrade GuideでReact v18.3について言及されています。これはReact v19で非推奨なAPIや削除など必要な変更についての警告が追加されたバージョンです。
React 19 Beta Upgrade Guide – React
削除されたAPIは十分な移行期間を設けられているため、長く放置されている環境でなければスムーズに移行できると思います。触れる機会がありそうなものを以下にピックアップします。
- element.refが非推奨に。
- refをpropsとしてサポートしたため、element.props.refを利用する。
- 以前テストに利用されていた
react-test-renderer
が非推奨に。- @testing-library/reactを推奨している。
- useRefの引数が必須に。
- [RFC] Make all refs mutable #64772
- MutableRefは非推奨になっており、RefObjectが推奨されている。
- Context.ProviderがContextで良くなった。
Bun v1.1.5
2024年4月26日にBun v1.1.5がリリースされました。
クロスコンパイルをサポートするようになりました。
# Linux x64
bun build --compile --target=bun-linux-x64 app.ts
# Windows x64
bun build --compile --target=bun-windows-x64 app.ts
# macOS Silicon
bun build --compile --target=bun-darwin-arm64 app.ts
# Linux arm64
bun build --compile --target=bun-linux-arm64 app.ts
package.jsonの末尾カンマとコメントが許容されるようになりました。
{
"name": "app",
"dependencies": {
// We need 0.30.8 because of a bug in 0.30.9
"drizzle-orm": "0.30.8"
}
}
Import Attributesを利用して、任意のファイルを特定の形式としてインポートできるようになりました。
import html from "./index.html" with type { type: "text" };
import json from "./config.foo" with { type: "json" };
import cfg from "./Configfile" with { type: "toml" };
console.log(html); // <!doctype html><html lang="ja"><head>....
console.log(cfg); // { "name": "app" }
console.log(json); // { "name": "app" } (converted to JSON object)
Remix Single Fetch
Remix v3からデフォルトの挙動になるSingle Fetchについて解説する記事。
Remix v2.9 で導入された Single Fetch
Single Fetchは、クライアントサイドでのページ遷移が行われた際に、サーバーへの複数のHTTPリクエストを並行して行う代わりに、1つのHTTPリクエストを実行しまとめてレスポンスを返す機能。
Remix v2.9からフィーチャーフラグで提供されている。
Single Fetchには、新しいストリーミング形式、action
関数の再検証、headers
関数の廃止などいくつか破壊的な変更があるため注意が必要。
satisfies演算子で型が絞られるケース
特定のケースではsatisfies演算子で型が絞り込まれてしまう???
あるリテラルがそのリテラルの対応する型を含むユニオンによって型を文脈的に指定される場合、親プリミティブに拡張されるのではなく実際のリテラル型が保持されるため、型の制約によってリテラル型として推論されるケースがある。
type Numbers = (1 | 2 | 3 | 4)[];
const numbers1 = [1, 2, 3];
// number[]
const numbers2 = [1, 2, 3] as const;
// [1, 2, 3]
const numbers3 = [1, 2, 3] satisfies Numbers;
// (1 | 2 | 3)[];
declare const test: <T extends "a" | "b">(arg: T) => T;
test("a");
// "a"
Server Component と Client Component で依存モジュールを切り替える
Node.jsのSubpath importsを利用して、React Server環境で利用されるソースを指定できる。
Server Component と Client Component で依存モジュールを切り替える
Subpath importsには、requireやimportの代わりにCommunity Conditionsといって任意の値を利用できる。TypeScriptのtypesなど。
Modules: Packages | Node.js v22.1.0 Documentation
server-onlyパッケージの例
{
"name": "server-only",
"files": ["index.js", "empty.js"],
"main": "index.js",
"exports": {
".": {
"react-server": "./empty.js",
"default": "./index.js"
}
}
}
React Server環境以外では、次のindex.jsが読み込まれエラーが出力される仕組み。
throw new Error(
"This module cannot be imported from a Client Component module. " +
"It should only be used from a Server Component."
);
F-Shape Pattern And How Users Read
サイトの種類によるユーザーの視線移動のパターンの紹介。
F-Shape Pattern And How Users Read — Smashing Magazine
Super意訳
- 意図的なリズムのない画面では、ユーザーの注意が失われる。
- F字型スキャンはデザインによって十分に誘導されない場合のユーザーの代替動作と考えて。
- 少なくともアンカーを設置してE字型に誘導するか、せめてレイヤー・ケーキ・スキャンできるようにしよう。
注意力が失われるから下に行くほど読まれる量が減っていくので、F字型スキャンが十分に誘導されていない場合に起きるというのは正しいように思う。ただし、ユーザーがそのページに全く興味がない場合などでも発生するので、ユーザー数が非常に多いサイトなどでは検出されがちではある ように思う。
部分的に読み飛ばされても問題がないように、重要なコンテンツに意図的に注意を向けさせる。ユーザーの注意力を維持させるために、制御されたリズムを画面に持たせるということをデザインで行えると良い。
img要素のalt属性に何を指定すればいいか
W3CのImages Tutorialの内容に基づいて説明している。
Alt属性にどのような内容を入れるべきかを説明するAlt Decision Tree。
個人的には、alt属性については次の2つを最低限認識しておいた方が良いと思う。
- alt属性に空文字を指定すると、装飾的な画像ということになる。
- alt属性には、必ず意味のあるテキストまたは空文字を指定すべき。
CSS の圧縮についてはもう議論されないのはなぜか
CSSの圧縮は、First Contentful Paint (FCP)の最適化などに役立つ。
HTTP圧縮アルゴリズムの進歩やHTTP/2の多重化によって、非圧縮と圧縮の差がある程度無視できる程度になったことや、フロントエンドのフレームワークやバンドラーが暗黙的にCSSの圧縮を行なっていることに触れている。記事では言及されていないが、CSS in JSなどの影響もありそう。
Why don’t we talk about minifying CSS anymore?
SVG Viewer
2024年2月くらいにリリースされたサービス。
SVGの検索、表示、圧縮、Reactなどへのコード変換などをサポートしている。
どこからデータを持ってきているか定かではないが、かなり量がある。
Meticulous
SDKを仕込んでおき、実際の画面の操作を元にテストコードを生成して実行したり、ロジックや見た目の変化を検知して、PRで確認できるようにしてくれるっぽい。バックエンドへのリクエストのモックもデフォルトで行う。