つまずきニュースレター(2024-03-28号)
はじめに
こんにちは。ファンタラクティブの yoshino です。
ファンタラクティブのエンジニアチームはMob.*(モブアスタリスク)という取り組みを毎週行っており、それぞれのメンバーがどのような開発に取り組んでいるか・業務でつまづいたことを社内で共有しています。
このニュースレターでは、その中でも実際の業務で起きたつまづきをピックアップし、まとめています。
wouter を Storybook でモックできない
背景
ルーティングライブラリの wouter を気軽に導入して使っていたところ、Storybook 上で動作しない事象に遭遇しました。
原因
Storybook 上で mock できるようなプラグインがなかったために、うまく wooter の挙動を手軽にモックすることができませんでした。
nextjs の router などはモックするためのプラグインが用意されているため、簡単にモックすることができますが、比較的に新しいライブラリだとそのサポートが期待できませんでした。
対応
wouter
をreact-router-dom
に置き換え、
MemoryRouter
を使用する事でルーティングをStorybook
上でモックする事ができました。
参考
Vitest + Storybook にて、MSW で API をモックできない
背景
Vitest にて、Storybook の Story をインポートしてテストを行ったところ、msw による API のモックが効いていませんでした。
原因
原因調査中です。
msw の起動には server と browser の2種類があり、vitest と storybook でそれぞれ必要な起動対象が異なります。(vitest は server、storybook は browser)
そのため、vitest で storybook を流用した場合は API のモックが動作していないのでは?という想定で調査を進めています。
対応
原因調査中のため、何か知っている方法などあればコメントいただけると嬉しいです!
参考
Storybook にて MSW のハンドラーが正常に設定されているか確認する
背景
特定のページコンポーネントのみ、Storybook でのプレビューが上手くいきませんでした。
原因
parameters.msw.handlers
に設定していたのがモックハンドラーではなく、モックデータだったことが原因でした。
出力されるエラーには、handler.test is not defined
といったようなエラーが出ていて、何が起きているのが理解するのに時間がかかりました。
対応
エラーの詳細を見ていると、handlers 配列を回しているような処理で handler が上手くとれていなさそうという事が分かりました。
対象の Story ファイルをあらためて確認したところ、handlers に設定しているモックファイルがハンドラーではないことに気づけたため、ハンドラーに変更して解決しました。
こちらのプロジェクトでは GraphQL を使用しており、モックデータは mockComponentName
、ハンドラーは mockMutationNameHandler
のような形式を取ることが多いです。コンポーネントや Mutation の名前によっては名前が長くなり、見落としたと思われます。
他のメンバーからもやるやるという話を聞いたので、parameters.msw.handlers
に対して型で縛るなどして気付けるように出来たらなと思いました。良い型の付け方あれば知りたいです。
特定のリンクをクリックすると、ブラウザ(Chrome)でタブが 2 つ開いてしまう
背景
通常、ウェブページ上のリンクをクリックすると、新しいタブまたはウィンドウが 1 つだけ開くことが期待される動作です。しかし、この問題では、期待される動作と異なり、リンク 1 つに対してタブが 2 つ開くという状況が発生していました。
原因
問題の原因は、HTML コード内の特定の<a>
タグ(アンカータグ)が 2 重になっていることにありました。これは、同じリンクが 2 重にネストされているか、または同じ機能を持つ<a>
タグが物理的に 2 つ存在していることを意味します。
ユーザーがリンクをクリックすると、ブラウザはこれら 2 つの<a>
タグの指示に従って、2 つのタブを開くことになります。
対応
この問題に対する対応として、HTML コードを調査し、2 重になっていた<a>
タグの内側のタグを削除しました。これにより、各リンクに対してタブが 1 つだけ開くようになり、期待されるブラウザの動作に戻りました。
さらに、この問題を解決する過程で、2 つのタブが開かないブラウザ環境が一般的に存在するかどうかについての知見も得られました。異なるブラウザや設定、プラグイン等の違いによって、同じ HTML コードでもブラウザの挙動が異なる場合があります。特に、ブラウザやその設定によっては、不正なマークアップやエラーを自動的に修正し、期待される動作を提供しようとするものもあります。Chrome は二つのタブを開く挙動を示すことがあるのに対し、Safari と Firefox では一般的にひとつのタブしか開かないため、問題にならないことが多いです。
Node.js v20 では、corepack を使う設定がデフォルトで有効化されていない
背景
Node.js v20 環境下で Yarn v4 を Corepack 経由で使用しようとした際、Expo の EAS ビルドで問題が発生しました。Node.js のこのバージョンでは、Corepack がデフォルトで有効化されていないためです。
原因
Node.js v20 では Corepack の自動有効化がデフォルトでオフになっています。これにより、Yarn v4 を含むパッケージマネージャを直接使用するためには、明示的に Corepack を有効にする必要があります。
対応
Expo クラウドでは、ビルドプロセス中にpackage.json
が存在する場合、eas-build-pre-install
スクリプトを実行します。この問題に対処するために、eas-build-pre-install
スクリプトにcorepack enable
コマンドを追加することで、Corepack を有効化し、Yarn v4 の使用を可能にしました。
参考
表示ページの描画より先に拡張機能 UI が描画された場合、mutation observer が機能しない
背景
Content Script を用いた拡張機能の UI 上で、表示ページの内容が変わることを検知するために、Mutation Observer を導入する必要がありました。しかし、ネットワーク遅延などにより、ページの内容が描画される前に拡張機能の UI が先に描画されることがあり、その結果、Observer が機能しない事態が発生しました。
原因
Observer を設定する際、監視対象の element(targetElement)がまだ存在していないため、Observer を正常に設定できていませんでした。
対応
targetElement の取得処理にリトライ(再試行)機構を実装しました。これにより、element が見つかるまで定期的に検索を試み、見つかり次第 Observer を設定することで問題を解決しました。
-
code
export const getElementRetry = ( elementId: string, retryInterval: number = 500, maxRetries: number = 20 ): Promise<HTMLElement> => { return new Promise((resolve, reject) => { let attempts = 0; const searchElement = (): void => { const targetElement = document.getElementById(elementId); if (targetElement) { resolve(targetElement); return; } if (attempts < maxRetries) { attempts++; setTimeout(searchElement, retryInterval); } else { reject(new Error("Element not found within the max retry limit.")); } }; searchElement(); }); };
おまけ 🍪
今回は Storybook の話題が多めですね。Storybook は開発を進める上で便利なのでファンタラクティブでも積極的に使用しています!
最後に
ファンタラクティブではフロントエンド・バックエンド問わず絶賛エンジニア募集中です!
気になる方は下のリンクをクリック!
ユーザーファーストなサービスを伴に考えながらつくる、デザインとエンジニアリングの会社です。エンジニア積極採用中です!hrmos.co/pages/funteractive/jobs
Discussion