背景
社内のあるwebサイトがCakePHP2系のViewテンプレートを利用しており、レガシーな構成になっていました。
そこでリプレイスを検討し技術選定をする上で、自分自身にも学びが多かったためまとめたいと思います。
技術選定の流れ
まずは簡単に流れを整理します。
1.判断軸の整理
このwebサイトでは何を重要視するか、リプレイス作業をするメンバーの技術スタックなど判断基準になるものを洗い出す
2.技術リサーチ
利用可能な技術の調査をし、各技術の特性、メリット、デメリットを洗い出す
3.プロトタイプの作成
簡単にプロトタイプを作成し、実際に触ってみての感想を出してみる
4.比較
以下の観点で比較をしていく
- パフォーマンス
- セキュリティ
- メンテナンス
5.意思決定
予算やリソースなどを確認しつつ、メンバーで話し合い技術選定をする
実際にどのようにやったか
1.判断軸
今回のwebサイトで以下のようなことを重視した。
- SEO対策が必要 → SSR(サーバーサイドレンダリング)が必須
- 時間やコストをかけづらい → リターンが少ないため低コストで実施
- DBからデータを取得して描画する簡易的なシステム
- 並行処理でデータ取得が可能であれば速度向上が見込める
- 将来的に静的ページにリプレイスする可能性を考慮
2.技術リサーチ
メリット | デメリット | |
---|---|---|
Next.js | 学習コストが低い、情報が豊富、複雑なサイト向け、SSR・SSGサポート | バージョンアップにコストがかかる、オーバースペック |
Nuxt.js | PWA対応が簡単 | Vue.jsベースのため学習コストが高い |
Gatsby | GraphQLとの連携が強い | プラグインが少ない、静的サイト向け |
Remix | Web標準に準拠、SSRサポート | SSGがサポートされていない |
SvelteKit | 高速、TypeScript対応、SSR・SSGサポート | 情報が少ない、独自のコンテキストやストアが必要 |
Astro | SSGが強い、TypeScript対応 | 情報が少ない |
inertiajs | フロントとサーバーサイドを繋ぐ、CakePHP5でも使用可能 | 構成が複雑、情報が少ない |
3.プロトタイプの作成
Next.jsとRemixが候補に残ったため、簡単にプロトタイプを作成してみました。
Next.js
import { PrismaClient } from '@prisma/client';
import Link from 'next/link';
export default async function getServerSideProps() {
const prisma = new PrismaClient()
const questions = await prisma.questions.findMany({
where: {
id: {
in: [1, 2, 3],
},
},
});
// questionsを3件表示する
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
{questions?.map((question, index) => (
<Link key={question.id} href={`/questions/${question.id}`}>
<div className="question-item">
<h2>{question.name}</h2>
<p>{question.content.slice(0, 100)}...</p>
</div>
</Link>
))}
</main>
);
}
-
データベースへの接続はPrismaというORMを使うと良さそう
-
ルーティングがディレクトリでできるので楽(ディレクトに[]入れるのとか慣れないけど)
- ファイル名と関数が一致していないとnot foundになるの注意(ここでハマってたあ)
-
SSRはこんな感じの記述で割と簡単にできそう
getServerSideProps()
-
Reactベースなので比較的書きやすい
-
Next.js14は比較的新しいのでChatGPTなどの情報は古いので注意
- 結構書き方が変わってそう
Remix
import { prisma } from "../../../prisma/db.server";
export async function call() {
return await prisma.questions.findMany({
where: {
id: {
in: [1, 2, 3],
},
},
});
}
import { json } from "@remix-run/node"
import { useLoaderData } from "@remix-run/react"
import { call } from "./index.server"
import { PrismaClient } from "@prisma/client"
import { Question } from '../../types'
export const loader = async () => {
const posts = await call()
return json(posts)
}
export default function QuestionIndex() {
const questions: Question[] = useLoaderData()
return (
<div>
<h1>questions</h1>
<ul>
{questions.map((question: Question) => (
<li key={question.id}>
<p>{question.content}</p>
</li>
))}
</ul>
</div>
)
}
- SSGを対応していない
- ルーティングにやり方が何種類かありそう→ https://remix.run/docs/en/main/file-conventions/routes#splat-routes
- index.server.ts バックエンド
- route.tsx フロントエンド
- prismaを利用できて基本Next.jsと構成は似ている
4.比較
Next.js
- メリット: 情報量が多く、SEO対策に有利、ハイブリッドレンダリング、ファイルベースのルーティングがわかりやすい
- デメリット: コードベースが大きくなりやすい、メジャーアップデートが頻繁にあるため保守運用が大変
Remix
- メリット: ビルドが高速、ルーティングが柔軟、コードベースが小さくなりやすい
- デメリット: 情報量が少ない、SSGがない、CSS in JSが非推奨
CakePHP + テンプレートエンジン
- メリット: 現状使っているので慣れているので開発しやすい
- デメリット: SSGには特別な設定が必要、コンポーネントベースではないため再利用性が低い、動的なUIの構築が複雑
5.意思決定
今回は上記比較をした結果、このwebサイトの特徴と規模などを考慮しRemixに決定しました。
- メインのプロダクトではないため保守運用にコストをかけたくない
- SSRができないのは懸念になるがSSGができないのは現状そこまでの懸念にはならない
- TypeScriptで完結するので開発しやすい
- 現状と違う新しい技術に挑戦できる
感想
今回初めての技術選定に挑戦し、正直とても難しかったです。どこから始めればいいかわからなかったので、メンバーや当初このwebサイト開発に関わった方などヒヤリングから始めました。
結論を出すまでは何がいいかわからなかったのですが、実際に手を動かして想像をより深めてみたり、1つ1つの技術の特徴を押さえていくことで比較しやすくなりました。
今後技術選定をする機会はまた訪れると思うので、ぜひ活かしていきたいです!