Open1

hono + vite + pages + preact.js、typescript の例

knaka Tech-Blogknaka Tech-Blog

概要

hono + pagesで、最近はvite使えるようですので、preact.js + typescript試してみました


環境

  • preact: 10.18.1
  • htm: 3.1.1
  • hono: 3.9.0
  • vite: 4.5.0
  • cloudflare pages

作成したコード

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


  • 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"
  }
}


フロントbuild

  • client modeで、ts buildできるようでした。

  • lib>entryに、配列で、複数ファイル指定すると、ビルドできました

  • 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',
          ],
          formats: ['es'],
          fileName: '[name]',
        },
        rollupOptions: {
          output: {
            dir: './dist/static'
          }
        },
        emptyOutDir: false,
        copyPublicDir: false
      }
    }
  } else {
    return {
      plugins: [
        pages(),
        devServer({
          entry: 'src/index.tsx'
        })
      ]
    }
  }
})


  • index.tsx
index.tsx
import { Hono } from 'hono'

const app = new Hono()

import Test1 from './pages/test/App';
import Test3 from './pages/test3/App';

//
app.get('/', (c) => {
  return c.render(<h1>Hello!</h1>)
})
/* test */
app.get('/test1', async (c) => { 
  return c.html(<Test1 items={[]} />);
});
app.get('/test3', async (c) => { 
  return c.html(<Test3 items={[]} />);
});

export default app

  • pages/test3/App.tsx
App.tsx
import type { FC } from 'hono/jsx'
import { html } from 'hono/html'
//
const Test3: FC = (props) => {
    return (
    <html>
    <body>
        <h1>Test3</h1>
        <div id="root"></div>
        <hr class="my-2" />
        <div id="root2"></div>
        {/* JS */}
        {import.meta.env.PROD ? (
            <script  type="module" src="/static/Page3.js"></script>
        ) : (
            <script type="module" src="/src/client/Page3.ts"></script>
        )}        
    </body>
    </html>
    )
}
export default Test3;


  • /src/client/Page3.ts
Page3.ts

console.log("#Page3.client.ts");
//
import { h, Component, render } from 'preact';
import htm from 'htm';

const html = htm.bind(h);
const elem = document.getElementById("root");

const li = [];
const data = ['hoge1', 'hoge2', 'hoge3'];
for (var i in data) {
    li.push(html`<h1>Hello[ ${data[i]}]  - 000</h1>`);
};
render(li, elem);
//
const li2 = [];
li2.push(html`<h1 class="text-3xl">li_2</h1>`);
li2.push(html`<hr class="my-2" />`);
for (var i in data) {
    li2.push(html`<h1>li2-Hello[ ${data[i]}]  - 111</h1>`);
};
li2.push(html`<hr class="my-2" />`);
render(li2, document.getElementById("root2"));


build

yarn build

  • build Log
$ yarn build
yarn run v1.22.19
warning package.json: No license field
$ vite build && vite build --mode client
vite v4.5.0 building SSR bundle for production...
✓ 31 modules transformed.
dist/_worker.js  24.42 kB
✓ built in 222ms
vite v4.5.0 building for client...
✓ 5 modules transformed.
dist/static/client.js   0.03 kB │ gzip: 0.05 kB
dist/static/Page2.js    0.15 kB │ gzip: 0.12 kB
dist/static/Page3.js   15.44 kB │ gzip: 5.38 kB
✓ built in 124ms
Done in 0.69s.

tree

$ cd src
$ tree .
.
├── client
│   ├── Page2.ts
│   └── Page3.ts
├── client.ts
├── index.tsx
├── pages
│   ├── Page1.ts
│   ├── test
│   │   └── App.tsx
│   ├── test3
│   │   └── App.tsx
│   └── test4
│       └── App.tsx
└── renderer.tsx

5 directories, 9 files

deploy

yarn build
yarn deploy