mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
feat: add Hono example and guide. (#32614)
This commit is contained in:
1 parent
5c89b63b61
commit
8e67d1e0a7
15 files changed
+1775
No files matched your search
@@ -260,6 +260,7 @@ export const gettingstarted: NavMenuConstant = {
|
||||
{ name: 'React', url: '/guides/getting-started/quickstarts/reactjs' },
|
||||
{ name: 'NuxtJS', url: '/guides/getting-started/quickstarts/nuxtjs' },
|
||||
{ name: 'Vue', url: '/guides/getting-started/quickstarts/vue' },
|
||||
{ name: 'Hono', url: '/guides/getting-started/quickstarts/hono' },
|
||||
{ name: 'Flutter', url: '/guides/getting-started/quickstarts/flutter' },
|
||||
{ name: 'iOS SwiftUI', url: '/guides/getting-started/quickstarts/ios-swiftui' },
|
||||
{
|
||||
|
||||
@@ -121,6 +121,14 @@ pnpm add dotenv
|
||||
|
||||
</Tabs>
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="hono" label="Hono">
|
||||
|
||||
```bash .env
|
||||
SUPABASE_URL=your_supabase_project_url
|
||||
SUPABASE_ANON_KEY=your_supabase_anon_key
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
@@ -703,6 +711,126 @@ app.post("/hello-world", async function (req, res, next) {
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel id="hono" label="Hono">
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="server-client"
|
||||
queryGroup="environment"
|
||||
>
|
||||
<TabPanel id="server-client" label="Server Client">
|
||||
|
||||
Create a Hono middleware that creates a Supabase client.
|
||||
|
||||
```ts middleware/auth.middleware.ts
|
||||
import { createServerClient, parseCookieHeader } from '@supabase/ssr'
|
||||
import { SupabaseClient } from '@supabase/supabase-js'
|
||||
import type { Context, MiddlewareHandler } from 'hono'
|
||||
import { env } from 'hono/adapter'
|
||||
import { setCookie } from 'hono/cookie'
|
||||
|
||||
declare module 'hono' {
|
||||
interface ContextVariableMap {
|
||||
supabase: SupabaseClient
|
||||
}
|
||||
}
|
||||
|
||||
export const getSupabase = (c: Context) => {
|
||||
return c.get('supabase')
|
||||
}
|
||||
|
||||
type SupabaseEnv = {
|
||||
SUPABASE_URL: string
|
||||
SUPABASE_ANON_KEY: string
|
||||
}
|
||||
|
||||
export const supabaseMiddleware = (): MiddlewareHandler => {
|
||||
return async (c, next) => {
|
||||
const supabaseEnv = env<SupabaseEnv>(c)
|
||||
const supabaseUrl = supabaseEnv.SUPABASE_URL
|
||||
const supabaseAnonKey = supabaseEnv.SUPABASE_ANON_KEY
|
||||
|
||||
if (!supabaseUrl) {
|
||||
throw new Error('SUPABASE_URL missing!')
|
||||
}
|
||||
|
||||
if (!supabaseAnonKey) {
|
||||
throw new Error('SUPABASE_ANON_KEY missing!')
|
||||
}
|
||||
|
||||
const supabase = createServerClient(supabaseUrl, supabaseAnonKey, {
|
||||
cookies: {
|
||||
getAll() {
|
||||
return parseCookieHeader(c.req.header('Cookie') ?? '')
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
cookiesToSet.forEach(({ name, value, options }) => setCookie(c, name, value, options))
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
c.set('supabase', supabase)
|
||||
|
||||
await next()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="hono-route" label="Route">
|
||||
|
||||
You can now use this middleware in your Hono application to create a server Supabase client that can be used to make authenticated requests.
|
||||
|
||||
```ts index.tsx
|
||||
import { Hono } from 'hono'
|
||||
import { getSupabase, supabaseMiddleware } from './middleware/auth.middleware'
|
||||
|
||||
const app = new Hono()
|
||||
app.use('*', supabaseMiddleware())
|
||||
|
||||
app.get('/api/user', async (c) => {
|
||||
const supabase = getSupabase(c)
|
||||
const { data, error } = await supabase.auth.getUser()
|
||||
|
||||
if (error) console.log('error', error)
|
||||
|
||||
if (!data?.user) {
|
||||
return c.json({
|
||||
message: 'You are not logged in.',
|
||||
})
|
||||
}
|
||||
|
||||
return c.json({
|
||||
message: 'You are logged in!',
|
||||
userId: data.user,
|
||||
})
|
||||
})
|
||||
|
||||
app.get('/signout', async (c) => {
|
||||
const supabase = getSupabase(c)
|
||||
await supabase.auth.signOut()
|
||||
console.log('Signed out server-side!')
|
||||
return c.redirect('/')
|
||||
})
|
||||
|
||||
// Retrieve data with RLS enabled. The signed in user's auth token is automatically sent.
|
||||
app.get('/countries', async (c) => {
|
||||
const supabase = getSupabase(c)
|
||||
const { data, error } = await supabase.from('countries').select('*')
|
||||
if (error) console.log(error)
|
||||
return c.json(data)
|
||||
})
|
||||
|
||||
export default app
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
|
||||
@@ -117,6 +117,13 @@ hideToc: true
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a NuxtJS app.',
|
||||
icon: '/docs/img/icons/nuxt-icon',
|
||||
},
|
||||
{
|
||||
title: 'Hono',
|
||||
href: '/guides/getting-started/quickstarts/hono',
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, secure it with auth, and query the data from a Hono app.',
|
||||
icon: '/docs/img/icons/hono-icon',
|
||||
},
|
||||
{
|
||||
title: 'RedwoodJS',
|
||||
href: '/guides/getting-started/quickstarts/redwoodjs',
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
title: 'Use Supabase with Hono'
|
||||
subtitle: 'Learn how to create a Supabase project, add some sample data to your database, secure it with auth, and query the data from a Hono app.'
|
||||
breadcrumb: 'Framework Quickstarts'
|
||||
hideToc: true
|
||||
---
|
||||
|
||||
<StepHikeCompact>
|
||||
|
||||
<StepHikeCompact.Step step={1}>
|
||||
|
||||
<QuickstartDbSetup />
|
||||
|
||||
</StepHikeCompact.Step>
|
||||
|
||||
<StepHikeCompact.Step step={2}>
|
||||
|
||||
<StepHikeCompact.Details title="Create a React app">
|
||||
|
||||
Boostrap the Hono example app from the Supabase Samples using the CLI.
|
||||
|
||||
</StepHikeCompact.Details>
|
||||
|
||||
<StepHikeCompact.Code>
|
||||
|
||||
```bash Terminal
|
||||
npx supabase@latest bootstrap hono
|
||||
```
|
||||
|
||||
</StepHikeCompact.Code>
|
||||
|
||||
</StepHikeCompact.Step>
|
||||
|
||||
<StepHikeCompact.Step step={3}>
|
||||
<StepHikeCompact.Details title="Install the Supabase client library">
|
||||
|
||||
The `package.json` file in the project includes the necessary dependencies, including `@supabase/supabase-js` and `@supabase/ssr` to help with server-side auth.
|
||||
|
||||
</StepHikeCompact.Details>
|
||||
|
||||
<StepHikeCompact.Code>
|
||||
|
||||
```bash Terminal
|
||||
npm install
|
||||
```
|
||||
|
||||
</StepHikeCompact.Code>
|
||||
|
||||
</StepHikeCompact.Step>
|
||||
|
||||
<StepHikeCompact.Step step={4}>
|
||||
<StepHikeCompact.Details title="Set up the required environment variables">
|
||||
|
||||
Copy the `.env.example` file to `.env` and update the values with your Supabase project URL and anon key.
|
||||
|
||||
Lastly, [enable anonymous sign-ins](https://supabase.com/dashboard/project/_/settings/auth) in the Auth settings.
|
||||
|
||||
<ProjectConfigVariables variable="url" />
|
||||
<ProjectConfigVariables variable="anonKey" />
|
||||
|
||||
</StepHikeCompact.Details>
|
||||
<StepHikeCompact.Code>
|
||||
|
||||
|
||||
```bash Terminal
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
</StepHikeCompact.Code>
|
||||
|
||||
</StepHikeCompact.Step>
|
||||
|
||||
<StepHikeCompact.Step step={5}>
|
||||
<StepHikeCompact.Details title="Start the app">
|
||||
|
||||
Start the app, go to http://localhost:5173.
|
||||
|
||||
</StepHikeCompact.Details>
|
||||
|
||||
<StepHikeCompact.Code>
|
||||
|
||||
```bash Terminal
|
||||
npm run dev
|
||||
```
|
||||
|
||||
</StepHikeCompact.Code>
|
||||
|
||||
</StepHikeCompact.Step>
|
||||
</StepHikeCompact>
|
||||
|
||||
## Next steps
|
||||
|
||||
- Learn how [server side auth](/docs/guides/auth/server-side/creating-a-client?queryGroups=framework&framework=hono) works with Hono.
|
||||
- [Insert more data](/docs/guides/database/import-data) into your database
|
||||
- Upload and serve static files using [Storage](/docs/guides/storage)
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="500px" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:0.993" fill="#ff5b11" d="M 257.5,0.5 C 258.822,0.330034 259.989,0.663368 261,1.5C 298.193,46.8936 333.193,93.8936 366,142.5C 390.289,179.069 410.955,217.735 428,258.5C 455.221,331.104 441.054,394.271 385.5,448C 336.892,489.082 280.892,505.082 217.5,496C 141.727,480.551 90.2265,436.718 63,364.5C 55.9081,340.989 53.5748,316.989 56,292.5C 60.0384,250.347 70.0384,209.68 86,170.5C 92.6509,154.514 101.318,139.848 112,126.5C 120.715,136.88 129.048,147.547 137,158.5C 140.682,162.349 144.515,166.016 148.5,169.5C 178.917,109.136 215.251,52.8028 257.5,0.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#ff9758" d="M 250.5,81.5 C 287.193,124.06 320.36,169.393 350,217.5C 359.293,233.418 366.959,250.085 373,267.5C 385.584,317.008 372.084,357.842 332.5,390C 294.216,416.939 252.216,424.939 206.5,414C 157.201,398.702 128.701,365.535 121,314.5C 119.131,298.409 120.798,282.742 126,267.5C 133.418,248.663 142.418,230.663 153,213.5C 163,198.833 173,184.167 183,169.5C 205.716,140.29 228.216,110.957 250.5,81.5 Z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,3 @@
|
||||
# Get your keys at https://supabase.com/dashboard/project/_/settings/api
|
||||
VITE_SUPABASE_URL=your_supabase_url
|
||||
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key
|
||||
@@ -0,0 +1 @@
|
||||
.env
|
||||
@@ -0,0 +1,59 @@
|
||||
# Hono Supabase Auth Example
|
||||
|
||||
Based on the Hono/JSX + Vite example by [@MathurAditya724](https://github.com/MathurAditya724) \o/
|
||||
|
||||
This example shows how to use Supabase Auth both on the client and server side with Hono.
|
||||
|
||||
## Supabase setup
|
||||
|
||||
- Create a new Supabase project at [database.new](https://database.new/)
|
||||
- Go to the `SQL Editor` and run the following query to create the `countries` table.
|
||||
|
||||
```sql
|
||||
-- Create the table
|
||||
create table countries (
|
||||
id bigint primary key generated always as identity,
|
||||
name text not null
|
||||
);
|
||||
-- Insert some sample data into the table
|
||||
insert into countries (name)
|
||||
values
|
||||
('Canada'),
|
||||
('United States'),
|
||||
('Mexico');
|
||||
|
||||
alter table countries enable row level security;
|
||||
```
|
||||
|
||||
- In a new query, create the following access policy.
|
||||
|
||||
```sql
|
||||
create policy "public can read countries"
|
||||
on public.countries
|
||||
for select to authenticated
|
||||
using (true);
|
||||
```
|
||||
|
||||
- [Enable anonymous sign-ins](https://supabase.com/dashboard/project/_/settings/auth) in the Auth settings.
|
||||
|
||||
## Setup
|
||||
|
||||
- Run `npm install` to install the dependencies.
|
||||
- Run `cp .env.example .env`.
|
||||
- Set the required environment vairables in your `.env` file.
|
||||
|
||||
## Commands
|
||||
|
||||
Run the `vite` dev server
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Building
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
This project is configured to use `node` runtime, you can change it to your desired runtime in the `vite.config.js` file. We are using [@hono/vite-build](https://www.npmjs.com/package/@hono/vite-build) package for building the project and [@hono/vite-dev-server](https://www.npmjs.com/package/@hono/vite-dev-server) for running the dev server.
|
||||
Generated
+1176
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "hono-vite-jsx",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build --mode client && vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.12.2",
|
||||
"@supabase/ssr": "^0.5.2",
|
||||
"@supabase/supabase-js": "^2.47.10",
|
||||
"hono": "^4.5.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hono/vite-build": "^1.1.0",
|
||||
"@hono/vite-dev-server": "^0.17.0",
|
||||
"@types/node": "^20.11.17",
|
||||
"vite": "^5.4.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
import { createBrowserClient } from '@supabase/ssr';
|
||||
import { hc } from 'hono/client';
|
||||
import { useEffect, useState } from 'hono/jsx';
|
||||
import { render } from 'hono/jsx/dom';
|
||||
import type { AppType } from '.';
|
||||
|
||||
const client = hc<AppType>('/');
|
||||
|
||||
const supabase = createBrowserClient(
|
||||
import.meta.env.VITE_SUPABASE_URL!,
|
||||
import.meta.env.VITE_SUPABASE_ANON_KEY!
|
||||
);
|
||||
|
||||
function App() {
|
||||
const [user, setUser] = useState<null | { id: string }>(null);
|
||||
// Check client-side if user is logged in:
|
||||
useEffect(() => {
|
||||
supabase.auth.onAuthStateChange((event, session) => {
|
||||
console.log('Auth event:', event);
|
||||
if (event === 'SIGNED_OUT') {
|
||||
setUser(null);
|
||||
} else {
|
||||
setUser(session?.user!);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>Hono Supabase Auth Example!</h1>
|
||||
<h2>Sign in</h2>
|
||||
{!user ? (
|
||||
<SignIn />
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
window.location.href = '/signout';
|
||||
}}
|
||||
>
|
||||
Sign out!
|
||||
</button>
|
||||
)}
|
||||
<h2>Example of API fetch()</h2>
|
||||
<UserDetailsButton />
|
||||
<h2>Example of database read</h2>
|
||||
<p>
|
||||
Note that only authenticated users are able to read from the database!
|
||||
</p>
|
||||
<a href="/countries">Get countries</a>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function SignIn() {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Ready about and enable{' '}
|
||||
<a
|
||||
href="https://supabase.com/docs/guides/auth/auth-anonymous"
|
||||
target="_blank"
|
||||
>
|
||||
anonymous signins here!
|
||||
</a>
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={async () => {
|
||||
const { data, error } = await supabase.auth.signInAnonymously();
|
||||
if (error) return console.error('Error signing in:', error.message);
|
||||
console.log('Signed in client-side!');
|
||||
alert('Signed in anonymously! User id: ' + data?.user?.id);
|
||||
}}
|
||||
>
|
||||
Anonymous sign in
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const UserDetailsButton = () => {
|
||||
const [response, setResponse] = useState<string | null>(null);
|
||||
|
||||
const handleClick = async () => {
|
||||
const response = await client.api.user.$get();
|
||||
const data = await response.json();
|
||||
const headers = Array.from(response.headers.entries()).reduce<
|
||||
Record<string, string>
|
||||
>((acc, [key, value]) => {
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
}, {});
|
||||
const fullResponse = {
|
||||
url: response.url,
|
||||
status: response.status,
|
||||
headers,
|
||||
body: data,
|
||||
};
|
||||
setResponse(JSON.stringify(fullResponse, null, 2));
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button type="button" onClick={handleClick}>
|
||||
Get My User Details
|
||||
</button>
|
||||
{response && <pre>{response}</pre>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const root = document.getElementById('root')!;
|
||||
render(<App />, root);
|
||||
@@ -0,0 +1,64 @@
|
||||
import { Hono } from 'hono';
|
||||
import { getSupabase, supabaseMiddleware } from './middleware/auth.middleware';
|
||||
|
||||
const app = new Hono();
|
||||
app.use('*', supabaseMiddleware());
|
||||
|
||||
const routes = app.get('/api/user', async (c) => {
|
||||
const supabase = getSupabase(c);
|
||||
const { data, error } = await supabase.auth.getUser();
|
||||
|
||||
if (error) console.log('error', error);
|
||||
|
||||
if (!data?.user) {
|
||||
return c.json({
|
||||
message: 'You are not logged in.',
|
||||
});
|
||||
}
|
||||
|
||||
return c.json({
|
||||
message: 'You are logged in!',
|
||||
userId: data.user,
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/signout', async (c) => {
|
||||
const supabase = getSupabase(c);
|
||||
await supabase.auth.signOut();
|
||||
console.log('Signed out server-side!');
|
||||
return c.redirect('/');
|
||||
});
|
||||
|
||||
app.get('/countries', async (c) => {
|
||||
const supabase = getSupabase(c);
|
||||
const { data, error } = await supabase.from('countries').select('*');
|
||||
if (error) console.log(error);
|
||||
return c.json(data);
|
||||
});
|
||||
|
||||
export type AppType = typeof routes;
|
||||
|
||||
app.get('/', (c) => {
|
||||
return c.html(
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.simplecss.org/simple.min.css"
|
||||
/>
|
||||
{import.meta.env.PROD ? (
|
||||
<script type="module" src="/static/client.js" />
|
||||
) : (
|
||||
<script type="module" src="/src/client.tsx" />
|
||||
)}
|
||||
</head>
|
||||
<body>
|
||||
<div id="root" />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
});
|
||||
|
||||
export default app;
|
||||
@@ -0,0 +1,56 @@
|
||||
import { createServerClient, parseCookieHeader } from '@supabase/ssr';
|
||||
import { SupabaseClient } from '@supabase/supabase-js';
|
||||
import type { Context, MiddlewareHandler } from 'hono';
|
||||
import { env } from 'hono/adapter';
|
||||
import { setCookie } from 'hono/cookie';
|
||||
|
||||
declare module 'hono' {
|
||||
interface ContextVariableMap {
|
||||
supabase: SupabaseClient;
|
||||
}
|
||||
}
|
||||
|
||||
export const getSupabase = (c: Context) => {
|
||||
return c.get('supabase');
|
||||
};
|
||||
|
||||
type SupabaseEnv = {
|
||||
VITE_SUPABASE_URL: string;
|
||||
VITE_SUPABASE_ANON_KEY: string;
|
||||
};
|
||||
|
||||
export const supabaseMiddleware = (): MiddlewareHandler => {
|
||||
return async (c, next) => {
|
||||
const supabaseEnv = env<SupabaseEnv>(c);
|
||||
const supabaseUrl =
|
||||
supabaseEnv.VITE_SUPABASE_URL ?? import.meta.env.VITE_SUPABASE_URL;
|
||||
const supabaseAnonKey =
|
||||
supabaseEnv.VITE_SUPABASE_ANON_KEY ??
|
||||
import.meta.env.VITE_SUPABASE_ANON_KEY;
|
||||
|
||||
if (!supabaseUrl) {
|
||||
throw new Error('SUPABASE_URL missing!');
|
||||
}
|
||||
|
||||
if (!supabaseAnonKey) {
|
||||
throw new Error('SUPABASE_ANON_KEY missing!');
|
||||
}
|
||||
|
||||
const supabase = createServerClient(supabaseUrl, supabaseAnonKey, {
|
||||
cookies: {
|
||||
getAll() {
|
||||
return parseCookieHeader(c.req.header('Cookie') ?? '');
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
setCookie(c, name, value, options)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
c.set('supabase', supabase);
|
||||
|
||||
await next();
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"strict": true,
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"types": ["@cloudflare/workers-types", "vite/client"],
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "hono/jsx"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import devServer from "@hono/vite-dev-server";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
// Change the import to use your runtime specific build
|
||||
import build from "@hono/vite-build/node";
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
if (mode === "client")
|
||||
return {
|
||||
esbuild: {
|
||||
jsxImportSource: "hono/jsx/dom", // Optimized for hono/jsx/dom
|
||||
},
|
||||
build: {
|
||||
rollupOptions: {
|
||||
input: "./src/client.tsx",
|
||||
output: {
|
||||
entryFileNames: "static/client.js",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
build({
|
||||
entry: "src/index.tsx",
|
||||
}),
|
||||
devServer({
|
||||
entry: "src/index.tsx",
|
||||
}),
|
||||
],
|
||||
};
|
||||
});
|
||||
Reference in new issue
Block a user