feat: Implement frontend build and server configuration for Vite and React
This commit is contained in:
13
frontend/index.html
Normal file
13
frontend/index.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ja">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>ポッドキャスト管理画面</title>
|
||||||
|
<meta name="description" content="RSSフィードから自動生成された音声ポッドキャストを再生・管理できます。" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
frontend/src/App.tsx
Normal file
12
frontend/src/App.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import './app/globals.css';
|
||||||
|
import RootLayout from './app/layout';
|
||||||
|
import Home from './app/page';
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<RootLayout>
|
||||||
|
<Home />
|
||||||
|
</RootLayout>
|
||||||
|
);
|
||||||
|
}
|
9
frontend/src/main.tsx
Normal file
9
frontend/src/main.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
@ -8,15 +8,8 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: "dist",
|
outDir: "dist",
|
||||||
// distフォルダにビルドされるので、distをベースパスにする
|
|
||||||
assetsDir: '',
|
|
||||||
// dist配信を前提にパスを調整
|
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
input: "index.html",
|
||||||
entryFileNames: `assets/[name].js`,
|
|
||||||
chunkFileNames: `assets/[name].js`,
|
|
||||||
assetFileNames: `assets/[name].[ext]`,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
16
server.ts
16
server.ts
@ -20,7 +20,7 @@ db.exec(fs.readFileSync(path.join(projectRoot, "schema.sql"), "utf-8"));
|
|||||||
|
|
||||||
// 静的ファイルパスの設定
|
// 静的ファイルパスの設定
|
||||||
const frontendPublicDir = path.join(projectRoot, "frontend", "public");
|
const frontendPublicDir = path.join(projectRoot, "frontend", "public");
|
||||||
const frontendBuildDir = path.join(projectRoot, "frontend", ".next");
|
const frontendBuildDir = path.join(projectRoot, "dist");
|
||||||
const podcastAudioDir = path.join(projectRoot, "static", "podcast_audio");
|
const podcastAudioDir = path.join(projectRoot, "static", "podcast_audio");
|
||||||
const generalPublicDir = path.join(projectRoot, "public");
|
const generalPublicDir = path.join(projectRoot, "public");
|
||||||
|
|
||||||
@ -68,10 +68,12 @@ app.get("/_next/*", async (c) => {
|
|||||||
const file = Bun.file(filePath);
|
const file = Bun.file(filePath);
|
||||||
if (await file.exists()) {
|
if (await file.exists()) {
|
||||||
let contentType = "application/octet-stream";
|
let contentType = "application/octet-stream";
|
||||||
if (filePath.endsWith(".js")) contentType = "application/javascript; charset=utf-8";
|
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(".css")) contentType = "text/css; charset=utf-8";
|
||||||
else if (filePath.endsWith(".png")) contentType = "image/png";
|
else if (filePath.endsWith(".png")) contentType = "image/png";
|
||||||
else if (filePath.endsWith(".jpg") || filePath.endsWith(".jpeg")) contentType = "image/jpeg";
|
else if (filePath.endsWith(".jpg") || filePath.endsWith(".jpeg"))
|
||||||
|
contentType = "image/jpeg";
|
||||||
return c.body(file, 200, { "Content-Type": contentType });
|
return c.body(file, 200, { "Content-Type": contentType });
|
||||||
}
|
}
|
||||||
return c.notFound();
|
return c.notFound();
|
||||||
@ -94,7 +96,9 @@ app.get("/podcast.xml", async (c) => {
|
|||||||
try {
|
try {
|
||||||
const file = Bun.file(filePath);
|
const file = Bun.file(filePath);
|
||||||
if (await file.exists()) {
|
if (await file.exists()) {
|
||||||
return c.body(file, 200, { "Content-Type": "application/xml; charset=utf-8" });
|
return c.body(file, 200, {
|
||||||
|
"Content-Type": "application/xml; charset=utf-8",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Error serving podcast.xml ${filePath}:`, e);
|
console.error(`Error serving podcast.xml ${filePath}:`, e);
|
||||||
@ -104,7 +108,7 @@ app.get("/podcast.xml", async (c) => {
|
|||||||
|
|
||||||
// フォールバックとして index.html(ルートパス)
|
// フォールバックとして index.html(ルートパス)
|
||||||
app.get("/", async (c) => {
|
app.get("/", async (c) => {
|
||||||
const indexPath = path.join(frontendBuildDir, "server", "app", "index.html");
|
const indexPath = path.join(frontendBuildDir, "index.html");
|
||||||
const file = Bun.file(indexPath);
|
const file = Bun.file(indexPath);
|
||||||
if (await file.exists()) {
|
if (await file.exists()) {
|
||||||
console.log(`Serving index.html from ${indexPath}`);
|
console.log(`Serving index.html from ${indexPath}`);
|
||||||
@ -146,5 +150,5 @@ serve(
|
|||||||
},
|
},
|
||||||
(info) => {
|
(info) => {
|
||||||
console.log(`Server is running on http://localhost:${info.port}`);
|
console.log(`Server is running on http://localhost:${info.port}`);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user