こんにちは、DXビジネス開発部の白木です。
普段はOPTiM Cloud IoT OS、OPTiM Collaboration Portalの開発に携わっています。
本記事は OPTiM TECH BLOG Advent Calendar 2025 Day 20 の記事です。また、フロントエンド推進室の運営メンバーの共同執筆になります。
- フロントエンド推進室について
- 運営メンバーからのフロントエンド小ネタ
- おわりに
フロントエンド推進室について
2025年度の10月にフロントエンド推進室が発足しました。 フロントエンド推進室は、全社のフロントエンド(製品、人限らず)をより強化し良いものにすることをミッションとした社内横断組織です。
主な活動
📅 フロントエンド雑談会
毎週水曜日に全社のフロントエンドエンジニアを集めて、技術トピックやチーム間の課題共有を行っています。カジュアルな雰囲気で最新のフロントエンド技術や各チームの取り組みについて情報交換しています。
🎤 OPTiM X-Talk
EMO(Engineering Manager Office)主催のX-Talkの発足第一回目の登壇・実施をサポートしました。社内の技術力向上と知見共有の場として継続的に活動しています。
🌟 Frontend OSS活動
全社横断的に利用可能なOSSの作成・管理を行っています。社内のフロントエンド開発の効率化と品質向上を目指し、積極的にコミットを推進しています。
🚀 社外イベント登壇
React Tokyo #3 会場スポンサーセッションでClineを用いたReactアプリケーション改善について発表し、Speaker Deckで2,000回以上閲覧されました
~エンジニア視点で議論する~ 次世代デザインシステムへの現在地: サイボウズ株式会社・株式会社サイバーエージェント・当社の3社で開催したイベントでデザインシステムについてエンジニア視点で議論しました
🎬 ゆるっと同時視聴会
社外イベント参加の障壁を減らし、個々のキャッチアップ力向上を目的とした継続活動です。
その他、フロントエンド相談会やAI体験会など、多様な活動を通じて社内のフロントエンド技術力の底上げに取り組んでいます。
運営メンバーからのフロントエンド小ネタ
今回は運営メンバー6名が、フロントエンドの小ネタを共有します。
脆弱性予防をしよう ~ツール編~ 高橋
ここ最近、npmの攻撃やReact/Next.jsやNode.jsの脆弱性が話題になっています。 ただ脆弱性はフレームワーク等だけの話ではなく、どの環境でも起こりうる問題です。
これらを対策するツールを調べてみたので小話として共有いたします。
npm audit / yarn audit / pnpm audit
インストールされたパッケージの既知のセキュリティ問題をチェックするコマンドです。 git hooksやCIフローに導入することでコミット/マージ前にパッケージに問題がないかをチェックすることが可能です。
私の担当のサービスはpnpmを使っていることから pnpm audit を採用しました。
現在はCIフローに組み込んでいます。
参考リンク
自動依存性アップデートツール
定期実行で、「こういう理由でこのバージョンに上げよう」のような更新アクションを起こしてくれるツールとして使っています。 npm packageのバージョン更新を2日待ってから更新やマイナーバージョン自動更新などを担わせています。 Renovateは、依存パッケージの既知の脆弱性(CVE)を検出し、修正バージョンへのアップデートを促す/更新PRを作成してくれたりする優れものです。
Dependabotという依存パッケージの脆弱性を検知し、それを解決するためのプルリクを自動で生成してくれるサービスもあります。
弊社ではSelf-managedなGitLabを利用していることから Renovate を採用しました。
参考リンク
SCA(Software Composition Analysis)
アプリケーションやコンテナの中に含まれる OSS ライブラリやフレームワーク、そのバージョンを自動的に特定し、既知の脆弱性やライセンスを評価することを目的に実行しています。
自動更新ツール(Renovate)と異なり、SCAは「現在の依存に既知CVEがあるか」を静的に検知・レポートをし、更新実行ではなく『検知レイヤー』と領域が異なるので併せて利用すると検知漏れを避けることができる可能性が上がると思います。
TrivyやOSV-Scanner、Snyk Open Sourceなどのツールがあります。 IaCが対応していること、採用事例が社内であることからTrivyを採用いたしました。
参考リンク
SAST (Static Application Security Testing)/DAST(Dynamic Application Security Testing)
前提としてCIに組み込みやすいものから調べていきました。
まずSASTとは、アプリケーションを実行せずにソースコードやバイナリコードを静的に解析し脆弱性を早期に検出する手法です。
ツールは、SonarQube、Semgrep、Snyk Codeなどの有名どころもありますが、GitLabを使っているのもあり GitLab SAST(組み込みのSAST) を利用することとしました。
注意点としてGitLab SASTに関しては、Free, Premium, Ultimateとプランが分かれています。 FreeでもSemgrepベースの基本機能は使用可能で、それを利用しています。
次にDASTとは、実行中のアプリケーションに対して外部から攻撃をシミュレートし、セキュリティ脆弱性を発見する手法です。
同様にGitLabのものを利用したかったのですが、Ultimateのみ利用可能という形になっており、別の選択肢を考えました。
他にはOWASP ZAPやNiktoのツールがあり一番ユースケースに合いそうな OWASP ZAP を採用しました。
ただし通常のCIフローに含めるのは運用上大変だったため定期Job側での動作側のCIに組み込む形の運用をしています。
参考リンク
たくさんのツールがあり選択肢も多く迷ってしまいますが、社内での採用事例やユースケースをもとに選びCVE含め脆弱性に早期に気づけるような仕組み作りをしていきたいなと思います。 脆弱性を作らないことは相当難しいので、いざとなった時の対応策があることでリスクも大きく減らすことを担保する上でもこういったツール等は便利です。
もしより良い仕組み化や手順などあればぜひ情報交換をいたしましょう!!!!
Storybookで類似コンポーネントを見つける簡単な方法 亀田
「このコンポーネントに似た実装ないかな?」 Storybookを起動するとそこには600個のコンポーネントがありました
こんなことありますよね。Storybookは便利ですがコンポーネントが増えてくると類似コンポーネントを探すだけでも骨が折れます。
Storybookのguiでコンポーネント検索はできるのですが、検索結果からコンポーネントを選択すると検索結果が非表示になります。かつ検索結果は1レイヤーでコンポーネントがずらっと並ぶのでフォルダ分けしていても意味がないです。
tagsとの出会い
ぐぬぬ。。。どうしたもんかと思って公式ドキュメントを眺めていると・・・「これだ!」って機能が見つかりました。 https://storybook.js.org/docs/writing-stories/tags
そう、tagsです。
const meta = { title: 'component/elements/Accordion/SimpleAccordion', component: SimpleAccordion, tags: ['autodocs'], } satisfies Meta<typeof SimpleAccordion>;
tagsに設定したタグはgui上の三角ロートマークから選択することができます。tagsはなんとフォルダ構成を保ったまま検索が可能です。コンポーネントを選択しても検索結果は表示されたままなのでとても見やすいです。
tags使ってみる
早速SimpleAccordion君のtagsに'accordion'を設定しました。
const meta = { title: 'component/elements/Accordion/SimpleAccordion', component: SimpleAccordion, tags: ['accordion'], } satisfies Meta<typeof SimpleAccordion>;
めちゃ良い〜全部のコンポーネントにタグをつけていけばかなり検索しやすくなりそうです。
~fin~
とはならず。問題があります。tagsはstringの配列型なので縛りが不十分です。具体的な辛みとしては'simpleAccordion'とか'accrdio'とか何でもtagsに入れられちゃいます。
tagsをカスタマイズしてみる
ならばtagsだけ置き換えた型を作っちゃえということで以下を作ってみました。
import type { Meta as OriginalMeta, StoryObj as OriginalStoryObj } from '@storybook/nextjs-vite'; // 組み込みタグ type BuiltInTag = 'autodocs' | '!autodocs' | 'dev' | '!dev' | 'test' | '!test'; /** * NOTE: * タグを新規に追加する場合はMUI公式のコンポーネントページを参考にすること * https://mui.com/material-ui/all-components/ */ type CategoryTag = | 'mobile' // モバイル専用 | 'layout' // レイアウト( 例:ヘッダー、フッター) | 'feedback' | 'navigation'; type ComponentTag = | 'textField' | 'button' | 'dialog' | 'checkbox' | 'radio' | 'select' | 'table' | 'treeView' | 'accordion' | 'breadcrumb' | 'card' | 'chip' | 'tooltip' | 'feedback' | 'list' | 'loading' | 'menu' | 'pagination' | 'tabs' | 'dateRangePicker' | 'typography' | 'link' | 'icon' | 'markdown'; export type StorybookTag = BuiltInTag | ComponentTag | ComponentCategoryTag; // Meta型の拡張 export type Meta<TComponent> = Omit<OriginalMeta<TComponent>, 'tags'> & { tags?: StorybookTag[]; }; // StoryObj型の拡張 export type StoryObj<TMeta> = Omit<OriginalStoryObj<TMeta>, 'tags'> & { tags?: StorybookTag[]; };
色々書いてますがやっていることは単純でstring[]型のtagsをOmitした後にカスタムtagsを結合させているだけです。カスタムtagsの実態もシンプルで、stringのリテラル型をユニオン型で定義しているだけです。
次のように使います。
- import type { Meta, StoryObj } from '@storybook/nextjs-vite'; + import type { Meta, StoryObj } from '@/storybook/types'; import { SimpleAccordion } from './SimpleAccordion'; const meta = { title: 'component/elements/Accordion/SimpleAccordion', component: SimpleAccordion, tags: ['accordion'], } satisfies Meta<typeof SimpleAccordion>; export default meta; type Story = StoryObj<typeof meta>; export const Default: Story = { args: { summary: 'サマリ', children: <div>children</div>, }, };
これなら複数人で開発していてもタグの設定には困りません。無尽蔵に増えることもないでしょう。MUIルールに沿っているので命名で困ることもほぼないです。抽象的に絞ることも考えてカテゴリタグも用意してみました。
tagsを使ってみての感想
とても良いです。しかし使ってもらうにはある程度tagの設定を入れる必要があります。面倒ですね。ただこの面倒な作業はAIに任せちゃえばよいでしょう。
課題としてあるのはstorybook側の仕様変更です。中間層があるので吸収できそうですが、場合によっては捨てるということも考えてます。
それとtagのつけ忘れですが、チームで「storybookのレビューはclaude codeのカスタムコマンドを使うこと」とルール化すれば拾えるので問題にはならないと思っています。(もちろんカスタムコマンドは作る必要あります)
以上です。
フロントエンドの学習について 白木
皆さんはどうやって言語や技術の勉強をしていますか? フロントエンドを触って1年半の未熟者ですが、おすすめの学習方法と学習練度とやるべき行動を考えてみました。
学習法
AIを教師として使うことは皆さんやっていると思います。いつでもどこでも絶対に怒らない先生というのは心理的安全性が高く便利な存在です。 しかし、ハルシネーションを起こすことがあるので、下記を試すと正しい回答が得られやすくなると思います。
MCP Serverで公式ドキュメントを引用して回答させる
例えば Material UI について調べたいときは Material UI の MCP Server に繋ぐことで、公式のドキュメントを引用して回答してくれます。
評価の高い記事や公開しているルールファイルを利用する
高い評価を得ている記事や公開されたルールファイルをAIに参照させることで、これらのソースに基づいて回答してくれます。 Cursor の @Docs 機能を使うとドキュメントをインデックス化して参照してくれるため、プロンプトにURLを入れて質問した時よりも回答の質や速度も速いと思います。
フロントエンドのレベルとやるべきこと
この図を作っている私としては、レベル2にいるかなと思います。 次のレベル3に行くにはフレームワークやOSSのコードやドキュメントを読む量が足りていないと思います。
まとめ
ただ、こうも思います。フロントエンドに強くなりたいからエンジニアをしているのか?違います。 便利にしたいことがあったり、面白そうだったりするのにフロントエンドの技術力が足りないから強くなりたいのだと思います。 つまり、今与えられている仕事やプロジェクトをやり切ることが、不便を便利に変えることにつながります。また、面白そうな技術に挑戦することで、弊社の経営理念である 世界の人々に大きく良い影響を与えるという目標を達成できると思っています。
スマホWebアプリのスクロール固定画面で部分的にスクロールを許可する方法 佐川
スマホ向けWebアプリを作成していると、 「この画面ではスワイプで操作させたい要素があるけど、画面としてはスクロール禁止にしたい・・・」 みたいなことがたまにあるかもしれません。 スワイプ操作のつもりが意図せずスクロールしてしまうというのは利用者には非常にストレスですが、メニューやリストのように、どうしてもスマホサイズの画面ならスクロールさせたい要素というのはあるもの。
こういう時はCSSのoverflow: hidden;で画面全体をスクロール不可にして・・・
html, body { overflow: hidden; }
と行きたいところですが、iOSだとこれがうまくいきません。 iOSのSafariには、スクロール時に終端を超えてスクロールした際にゴムみたいに伸びるバウンススクロールという挙動がありますが、これがoverflow: hidden;では消えないんです。 なので、スワイプした際のイベント自体に手を付けてしまいましょう。
スクロール制御
画面全体のスクロールを止めつつ、特定の要素だけはスクロール許可したい場合、 「スクロールを許可するクラスを作成して、それ以外の要素のスクロールはキャンセルする」 という形をとるのがいいでしょう。 今回はcanScrollとします。
TypeScript:
const handleTouchMove = (e: TouchEvent): void => { const target = e.target as HTMLElement; const isInScrollableArea = target.closest('.canScroll'); if (!isInScrollableArea) { e.preventDefault(); // スクロールのイベントを破棄 } // .canScrollエリア内なら何もしない = スクロール許可 }; document.addEventListener('touchmove', handleTouchMove, { passive: false });
CSS:
.canScroll { overflow-y: auto; /* スクロールを有効化 */ overscroll-behavior: contain; /* スクロール連鎖を防ぐ */ -webkit-overflow-scrolling: touch; /* iOS慣性スクロール */ }
closest()は指定した要素の親要素までさかのぼって検索してくれるので、canScrollの中の要素であれば全てスクロール可能になります。
<div class="canScroll" style="max-height: 300px;"> <p>このテキストをタッチしても</p> <p>ちゃんとスクロールできる!</p> <p>内容が多ければスクロールされます</p> <!-- ... さらにコンテンツ ... --> </div>
仕組み
JavaScript: .canScrollエリア外のタッチ操作をpreventDefault()で無効化 CSS: overscroll-behaviorで、canScrollエリア内で終端に達した時に、親要素(画面全体)へのスクロール伝播するのを防止
この2つの組み合わせで、快適なスマホWebアプリを実現できます!
注意点
追加したイベントリスナーは、絶対に必ず アンマウント時に消しておきましょう。
// クリーンアップ document.addEventListener('touchstart', handleTouchStart, { passive: false });
また、overscroll-behaviorは、iOS Safari 16 (Release date: 2022-09-12) から対応であるため、古いバージョンでは機能しない可能性があります。
こちらに対応する場合は、スクロールの終端判定も含めて実装する必要があります。(TouchStartとの差分を計測するなど)
開発者ツールのネットワークタブを見やすくする設定 菅
フロントエンドエンジニアかどうかを問わず、皆様ブラウザの開発者ツールを使うことは多いかと思います。 特にネットワークタブは、APIリクエストの確認やパフォーマンス分析に欠かせないツールです。
今回は、ネットワークタブをより使いやすくするための設定を2つ紹介します。日々の開発効率が少しでも上がればうれしいです。 なお、この記事で使用している画像はmacOS版のMicrosoft Edgeのものですが、Google Chromeでも同様の設定が可能です。
リソースでのフィルタ
開発者ツールのネットワークタブを開くと、画像、CSS、JavaScript、APIリクエストなど、様々な種類の通信が混在して表示されます。特にページの初期読み込み時には数十から数百のリクエストが発生することもあり、目的の通信を見つけるのが困難です。 そこで活用したいのが、ネットワークタブ左上にあるフィルタ機能です。フィルタアイコンをクリックすると、リソースタイプごとのフィルターボタンが表示されます。
主要なフィルターボタンには以下があります
- Fetch/XHR: APIリクエストなどの非同期通信
- JS: JavaScriptファイル
- CSS: スタイルシート
- Img: 画像ファイル
これらのフィルターボタンをクリックすることで、該当するリソースタイプの通信のみに絞って確認できます。 特にフロントエンド開発では、バックエンドAPIとの通信を確認する機会が多いため、Fetch/XHRフィルターを使う頻度が高いです。APIのレスポンスやステータスコードを素早く確認したいときに非常に便利です。
リクエストの行を広く見せる
リクエストの数が多い場合や、似たようなエンドポイントへのリクエストが並んでいる場合、リクエストURLの全体が省略されてしまい、どのリクエストなのか判別しづらいことがあります。
例えば、以下のようなエンドポイントがあった場合:
/api/v1/users/123/posts/api/v1/users/123/comments/api/v1/users/123/likes
デフォルトの表示では末尾が省略され、一見して区別がつきにくくなります。
このような場合に便利なのが「Big request rows」の設定です。この設定を有効にすると、リクエスト行の高さが広がり、省略されていたURLの部分も表示されるようになります。
設定方法
ネットワークタブ右上の歯車アイコン(設定ボタン)を押下し、表示されたメニューから「Big request rows」にチェックを入れるだけです。
設定前
URLが省略されており、リクエスト先の詳細が分かりづらい状態です。
設定後
URLの全体が表示され、各リクエストの識別が容易になりました。
その他の便利な設定
ネットワークタブには他にも便利な設定があります:
- Preserve log: ページ遷移後も通信履歴を保持
- Disable cache: キャッシュを無効化して常に最新のリソースを取得
- Throttling: ネットワーク速度を制限してモバイル環境をシミュレート
これらも併せて活用すると、さらに開発効率が向上します。
まとめ
今回紹介した2つの設定は、どちらも数秒で設定できる簡単なものです。しかし日々の開発作業において地味に効いてくる便利な機能です。 特にAPIとの通信を頻繁に確認する開発者の方は、ぜひ試してみてください。
おわりに
ReactやVue.jsなどの最新フロントエンド技術を活用し、UI/UXを追求するプロダクト開発に取り組んでいます。フロントエンド大好きな仲間を募集しています。興味がある方は、ぜひこちらからご応募ください!



