🤖

hono + vite + D1 + pages + preact.js、何か作る

2023/11/04に公開

概要

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

作成したコード

https://github.com/kuc-arc-f/hono_vite_11


  • 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