🤖
hono + vite + D1 + pages + preact.js、何か作る
概要
hono + vite + D1の、例になります
- 前の、hono + vite + pagesの続編になります。
- d1 + honoのバインディング設定は、pages画面から設定すると、接続できました
- フルスタック構成
環境
- hono: 3.9.0
- vite: 4.5.0
- preact: 10.18.1
- cloudflare pages
- cloudflare d1
作成したコード
- vite.config.ts
vite.config.ts
import { defineConfig } from 'vite'
import { resolve } from 'path'
import devServer from '@hono/vite-dev-server'
import pages from '@hono/vite-cloudflare-pages'
export default defineConfig(({ mode }) => {
if (mode === 'client') {
return {
build: {
lib: {
entry: [
'./src/client.ts',
'./src/client/Page2.ts',
'./src/client/Page3.ts',
'./src/client/Page4.ts',
],
formats: ['es'],
fileName: '[name]',
},
rollupOptions: {
output: {
dir: './dist/static'
}
},
emptyOutDir: false,
copyPublicDir: false
}
}
} else {
return {
plugins: [
pages(),
devServer({
entry: 'src/index.tsx',
cf: {
d1Databases: ['DB'],
d1Persist: true
}
})
]
}
}
})
- package.json
{
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build && vite build --mode client",
"preview": "wrangler pages dev dist",
"deploy": "$npm_execpath run build && wrangler pages deploy dist"
},
"dependencies": {
"hono": "^3.9.0",
"htm": "^3.1.1",
"preact": "^10.18.1"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20230914.0",
"@hono/vite-cloudflare-pages": "^0.0.2",
"@hono/vite-dev-server": "^0.0.12",
"@preact/preset-vite": "^2.6.0",
"vite": "^4.5.0",
"wrangler": "^3.14.0"
}
}
api参考
- src/index.ts
index.ts
app.get('/api/test1', async (c) => {
const result = await c.env.DB.prepare(`SELECT * FROM Task ORDER BY id DESC`).all();
console.log(result.results);
return Response.json({ret: "OK", data: result.results});
});
-
List, 追加画面
-
pages/test4/App.tsx
App.tsx
import type { FC } from 'hono/jsx'
import { html } from 'hono/html'
import {Layout} from '../layout';
//
const Test4: FC = (props) => {
console.log(props);
//
return (
<Layout>
<h1>Test4</h1>
<p>SSR-List</p>
<hr class="my-2" />
<label>Title:</label>
<input type="text" id="title"
class="border border-gray-400 rounded-md px-3 py-2 w-full focus:outline-none focus:border-blue-500"/>
<br /><button id="save" class="btn-purple ms-2 my-2">Save</button>
<hr class="my-2" />
<div id="root"></div>
<ul>
{props.items.map((item) => {
return (
<li key={item.id}>
<a href={`/test/${item.id}`}><h3>{item.title}</h3></a>
<p>id={item.id}</p>
<hr />
</li>
);
})}
</ul>
<hr />
{/* JS */}
{import.meta.env.PROD ? (
<script type="module" src="/static/Page4.js"></script>
) : (
<script type="module" src="/src/client/Page4.ts"></script>
)}
</Layout>
)
}
export default Test4;
- 追加、ロジック部分
- client/Page4.ts
Page4.ts
console.log("#Page4.client.ts");
//
import { h, Component, render } from 'preact';
import htm from 'htm';
//const html = htm.bind(h);
//const elem = document.getElementById("root");
//
const Page4 = {
/**
*
* @param
*
* @return
*/
addItem : async function()
{
try{
let ret = false;
let titleValue = "";
const title = document.querySelector("#title") as HTMLInputElement;
if(title) {
titleValue = title.value;
}
const item = {
title: titleValue,
content: "",
}
console.log("title=", titleValue);
const body = JSON.stringify(item);
const res = await fetch("/api/test/create", {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: body
});
const json = await res.json()
console.log(json);
if (res.status !== 200) {
console.error("error, status <> 200");
throw new Error(await res.text());
}
if (json.ret !== "OK") {
console.error("Error, json.ret <> OK");
return ret;
}
ret = true;
return ret;
} catch (e) {
console.error("Error, addItem");
console.error(e);
throw new Error('Error , addItem');
}
},
/**/
initProc: function() {
//console.log("init");
//btn
const button = document.querySelector('#save');
button?.addEventListener('click', async () => {
const result = await this.addItem();
console.log("result=", result);
if(result === true) {
location.reload();
}
});
},
}
Page4.initProc();
Discussion