はじめに
技術部では、事業部横断的な仕事としてコーポレートサイトの運用も行っており、過去にはWordPress on EC2で運用されてきた弊社のWebメディア(Q by Livesense)を、Hugo on Clouflare(Workers & Pages)に移行した実績があります。
今回は、Q by Livesenseでの移行の経験を活かし、採用サイトの移行を実施したことについて詳しくお話しします。
移行前に困っていたこと
過去の記事にも書いていますが、WordPressの運用はとにかく大変でした。
管理画面で操作してコンテンツを差し替えるというのはWordPressの自然な管理方法ですが、このサイトもコンテンツとテーマの境界が曖昧だったために、変更すると問題となる部分を管理画面で変更してしまうこともありました。コンテンツ修正の過程で、バグとなるHTMLコードが混入してしまうことも多々ありました。
また、弊社の構成では、リリースに際してサーバーにSSHして作業する必要がある部分がありました。ちょっとした変更であってもコンテンツ管理者はエンジニアに相談して、管理画面だけで変更できる作業か、エンジニアが作業する必要があるものか、確認する必要がありました。
これらの問題により、コンテンツ管理者とエンジニアの双方にとって負担があり、小さな変更をするのに腰が重くなる原因となっていました。
モダンな開発と同様に、コードに書いてGitで管理し、CI/CDにより堅牢なコードを保ち、プルリクエストを通じて議論や修正をできるようにしたいと、常々考えていました。
移行によって得たもの
AIネイティブな環境になった
近年は生成AIの発展により、職種にかかわらずコードを変更できるようになってきました。そのとき、プレビューで変更結果を確認できるというのが素早いデリバリーのために非常に重要になっています。
弊社もAIエージェントのDevinを導入しており、コーポレートサイト関連のリポジトリについては、エンジニア職以外の人であっても(Git操作が分からなくても)GitHubにPull Requestを気軽に出せるような環境を整えています。しかし、WordPressの場合はどうしても、実際にサイトに適用しなければプレビューができない問題があります。そして上述の通り、デリバリーに時間がかかる・腰が重いというのが大きな課題でした。
この点、Cloudflare Workers & Pagesにはプレビュー環境が標準で用意されていて、Pull Requestを出したらその場でプレビュー環境が立ち上がります。DevinなどのAIエージェントに指示して、人事担当者自ら資料や文言を差し替えてもらったり、デザイナー自らデザインの変更を行ったり、というのがやりたかったことです。
コードを変更したい・プレビューが見たいという要求のためだけに間に作業者としてのエンジニアを挟むのは効率が非常に悪く、意図が誤って伝わることもあります。今回の移行によって、サイトを運用している人・何かを変更したい人が自らAIエージェントを利用してコードを変更し、プレビューを確認して、リリースまで行うというフローが整いました。



Hugo + Cloudflare Pagesという構成が標準的な技術になった
今回の移行により、コーポレートサイトであるQ by Livesense、エンジニアのイベント用のティザーサイト(yabaibuki.dev)、エンジニアハンドブック、そしてこの採用サイトの計4つのサイトが「Hugo + Cloudflare Pages」という構成で統一されました。
これにより、技術スタックが標準化され、運用・保守の効率が大幅に向上しました。誰でもスムーズに更新作業が行える体制が整ったことは、デリバリーのスピードアップに大きく寄与しています。
パフォーマンスが改善した

Q by Livsesnseの移行のときと同様に、静的サイト化したことで、動的にHTMLを生成するWordPressに比べて表示速度が上がりました。さらにCSSやJSのminifyやキャッシュバスターの実装、Cloudfrale PagesでのブラウザキャッシュのTTLの設定、アクセシビリティ周りの実装など、全体的なパフォーマンスの改善を加えたため、Lighthouseでパフォーマンスのスコアが上がりました。

移行において大変だったこと
ここでは、記録としてHugoへの移行で苦労したことを記載します。
今回の移行後のHugo + Cloudflare Pagesという構成は、すでにQ by Livesenseなどで採用していた構成と同様のため経験があり、僅かな作業期間で移行できました。 具体的には、AIエージェントを使ってHTMLを出力し、そのHTMLをHugoの形式に合わせて加工するという作業です。それにはたいして時間がかからず、第一弾として見た目でそれらしいものは3日ほどで作ることができました。
しかし、今回の移行ではAIコーディングに適したリポジトリにすることが1つの重要な目標でした。
そのためにCI/CDを整えることが必須であり、AIが作業しやすい実装にすることが重要でした。それがいろいろ大変でした。
長年のツギハギ運用の負債が溜まっていた
弊社の採用サイトのデザイン・コンセプトは、2017年に初回リリース、2024年にプチリニューアルを行っています。その間にコンテンツが差し替わっていったのはもちろん、WordPressのメジャーバージョンアップ、利用しているプラグインのバージョンアップ、動作するEC2のリニューアルなど、コンテンツ以外の大きなバージョンアップも行われています。
2017年当時と2025年現在では、CSSで使える記法、JavaScriptで利用できるライブラリが異なります。しかし過去の変更では、それらに包括的なアップデートは加えず、必要な変更のみ行う形でメンテされてきました。その結果、ツギハギのSass/JavaScriptとたくさんのデッドコードという負債が誕生してしまいました。
さらに負債がありました。フロント資源は、当初は総合的なフレームワークで実装されてビルドして実際のCSS/JavaScriptを生成していました。しかし、時代経過とともにその総合的なフレームワークもメンテされなくなり、動作しなくなってしまいました。なお、総合的なフレームワークで実装されていたのは、フロント資源だけでなくコンテンツも一部含まれています。
これらの問題を解決するため、今回の移行作業では、まずは実際のWordPress上で動作するコード・・・つまり、
- WordPressを通して生成されたHTML
- Sassを変換したCSS
- 複数のJavaScriptを結合したJavaScript
の3つをスタート地点として、AIコーディングしやすい状態を目指して整理を進めました。
HTMLとCSSの整理
WordPress時代のSassは、いくつものコンポーネントに分けて記載されていました。今回Sassから生成されたCSSコードは1ファイルにまとめられて、5,000行以上ある状態でした。

Sassの(当時の)メリットの1つは、ネストできることです。しかし、弊社の採用サイトでは過度にネストが多用され、HTML要素でのセレクタが多用されていました。HTML要素でのセレクタは厄介で、優先順序が記載順序と一致せず、複雑になってしまっていました。
Sassのメリットに、ファイルを分割し再利用できること、コンポーネントを再利用できること(Mixin)も挙げられます。しかし、SassからCSSに変換した結果、これらの機能で同じようなスタイルがCSS内で複数回登場することで、整理する上ではかえって厄介になってしまいました。
1つのHTML要素に適用されるスタイルは、5,000行以上のCSSの中から複数箇所の記述を結合しなければわからないので、とても読解に苦労しました。CSSがそんな状態なので、stylelintの指摘事項は当初2,000個以上ありました。

こうなると、AIエージェントに作業させても全く正常な結果を生み出してくれません。行数が多すぎるためgrepとsedを駆使して編集を繰り返し、バグを生み出すような動作をしていました。仕方ないので、手動で整理を行いました。
これはもともとのSassのコードです。(かなり端折ってます)
.pageTop{
&-message{
.message-pgh{
span{
line-height: 3.0;
}
}
}
}
これをCSSにコンパイルすると、こうなります。
.pageTop-message .message-pgh span {
line-height: 3;
}
そのセレクタが示すHTMLの箇所にBEM記法でクラス名をつけました。
.top-message__span {
line-height: 3;
}
HTMLの構造でも、 div > div > div > div > … とひたすら divで構造を作っている部分が混乱しやすいため、適宜 section / header / main / article / footer などの別のHTML要素名で命名を変えていきました。
HTML構造の整理とBEM記法のクラス名付与を繰り返して、複雑な実装を変換していきました。
現在でもまだ全てを変換し終えたわけではないのですが、大部分のCSSセレクタのネストがなくなり、重複するセレクタもなくなり、CSSの見通しが良くなっています。最後にはstylelintの指摘数は0個になりました。
これによりGitHubリポジトリの Required Status Check としてstylelintを設定することもでき、AIエージェントにも「stylelintの指摘事項は対応すること」を指示できるようになりました。CSSとHTMLに関して、AI対応できたと言えます。
余談: 今思えば、このCSS整理の作業に関しては、Sassから移行を開始したほうがスムーズだった可能性はあります。
JavaScriptの整理
JavaScriptもツギハギの改修がされ続けた結果、古いライブラリや使っていない実装が残っていました。それらを整理し、フレームワークによって生成・結合されたJavaScriptを再度、可読性の高い形に分解していきました。
HTML/CSSの整理により、JavaScriptも連動して実装を修正する必要があったのですが、実装を直していると、動かなくなっていたアニメーションが発掘されました。
1つ1つ機能を復元すると、想像以上にアニメーションが多いサイトであったことがわかりました。バグを直すことで、不安定だったアニメーションも安定動作するようになりました。

デッドコードを削除し、本来デッドではなかったコードを復元し、lintでエラーにならない状態にしたことで、JavaScriptに関してもAIエージェントに作業依頼をしやすい状態になりました。
レイアウトの堅牢化
フロント資源の見通しが良くなった結果、色々なミスが気になり始めました。
例えば、ヘッダーでのこのようなズレが気になり始めました。

これは margin: 46px 0 0; をメディアクエリで margin-top: 26px; に上書きして、JavaScriptで transform: translateY(-10px); することで絶妙にズレているというものでした。
何を言っているんだ?って思うでしょう。本当の話です。
とにかくこのようなレイアウトが原因で、HTMLとCSSの整理をすればするほどズレが目立っていくので、flexなどを利用してレイアウトをやり直しました。

これを例として、多くのレイアウトを再配置しました。見た目は移行前のサイトにそっくりなのですが、コードでは劇的にレイアウトが堅牢になりました。
これでようやく、AIエージェント経由で「文字を1pt大きく」みたいな指示をした際に、連鎖的にレイアウトが崩壊する状況を脱しました。
おわりに
今回の採用サイトの移行プロジェクトは、単なる技術スタックの刷新に留まらず、長年の技術的負債の解消とエンジニア職以外の人も参加できる運用体制の構築という、2つの大きな成果を得ることができました。
今回の経験を通じて、AIネイティブな開発環境にするためには、地道な技術的負債の解消も含む人間も開発しやすい状態の構築が不可欠であることを実感しました。