Bun
Bun ist eine weitere JavaScript-Laufzeitumgebung, die sich von Node.js und Deno unterscheidet. Bun enthält einen Transcompiler, sodass wir den Code in TypeScript oder gewöhnlichem JavaScript schreiben können. Hono funktioniert auch auf Bun.
1. Bun installieren
Um den Befehl bun zu installieren, folge der Anleitung auf der offiziellen Website.
2. Einrichtung
2.1. Ein neues Projekt einrichten
Für Bun steht eine Projektvorlage zur Verfügung. Starte dein Projekt mit dem Befehl „bun create“. Wähle für dieses Beispiel die Vorlage bun aus.
bun create hono@latest my-appWechsle nach my-app und installiere die Abhängigkeiten.
cd my-app
bun install2.2. Ein vorhandenes Projekt einrichten
In einem vorhandenen Bun-Projekt müssen wir lediglich im Stammverzeichnis des Projekts die Abhängigkeit hono installieren:
bun add honoFüge anschließend den Befehl dev zu deiner bestehenden package.json hinzu.
{
"scripts": {
"dev": "bun run --hot src/index.ts"
}
}Die Bun-Projektvorlage zeigt eine minimale Beispielkonfiguration. Sie entspricht dem Ergebnis von bun create hono@latest.
3. Hello World
Unten findest du das „Hello World“-Skript. Es entspricht weitgehend dem Code auf anderen Plattformen.
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Bun!'))
export default appWenn du Hono in einem vorhandenen Projekt einrichtest, erwartet der Befehl bun run dev, dass das „Hello World“-Skript in src/index.ts liegt.
4. Ausführen
Führe den Befehl aus.
bun run devÖffne anschließend http://localhost:3000 in deinem Browser.
Portnummer ändern
Du kannst die Portnummer angeben, indem du port exportierst.
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,
} Statische Dateien ausliefern
Um statische Dateien auszuliefern, verwende serveStatic aus dem Paket @hono/bun.
bun add @hono/bunimport { 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' }))Der obige Code funktioniert mit der folgenden Verzeichnisstruktur.
./
├── favicon.ico
├── src
└── static
├── demo
│ └── index.html
├── fallback.txt
├── hello.txt
└── images
└── dinotocat.pngrewriteRequestPath
Wenn du http://localhost:3000/static/* auf ./statics abbilden möchtest, kannst du die Option rewriteRequestPath verwenden:
app.get(
'/static/*',
serveStatic({
root: './',
rewriteRequestPath: (path) =>
path.replace(/^\/static/, '/statics'),
})
)mimes
Mit mimes kannst du MIME-Typen hinzufügen:
app.get(
'/static/*',
serveStatic({
mimes: {
m3u8: 'application/vnd.apple.mpegurl',
ts: 'video/mp2t',
},
})
)onFound
Mit onFound kannst du festlegen, was passieren soll, wenn die angeforderte Datei gefunden wird:
app.get(
'/static/*',
serveStatic({
// ...
onFound: (_path, c) => {
c.header('Cache-Control', `public, immutable, max-age=31536000`)
},
})
)onNotFound
Mit onNotFound kannst du festlegen, was passieren soll, wenn die angeforderte Datei nicht gefunden wird:
app.get(
'/static/*',
serveStatic({
onNotFound: (path, c) => {
console.log(`${path} is not found, you access ${c.req.path}`)
},
})
)precompressed
Die Option precompressed prüft, ob Dateien mit Erweiterungen wie .br oder .gz verfügbar sind, und liefert sie anhand des Headers Accept-Encoding aus. Dabei wird Brotli bevorzugt, gefolgt von Zstd und Gzip. Ist keine dieser Varianten verfügbar, wird die ursprüngliche Datei ausgeliefert.
app.get(
'/static/*',
serveStatic({
precompressed: true,
})
)Tests
Für Tests auf Bun kannst du bun:test verwenden.
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)
})
})Führe anschließend den Befehl aus.
bun test index.test.ts