feat: migrate frontend to Next.js

This commit is contained in:
2025-06-04 09:08:32 +09:00
parent 25c771b90b
commit 1defdb8bef
5 changed files with 48 additions and 19 deletions

View File

@ -2,9 +2,10 @@
"name": "podcast-frontend",
"version": "1.0.0",
"scripts": {
"dev": "bun dev",
"build": "bun build",
"start": "bun start"
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"react": "^18.0.0",
@ -17,7 +18,6 @@
"bun-types": "^0.1.0",
"@types/bun": "latest"
},
"module": "src/index.tsx",
"type": "module",
"private": true
}

14
frontend/src/app/page.tsx Normal file
View File

@ -0,0 +1,14 @@
import React from "react";
import FeedList from "../components/FeedList";
import EpisodeList from "../components/EpisodeList";
export default function Home() {
return (
<div style={{ padding: "20px", fontFamily: "sans-serif" }}>
<h1> </h1>
<FeedList />
<hr style={{ margin: "20px 0" }} />
<EpisodeList />
</div>
);
}

View File

@ -1,14 +1,20 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"jsx": "react-jsx",
"strict": true,
"moduleResolution": "Node",
"esModuleInterop": true,
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"outDir": "build"
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"outDir": "dist"
},
"include": ["src"]
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

View File

@ -2,16 +2,23 @@
"name": "podcast-generator",
"version": "1.0.0",
"scripts": {
"start": "bun run server.ts"
"start": "bun run server.ts",
"build:frontend": "cd frontend && bun build"
},
"dependencies": {
"@aws-sdk/client-polly": "^3.823.0",
"next": "^14.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"openai": "^4.104.0",
"rss-parser": "^3.13.0"
},
"type": "module",
"devDependencies": {
"@types/bun": "latest"
"typescript": "^5",
"@types/bun": "latest",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0"
},
"private": true,
"peerDependencies": {

View File

@ -93,21 +93,23 @@ serve({
}
}
// Serve /build/* from frontend/build (compiled JS/CSS)
if (pathname.startsWith("/build/")) {
const assetPath = pathname.substring("/build/".length);
const filePath = path.join(frontendBuildDir, assetPath);
// Next.jsの静的ファイルを提供
if (pathname.startsWith("/_next/")) {
const assetPath = pathname.substring("/_next/".length);
const filePath = path.join(frontendBuildDir, "_next", assetPath);
try {
const file = Bun.file(filePath);
if (await file.exists()) {
let contentType = "application/octet-stream";
if (filePath.endsWith(".js")) contentType = "application/javascript; charset=utf-8";
else if (filePath.endsWith(".css")) contentType = "text/css; charset=utf-8";
else if (filePath.endsWith(".png")) contentType = "image/png";
else if (filePath.endsWith(".jpg") || filePath.endsWith(".jpeg")) contentType = "image/jpeg";
// 必要に応じて他のMIMEタイプを追加
return new Response(file, { headers: { "Content-Type": contentType } });
}
} catch (e) {
console.error(`Error serving file from frontend build dir ${filePath}:`, e);
console.error(`Error serving Next.js static file ${filePath}:`, e);
}
}