mizdra's blog
https://www.mizdra.net/
ぽよぐらみんぐ
フィード
zsh + fzf で「あの時作業していたあのブランチ」を快適に探す
mizdra's blog
今まで id:mizdra はターミナルで Git ブランチを切り替えるときに、zsh + peco を使った Git ブランチ検索用のキーバインドを使用していた。 # .zshrc function select-git-branch() { selected_branch=$(git branch | cut -c 3- | peco) BUFFER="${LBUFFER}${selected_branch}${RBUFFER}" CURSOR=$#LBUFFER+$#selected_branch zle redisplay } zle -N select-git-branch bind…
1ヶ月前
React Server Components で時限式コンポーネントを作る
mizdra's blog
特定の時間になったらコンテンツをページに出したい、ということがあると思う。漫画サービスなら「ゴールデンウィーク限定!全話無料キャンペーン!」みたいなのとか。 普段の業務ではこうしたことを実現するために、時限式コンポーネントや、ScheduledComponent などと呼ばれるものを作ってる *1。 // components/ScheduledComponent.tsx export function ScheduledComponent({showAt, children}: { showAt: Date; children: React.ReactNode; }) { if (new D…
3ヶ月前
builderscon 2024 に参加 & 登壇発表しました
mizdra's blog
2024/08/10 (土) に「builderscon 2024」に参加してきました。 fortee.jp 発表 ありがたいことに「React Server Components の疑問を解き明かす」という題で発表させて頂くことができました。 speakerdeck.com React Server Component (RSC) は、サーバーサイド上でレンダリングされる React コンポーネントです。React Server Component を用いると、コンポーネントの中から DB にアクセスしたり、ファイルシステムにアクセスしたりできます。 一方で、今までにも erb や pug …
3ヶ月前
tsconfig.json の include オプションには何を指定すべきか
mizdra's blog
TL;DR "include": ["src/index.ts"] はやめよう src 配下にあるのに型チェックされない & auto-import できないファイルが生まれてしまう "include": ["src/**/*"] や "include": ["**/*"] がオススメ どっちが良いかはプロジェクトによる "include": ["src/**/*"] は "include": ["src"] と、"include": ["**/*"] は include 指定無しと同じなので、それでも OK すっごい凝りたいなら Solution Style tsconfig.json を使…
4ヶ月前
閉じている details 要素に `#fragment` でジャンプして、ジャンプと同時に展開したい
mizdra's blog
最近用語集のようなページを作る機会があった。それぞれの用語の名前と説明がバーっと並んでて、説明部分は <details> 要素で隠されている。用語の名前をクリックすると <details> が展開されて、説明部分が読める、といった感じ。 用語集ページの例 他のページから特定の用語の説明に飛べるように、用語を表す要素それぞれに id 属性が振ってある。例えば https://glossary.example.com/#javascript という URL でアクセスすると、「JavaScript」の用語がある位置にスクロールした状態で、用語集ページを開ける。 ただ (一部ブラウザで) https…
4ヶ月前
Node.js の --require/--import オプションについて
mizdra's blog
Node.js には --require=module と --import=module というオプションがあります。このオプションを使うと、エントリポイントとなるプログラムよりも前に、任意のモジュールを実行できます。 例えば以下のようなコマンドを実行すると、Node.js ランタイムはまず最初に preload.cjs を実行し、それから main.mjs を実行できます。 node --require ./preload.cjs main.mjs エントリポイントよりも前に、何かしらの処理を実行したい時に使うことを想定しています。 --require と --import の違い --i…
5ヶ月前
GitHub Sponsors 始めました
mizdra's blog
GitHub Sponsors 始めました。以下のページからスポンサーできます。 github.com 主に僕が作った OSS を使っている方、ブログを読んだりしている方からスポンサーして頂くことを想定しています。僕の OSS や記事がきっかけで、僕を支援をしたいと思った方がいらっしゃれば、是非スポンサー登録をしてみてください。 GitHub Sponsors を始めた理由 ちょっとした OSS を繰り返し作っていった結果、その OSS をメンテナンスする時間が増えてきました。情熱的に OSS 活動に時間を注がれている方と比較するとそうでもないかもしれませんが、個人的にはそこそこ OSS のメ…
5ヶ月前
tsc の代替実装は作れるのか
mizdra's blog
tsc の代替実装を作る話、とりわけ Rust や Go で tsc を高速化した移植版を作る話について。非常に野心的で面白いと思いつつ、正直僕は実用レベルまで達したものが本当に登場するのか疑問に思っている。今ある型システムもそうだし、新機能として追加されるものにも追従する必要がある。当然、実用レベルとして使ってもらうには、不具合も少なくないといけない。 それに tsc も最近はパフォーマンス改善に力を入れているように見えている。実際にリリースノートを見ると、ちょくちょくパフォーマンス改善系の変更が入っている。 TypeScript: Documentation - TypeScript 4.…
6ヶ月前
似ているけどちょっと違うものをスタイリングする CSS テクニック
mizdra's blog
React + CSS Modules なプロジェクトを例にサンプルコードを書いてるけど、それ以外の構成のプロジェクトでも使えるテクニックのはず。記事タイトルは id:hitode909 さんの 似ているけどちょっと違うものたちをモデリングする技術 - hitode909 のリスペクトです。 data 属性, 属性セレクター, CSS カスタムプロパティを使う 記事のリストがあって、記事のカテゴリごとに文字色やボーダーの色を変えたい、みたいな状況だったとする。多分素朴に書くと以下のようになるはず。 import styles from './Entry.module.css'; import …
9ヶ月前
fetch の中断と Back/Forward Cache からの復元で発生する奇妙な現象について
mizdra's blog
TL;DR あるリソースの fetch 中にページ遷移すると、一部ブラウザでは fetch が中断される 中断されると、TypeError が throw される ページ遷移時は、ブラウザによって遷移前のページの実行が"停止"され、"捨てられる"ので、通常 throw された後のことは考えなくて良い しかし、そのページが Back/Forward Cache から復元されうるなら、話は別 ブラウザバックすると、エラーが throw された後からページが再開される!!! そして発生する、奇妙な現象の数々... はじまりは、あるサービスの不具合報告 ある日、「Webサービスから外部サービスにページ…
1年前
ESLint の Suggestions から学ぶ、コードの自動修正の奥深さ
mizdra's blog
これは、はてなエンジニアアドベントカレンダー2023 4日目の記事です。 3日目は id:mechairoi さんの「SQLiteでLinderaを使った日本語全文検索」でした。 blog.chairoi.me 今日のテーマは、JavaScript 向けの Linter 「ESLint」についてです。ESLint を使うと、JavaScript で書かれたコードを静的解析して、よくある間違いを検出したり、コーディングスタイルを統一できます。 通常、ESLint のルールによって報告された問題 (error や warn) は人が手で修正します。ただし、ルールが報告する問題の中には「fixabl…
1年前
GraphQL のレスポンスのモックデータの作成を補助する TypeScript ライブラリを作った
mizdra's blog
GraphQL を使って Web アプリケーションを実装していると、GraphQL API のリクエストをモックしたいことがあると思います。 ユニットテストのために、ダミーレスポンスに差し替えたい ビジュアルリグレッションテストのために、ダミーレスポンスに差し替えたい Storybook で story を書くために、ダミーレスポンスに差し替えたい バックエンドの resolver 実装を待たずにフロントエンド側の開発を始めるために、ダミーレスポンスに差し替えたい 一般には GraphQL Client にモックするための機能が実装されてるので、そうしたものを使うことが多いと思います。 zen…
1年前
react-relay の useFragment で本来取得できるはずの field が欠損する現象について
mizdra's blog
react-relay を使っていると、稀に「本来取得できるはずの field が欠けた状態のオブジェクトが useFragment から返される」現象に遭遇することがあります。 例えば、以下のようなエントリーのタイトルと本文を表示するエントリーページがあったと仮定します。デフォルトではタイトルのみが表示されていて、「本文を表示」ボタンを押すと、GraphQL API から本文が fetch されて表示されます。 import {PreloadedQuery, usePreloadedQuery, graphql, useFragment, useLazyLoadQuery} from 're…
1年前
Next.js で言語ごとに異なるアセット画像を埋め込む
mizdra's blog
多言語対応している Web アプリで、あらかじめファイルに書き出しておいた画像 (アセット) が言語別にあって、それをページに埋め込むにはどうするか、という話題です。基本は言語ごとに別々の画像を出すことないと思いますが、たまーにあるんですよね。例えばGoogle Play のバッジが言語ごとに違うので、これを言語ごとに出し分けたいとか。 Google Play バッジ – Google 色々方法があるので、それをいくつか紹介します。 方法1. import 文を言語の数だけ書く シンプルにやるなら、言語の数だけ import 文を書いて、next/image の <Image> コンポーネント…
1年前
Relay の %future added value, %other との向き合い方
mizdra's blog
前提 まず議論の土台は https://github.com/facebook/relay/issues/2351 GraphQL では Enum に対する variant の追加が破壊的変更になりうる 新しい variant が来ることを考慮してなくて、突然アプリケーションが壊れる可能性がある 自分たちで実装している GraphQL API なら、variant の追加タイミングを調整できるので問題にならないようにもできる しかし、外部の GraphQL API サーバーを利用している場合は、追加タイミングを予知できないので、ある日突然壊れる そのため、Relay は未知の値が来ても壊れない…
1年前
アセットの import を簡単にする TypeScript Language Service Plugin を作った
mizdra's blog
Web ページを作るときに、あらかじめファイルに書き出しておいた画像 (アセット) をページに埋め込みたいことがよくあると思います。例えばヘッダーにサービスのロゴ画像を埋め込む場合、以下のようなコードを書くと思います。 // src/components/Header.tsx export function Header() { return ( <header> <img src="/assets/logo.png" alt="Logo image" /> {/* ... */} </header> ); } 一方で、最近のWeb フロントエンドフレームワーク (例: Next.js, Re…
1年前
Node.js でフィクスチャーファイルを簡単に作成するライブラリを作った
mizdra's blog
よく Node.js で CLI ツールを作っているのだけど、そのテストコードを書くのが大変だなあという課題感があった。例えば、ESLint のエラーをルールごとにグルーピングして、ルール単位で修正できるツール (eslint-interactive) を作ったときは、以下のようなテストコードを書いていた。 // fixtures/semi.js const val = 0 // fixtures/prefer-const.js let val = 0; // fixtures/.eslintrc.js module.exports = { root: true, parserOptions:…
1年前
Next.js で SSR を強制する
mizdra's blog
SSG も ISR も SSR も、どれも便利なのだけど、どれも扱いが難しい! SSR 1つを取っても、first paint の状態で GraphQL API から取得したデータがレンダリングされた状態を目指すなら、それなりに複雑な仕組みを getServerSideProps/_app.ts に実装しないといけない。 BFF で GraphQL API を叩いて、その結果を pageProps に焼き込んで、 コンポーネントのレンダリング時に pageProps から結果を取り出して GraphQL クライアントのキャッシュにそれを書き込んで…みたいなことを SSR でやる必要がある訳だけ…
1年前
Relay でも msw の handler を型付きで書く
mizdra's blog
msw を使うと、GraphQL API をモックしてダミーレスポンスを返せます。以下のような handler と、その他少々のセットアップコードを用意するだけで簡単にモックできます。 // src/mocks/handlers.js import { graphql } from 'msw'; export const handlers = [ // ブログのトップページのクエリをモックする handler。 // `graphql.query` の第一引数には、 // `query <クエリ名> { ... }` の `<クエリ名>` の部分に対応した文字列を書く。 graphql.que…
2年前
npm package を実装するための自分専用テンプレートリポジトリを作った
mizdra's blog
npm package を作る度にイチから開発環境の構築をしていて大変だったので、自分専用のテンプレートリポジトリを作りました *1。 github.com せっかくなので、テンプレートの特徴とか、どういうこと考えながら作ったとか紹介してみます。 はじめに: 基本的な技術スタック npm TypeScript Node.js Native ESM Prettier ESLint Vitest Renovate GitHub Actions vscode 向けの各種設定ファイル (extensions.json, launch.json, settings.json) GitHub の「テンプレ…
2年前
Twitter に投稿したツイートを Mastodon に転送するようにした
mizdra's blog
去年の 11 月から続く一連の騒動を受けて、id:mizdra のフォロワーの中でも Twitter から Fediverse に移行してきている人が増えてきた。僕自身は移行するつもりはないけれど、移行したフォロワーが僕のツイートを Fediverse から見れるように、ツイートを Mastodon へと転送するようにしてみた。せっかくなので、そのやり方について書き残しておく。 作戦 IFTTT という「〇〇したらXXする」みたいなピタゴラスイッチをボタンポチポチで作れるサービスがある。これを使い、当該 Twitter アカウントでツイートがされたら、それを契機に Mastodon にトゥート…
2年前
Next.js の getServerSideProps を共通化する
mizdra's blog
Next.js で開発していると、複数のページの getServerSidePropsで同じようなコードを度々書くことになると思う。例えば 「GraphQL クライアントでクエリを fetch して、そのレスポンスをpagePropsに焼き込むロジック」であったり、「(マルチテナントアプリケーションにおいて) リクエストヘッダーからテナントを特定するロジック」であったり。こうした大部分のページで使われるロジックのコードは、何度も書かずに済むよう、何らかの共通化をしたくなる。 すでに色々な人が似たような動機でgetServerSidePropsを共通化する方法を紹介していると思う。それを参考にし…
2年前
YAPC::Kyoto 2023 に参加してきた
mizdra's blog
登壇とかではなく、いち聴者として参加してきました。 yapcjapan.org 前日祭も参加していて、土日での京都滞在でした。 yapcjapan.connpass.com 僕と YAPC YAPC への参加は去年の YAPC::Japan::Online 2022 に続いてとなり、YAPC::Kyoto 2023 で2回目です。オフラインの YAPC は初めてでした。 また、別の話として新卒入社のタイミングがコロナと重なっており、参加人数が数百人超える大きなカンファレンスに出たことがほとんどありませんでした (入社前のものを含めると HTML5 Conference 2018 と build…
2年前
CPU シミュレータを用いて継続的ベンチマークを安定化させる
mizdra's blog
id:mizdra は eslint-interactive というツールをメンテナンスしています。このツールを使うと、多数の ESLint エラーを効率的に修正できます (詳しくは以前書いた記事を見てください)。 www.mizdra.net eslint-interactive では「中規模〜大規模なコードベースであってもキビキビ動く」を大事にしてます。その一環として、eslint-interactive には CI (GitHub Actions) でベンチマークを取り、以前から大きく劣化していたら CI を fail させる仕組みがあります。 https://github.com/mi…
2年前
試行錯誤を邪魔しない開発環境
mizdra's blog
ある機能を実装する際、完成形のコードになるまでには、プログラムとして不正確な状態や、プロダクト品質ではない状態を経る 静的型検査や lint rule に違反したコードが途中に挟まる 型エラーや lint エラーは望ましくないので、できるだけ早くこうした情報を開発者に伝え、気付けるようにすると良い CI でこうしたエラーを検知して、Pull Request をマージする前に気づけるようにするとか エディタ上にエラーの情報を表示して、コーディング中に気づけるようにするとか エラーを積極的に通知してくれるのはありがたいけど、やりすぎには注意するべき なんとなくでも動いてくれたほうが嬉しい 例えば …
2年前
ネイティブモジュールに依存しない node-canvas 代替ライブラリを使う
mizdra's blog
Web フロントエンドにて、Canvas を使った View のテストを書きたいことがたまにあります。ブラウザであれば以下のようにして Canvas を利用できますが、テストが実行される Node.js ではそのような API は生えていません。 const canvas = document.createElement('canvas'); canvas.width = 200; canvas.height = 200; const ctx = canvas.getContext('2d'); ctx.fillStyle = 'green'; ctx.fillRect(10, 10, 150…
2年前
ある Web ページに関するリソースのうち、ブラウザにリークしているものを調べる
mizdra's blog
最近の Web フロントエンドの開発では、JavaScript/CSS ファイルを bundler (webpack, vite, ...) でバンドルして、それをブラウザに配信することが多いと思います。 例えば以下のようなコードを bundler でバンドルすると、react + react-dom/client + ./locales/ja-JP.json が結合された bundle.js というファイルが生成されます (出力されるファイル名は bundler によって異なるのでイメージです)。 import React from 'react'; import { createRoot …
2年前
next lint は lint 対象のディレクトリが制限されている
mizdra's blog
ということに next lint を触っていて気づきました。公式ドキュメントにもそう書いてありました。 next lint runs ESLint for all files in the pages, components, and lib directories. It also provides a guided setup to install any required dependencies if ESLint is not already configured in your application. (https://nextjs.org/docs/api-reference/…
2年前