Closed1
Preact.js + vite + express, CMS表示系の作成
概要
Preact.js + express SSR(react-dom/server)で、CMS表示のメモになります。
- 主に、SSRになります。一部CSRになります。
- 編集機能は、前の複数blog対応 Headless CMSと連携します (CF-pages)
- テストは、vercelにデプロイする形です。
[ 公開: 2024/03/02 ]
環境
- Preact.js
- vite: 5
- express
- vercel
関連
- 前のexpress 構成関連です。
作成したコード
-
詳細 : MD変換ライブラリ使います。
-
pages/posts/show/App.tsx
App.tsx
export default function PostShow(props: any) {
console.log("#taskShow");
const content = marked.parse(props.item.content);
//console.log(content);
//
return (
<Layout title="Show">
<div className="post_show_wrap container bg-white mx-auto mt-14 mb-8 px-8 py-4">
<a href="/" className="btn-outline-purple ms-2 my-0"
>back</a>
<hr className="my-4" />
<div id="root"></div>
<h1 className="text-4xl font-bold">{props.item.title}</h1>
<p>id: {props.item.id}, {props.item.createdAt}</p>
<hr />
<div dangerouslySetInnerHTML={{ __html: content }} id="content_html"
className="mb-8" />
<hr className="my-12" />
</div>
<style>{`
.post_show_wrap {min-height : 600px;}
`}
</style>
</Layout>
)
};
- Top: pages/posts/App.tsx
App.tsx
export default function Page(props: any) {
//console.log(props.site);
if(props.page){
nextPage = Number(props.page) + 1;
beforePage = Number(props.page) - 1;
if(beforePage <= 1) { beforePage = 1;}
}
//
return (
<Layout>
<div className="text-center py-16 bg-gray-400 text-white mt-10">
<h1 className="text-4xl font-bold">{props.site.name}</h1>
</div>
<input type="text" className="d-none" id="item_id" defaultValue={props.id} />
<div className="col-md-6 text-end bg-white py-1">
<span className="search_key_wrap">
<input type="text"
className="mx-2 border border-gray-400 rounded-md px-3 py-2 focus:outline-none focus:border-blue-500"
name="searchKey" id="searchKey"
placeholder="Title search" />
</span>
<button className="ms-2 btn-outline-purple" id="btn_search"
>Search</button>
</div>
<div className="post_list_wrap container mx-auto my-2 px-2">
{props.items.map((item: any) => {
return (
<div key={item.id} className="rounded-md bg-white my-2 p-4">
<div className="flex flex-row">
<div className="flex-1 p-2 m-1">
<a href={`/posts/${item.id}`}><h3 className="text-3xl font-bold"
>{item.title}</h3></a>
<p>ID: {item.id}, {item.createdAt}</p>
</div>
<div className="flex-1 p-2 m-1 text-end">
<a href={`/posts/${item.id}`}>
<button className="btn-outline-purple ms-2 my-2">Show</button>
</a>
</div>
</div>
</div>
);
})}
</div>
<div id="app"></div>
{(process.env.NODE_ENV === "develop") ? (
<script type="module" src="/static/Top.js"></script>
): (
<script type="module" src="/public/static/Top.js"></script>
)}
<hr className="my-8" />
<style>{`
.post_list_wrap {min-height: 500px;}
`}</style>
</Layout>
)
}
- src/index.ts
- headless CMS APIと、連携します。
- API接続先は、 .envから取得します。
index.ts
import express from 'express';
import { renderToString } from 'react-dom/server';
const app = express();
....
import PostsIndex from './pages/posts/App';
import PostsShow from './pages/posts/show/App';
app.get('/',async (req: any, res: any) => {
try {
const site = await siteRouter.get();
const items = await postRouter.get_list_page(Number(1));
res.send(renderToString(PostsIndex({items: items, page: 1, site: site})));
} catch (error) { res.sendStatus(500); }
});
.env
VITE_SITE_ID=1
VITE_API_URL=http://localhost
VITE_API_KEY="123"
- top
このスクラップは2024/04/14にクローズされました