Bun
Bun is another JavaScript runtime. It's not Node.js or Deno. Bun includes a trans compiler, we can write the code with TypeScript. Hono also works on Bun.
1. Install Bun
To install bun command, follow the instruction in the official web site.
2. Setup
2.1. Setup a new project
A starter for Bun is available. Start your project with "bun create" command. Select bun template for this example.
bun create hono@latest my-appMove into my-app and install the dependencies.
cd my-app
bun install2.2. Setup an existing project
On an existing Bun project, we only need to install hono dependencies on the project root directory via
bun add hono3. Hello World
"Hello World" script is below. Almost the same as writing on other platforms.
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Bun!'))
export default app4. Run
Run the command.
bun run devThen, access http://localhost:3000 in your browser.
Change port number
You can specify the port number with exporting the port.
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Bun!'))
export default app
export default {
port: 3000,
fetch: app.fetch,
} Serve static files
To serve static files, use serveStatic imported from hono/bun.
import { serveStatic } from 'hono/bun'
const app = new Hono()
app.use('/static/*', serveStatic({ root: './' }))
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))
app.get('/', (c) => c.text('You can access: /static/hello.txt'))
app.get('*', serveStatic({ path: './static/fallback.txt' }))For the above code, it will work well with the following directory structure.
./
├── favicon.ico
├── src
└── static
├── demo
│ └── index.html
├── fallback.txt
├── hello.txt
└── images
└── dinotocat.pngrewriteRequestPath
If you want to map http://localhost:3000/static/* to ./statics, you can use the rewriteRequestPath option:
app.get(
'/static/*',
serveStatic({
root: './',
rewriteRequestPath: (path) =>
path.replace(/^\/static/, '/statics'),
})
)mimes
You can add MIME types with mimes:
app.get(
'/static/*',
serveStatic({
mimes: {
m3u8: 'application/vnd.apple.mpegurl',
ts: 'video/mp2t',
},
})
)onFound
You can specify handling when the requested file is found with onFound:
app.get(
'/static/*',
serveStatic({
// ...
onFound: (_path, c) => {
c.header('Cache-Control', `public, immutable, max-age=31536000`)
},
})
)onNotFound
You can specify handling when the requested file is not found with onNotFound:
app.get(
'/static/*',
serveStatic({
onNotFound: (path, c) => {
console.log(`${path} is not found, you access ${c.req.path}`)
},
})
)precompressed
The precompressed option checks if files with extensions like .br or .gz are available and serves them based on the Accept-Encoding header. It prioritizes Brotli, then Zstd, and Gzip. If none are available, it serves the original file.
app.get(
'/static/*',
serveStatic({
precompressed: true,
})
)Testing
You can use bun:test for testing on Bun.
import { describe, expect, it } from 'bun:test'
import app from '.'
describe('My first test', () => {
it('Should return 200 Response', async () => {
const req = new Request('http://localhost/')
const res = await app.fetch(req)
expect(res.status).toBe(200)
})
})Then, run the command.
bun test index.test.ts