つまずきニュースレター(2024-02-09号)
はじめに
ファンタラクティブのエンジニアチームはMob.*(モブアスタリスク)という取り組みを毎週行っており、それぞれのメンバーがどのような開発に取り組んでいるか・業務でつまずいたことを社内で共有しています。
このニュースレターでは、その中でも実際の業務で起きたつまずきをピックアップし、まとめています。
【vitest + urql】urqlを使っているコンポーネントの単体テストが落ちてつまずいた!
背景:
urqlを使っているコンポーネントの単体テストが落ちる
原因:
クライアントをモックするために、urql client の Provider を設定しないといけませんでした。
対応:
Provider を用いて、モックした client を設定することで解消しました。
vitest の mock
関数などもありますが、今回のケースでは render する際に、 Provider を一緒に設定する方針で対応しました。
import { Provider } from "urql";
const clients = {
executeQuery: () => {},
};
// ...
test("render items", () => {
render(
<Provider value={clients}>
<Component />
</Provider>,
);
// ...
参考
border-radius してもはみ出てしまいつまずいた!
背景:
背景のある要素に対して border-radius を設定したけど、うまくスタイルが当たらず border-radius を貫通して要素が表示されてしまう。
原因:
border-radius を設定している要素(以下 container)からはみ出る要素を隠すスタイリングをしていなかったために、貫通してしまっていました。
対応:
border-radius を設定している要素に対して、overflow: hidden を設定しました。こうすることで、角丸のエレメントを作成することができました。
参考:
【Nextjs】API を叩くと431 (Request Header Fields Too Large)が返ってきてつまずいた!
背景:
クライアントからAPIにリクエストを送信すると、431 Request Header Fields Too Large
エラーが返され、APIへのアクセスが不能になりました。リクエストヘッダーなどにも不備はなさそうで、リクエストも届いていそうなのですが何故かエラーコードが返されていました。
原因:
next.config.js
のrewrites
内で使用されている環境変数が誤って設定されており、正しいエンドポイントにリクエストを送れていませんでした。
対応:
next.config.js
内のrewrites
で使用されている環境変数を正しく設定することで解消しました。エラーメッセージにある Request Header
からは想定しづらい修正箇所だったため、解決に時間を要しました。
参考:
【Nextjs + CloudFront】特定のページでリロードすると、別ページに飛ばされてつまずいた!
背景:
特定のページをリロードすると、意図しない別ページに移動される現象が発生しました。
原因:
CloudFront Function で動的ルーティングの設定が行われていなかったため、ページ内の動的パスが適切に処理されていませんでした。
対応:
CloudFront Function 上で動的ルーティングの設定を行うことで解消。
今のところ、動的なパスが現れるたびに設定を行う必要がありそうなので、プロジェクト内のルーティングを見て関数を自動生成するなど改善策を模索中。。。
const dynamicPatterns = {
page: /\/hoge\/([^\/]+)\/?[^\/]*\.html$/,
};
const pageMatch = uri.match(dynamicPatterns.page);
if (pageMatch) {
uri = uri.replace(pageMatch[1], "[id]");
}
Falsyな値のチェックでつまずいた!
背景
JavaScriptでgetElementsByClassName
メソッドを使用する際、返り値としてHTMLCollection
が返されます。しかし、このHTMLCollection
をそのままif文の条件に使用すると、意図しない挙動が発生する可能性があります。
原因
getElementsByClassName
の返り値がHTMLCollection
であるとき、このオブジェクトが空であっても、if文の条件として評価されるとtrue
となってしまいます。これはJavaScriptの真偽値の評価において、空のオブジェクトはtrue
とみなされるためです。
HTMLCollection
が空(つまり、指定されたクラス名を持つ要素が一つもない)の場合、HTMLCollection
は実際には空の配列のような形([]
)を取りますが、これは依然として真偽値としてはtrue
と評価されます。
対応
この問題を解決するためには、HTMLCollection
のlength
プロパティを使用して、実際に要素が存在するかどうかをチェックする必要がありました。
const elements = document.getElementsByClassName('foo');
// NG
if (elements) {}
// OK
if (elements.length > 0) {}
SpeakerDeckの埋め込みでつまずいた!
背景
nuxtjsで構築されているページにSpeakerDeckを埋め込む作業を行った。この際の、埋め込み方としてscript
タグを使用する方法を試してみました。
原因
nuxt dev
ではscript
タグを使った埋め込みが正常に機能したが、nuxt build && nuxt export
を実行した際にはうまく動作しなかった。なぜbuild時は機能しないのか正直理解できていません。ご存じの方がいたらコメント頂けると幸いです。
対応
最終的に、埋め込み方法をiframe
に変更して対応しました。
補足情報
詳細な埋め込み方法についてはこちらで確認できます
Google拡張機能のタブ切り替え時のUIでつまずいた!
背景
chrome拡張機能の開発で、content script UIをpopupUI風に見せる実装をしていました
課題
拡張機能のUIを表示した後、ブラウザタブを切り替えても表示状態を維持する方法でつまずきました
対応
まず拡張機能アイコンをクリックしたとき、そのタブのIDをストレージに保存します。
content script UIは、Service Workerを通じてタブのIDを取得し、このIDがストレージに保存されているタブIDと一致する場合にのみUIを表示状態に切り替えるようにすることで対応しました。
もっと良い方法をご存知の方、コメントお待ちしています!
【Next.js】環境変数を使用したフォントのURL指定でつまずいた!
背景
プロジェクトで使用しているフォントのURLをS3に配置し、その向き先を環境変数で管理したいかった。当初、フォントの読み込みはSCSSファイルで行っていたが、SCSSファイルでは環境変数を参照できないという問題がありました。
対応
この問題を解決するために、Styled JSXを使用してフォントの読み込みをコンポーネントで行うようにしました。これにより、Next.jsの環境変数を利用して動的にフォントのURLを設定できるようになりました。
const fontDomain = process.env.NEXT_PUBLIC_FONT_BASE_URL
return (
<style jsx>
{`
@font-face {
font-family: 'foo';
src: url(${fontDomain}/fonts/hoge.woff)
format('woff');
unicode-range: fuga
}
`}
</style>
);
余談
以下の記事を見つけました。この記事内にある通りnextConfigのsassOptionsを調整することで同様のことができるかもしれません。
おまけ🍪
今回から、エンジニアチームで「つまずきニュースレター」をはじめることにしました!
このニュースレターを通じて、私たちファンタラクティブのエンジニアチームが日々どんな風に仕事をしているのか、また、ちょっとしたつまずきやアレコレをどう乗り越えているのかを、のぞいてみてもらえたら嬉しいなと思っています。
もしあなたが仕事で「うーん」と思うことがあったとき、ここからちょっとしたヒントを見つけてもらえたら、それ以上の喜びはありません。気楽に読んで、何か一つでも「なるほどなぁ」と思ってもらえるところが見つかれば最高です!
最後に
ファンタラクティブではフロントエンド・バックエンド問わず絶賛エンジニア募集中です!
気になる方は下のリンクをクリック!
ユーザーファーストなサービスを伴に考えながらつくる、デザインとエンジニアリングの会社です。エンジニア積極採用中です!hrmos.co/pages/funteractive/jobs
Discussion