Frontend Weekly 2024-02-23
Deno 1.41
2024 年 2 月 22 日に Deno 1.41 がリリースされました。deno compile で生成されるバイナリがかなり小さくなりました。
Remix 2.7.0
2024 年 2 月 20 日に Remix 2.7.0 がリリースされました。SPA モードが安定版になった他、Remix Vite が Cloudflare Pages をサポート、Vite との互換性の改善などが行われています。
React Strict DOM
Meta が React Strict DOM(RSD)を公開しました。これは Web およびネイティブ用のスタイル付き React コンポーネントの開発の改善および標準化を目的とした React DOM と StyleX の実験的な統合とのことです。
https://github.com/facebook/react-strict-dom
React Native for Web は React Native の API を Web 上で補完しようするものでしたが、RSD は Web API を React Native に組み込んでいこうとする試みです。
既にかなりの機能が実装されています。
https://github.com/facebook/react-strict-dom/blob/main/packages/react-strict-dom/COMPATIBILITY.md
import { css, html } from "react-strict-dom";
const styles = css.create({ container: { borderTopWidth: 1 }, h1: { padding: 10, backgroundColor: "#eee" }, content: { padding: 10 },});
export default function Example(props) { const { title, children } = props; return ( <html.div style={styles.container}> <html.h1 style={styles.h1}>{title}</html.h1> <html.div style={styles.content}>{children}</html.div> </html.div> );}
htmz
htmz は標準の HTML を利用してページの部分更新を行う数行のスニペットです。
<script> function htmz(frame) { setTimeout(() => document .querySelector(frame.contentWindow.location.hash || null) ?.replaceWith(...frame.contentDocument.body.children) ); }</script><iframe hidden name="htmz" onload="window.htmz(this)"></iframe>
実用的かはともかく、かなり面白いアイデアだと思います。リンクをクリックされると、iframe に対応したコンテンツが描画され、そのコンテンツを hash の id が付いた要素の中身と置換する仕組みになっています。
<base target="htmz" />
<div role="tablist"> <a class="tab" href="dog.html#my-tab-panel">Dog</a> <a class="tab" href="cat.html#my-tab-panel">Cat</a> <a class="tab" href="horse.html#my-tab-panel">Horse</a></div>
<div id="my-tab-panel" role="tabpanel"></div><iframe hidden name="htmz" onload="window.htmz(this)"></iframe>
Safetest
Safetest は、Netflix の開発した Playwright や Vitest/Jest を組みわせたテストライブラリです。
https://github.com/kolodny/safetest?tab=readme-ov-file
従来のフロントエンドのテスト手法である単体/統合テストや E2E テストの欠点を、両方を組み合わせることで補完することを目的としています。アプリケーションの起動時にテスト用のフックをインジェクトする仕組みのため、ブラウザとテストコンテキスト間の双方向通信や、Playwright や Jest/Vitest の機能へのアクセスも可能になっています。
テストの記述方法は、見慣れたものです。
export const Header = ({ admin }: { admin: boolean }) => ( <div className="header"> <div className="header-title">The App</div> <div className="header-user"> <div className="header-user-name">admin</div> {admin && <div className="header-user-admin">admin</div>} <div className="header-user-logout">Logout</div> </div> </div>);// Header.safetest.tsximport { describe, it, expect } from "safetest/jest";import { render } from "safetest/react";import { Header } from "./Header";
describe("Header", () => { it("can render a regular header", async () => { const { page } = await render(<Header />); await expect(page.locator("text=Logout")).toBeVisible(); await expect(page.locator("text=admin")).not.toBeVisible(); expect(await page.screenshot()).toMatchImageSnapshot(); });
it("can render an admin header", async () => { const { page } = await render(<Header admin={true} />); await expect(page.locator("text=Logout")).toBeVisible(); await expect(page.locator("text=admin")).toBeVisible(); expect(await page.screenshot()).toMatchImageSnapshot(); });});
なお、実験的ですが Playwright にも Component 単位でのテストを可能にする似たようなことが出来る機能が入っています。