使用 Bun.serve()
的 routes
選項,您可以在同一個應用程式中執行前端和後端,無需額外步驟。
若要開始使用,請匯入 HTML 檔案並將它們傳遞給 Bun.serve()
中的 routes
選項。
import { sql, serve } from "bun";
import dashboard from "./dashboard.html";
import homepage from "./index.html";
const server = serve({
routes: {
// ** HTML imports **
// Bundle & route index.html to "/". This uses HTMLRewriter to scan the HTML for `<script>` and `<link>` tags, run's Bun's JavaScript & CSS bundler on them, transpiles any TypeScript, JSX, and TSX, downlevels CSS with Bun's CSS parser and serves the result.
"/": homepage,
// Bundle & route dashboard.html to "/dashboard"
"/dashboard": dashboard,
// ** API endpoints ** (Bun v1.2.3+ required)
"/api/users": {
async GET(req) {
const users = await sql`SELECT * FROM users`;
return Response.json(users);
},
async POST(req) {
const { name, email } = await req.json();
const [user] =
await sql`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
return Response.json(user);
},
},
"/api/users/:id": async req => {
const { id } = req.params;
const [user] = await sql`SELECT * FROM users WHERE id = ${id}`;
return Response.json(user);
},
},
// Enable development mode for:
// - Detailed error messages
// - Hot reloading (Bun v1.2.3+ required)
development: true,
// Prior to v1.2.3, the `fetch` option was used to handle all API requests. It is now optional.
// async fetch(req) {
// // Return 404 for unmatched routes
// return new Response("Not Found", { status: 404 });
// },
});
console.log(`Listening on ${server.url}`);
bun run app.ts
HTML 匯入即路由
網路始於 HTML,Bun 的全端開發伺服器也是如此。
若要指定前端的進入點,請將 HTML 檔案匯入到您的 JavaScript/TypeScript/TSX/JSX 檔案中。
import dashboard from "./dashboard.html";
import homepage from "./index.html";
這些 HTML 檔案在 Bun 的開發伺服器中用作路由,您可以將它們傳遞給 Bun.serve()
。
Bun.serve({
routes: {
"/": homepage,
"/dashboard": dashboard,
}
fetch(req) {
// ... api requests
},
});
當您向 /dashboard
或 /
發出請求時,Bun 會自動將 HTML 檔案中的 <script>
和 <link>
標籤捆綁在一起,將它們公開為靜態路由,並提供結果。
像這樣的 index.html 檔案
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" href="./reset.css" />
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./sentry-and-preloads.ts"></script>
<script type="module" src="./my-app.tsx"></script>
</body>
</html>
會變成像這樣
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" href="/index-[hash].css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/index-[hash].js"></script>
</body>
</html>
如何與 React 一起使用
若要在您的用戶端程式碼中使用 React,請匯入 react-dom/client
並渲染您的應用程式。
import dashboard from "../public/dashboard.html";
import { serve } from "bun";
serve({
routes: {
"/": dashboard,
},
async fetch(req) {
// ...api requests
return new Response("hello world");
},
});
import "./styles.css";
import { createRoot } from "react-dom/client";
import { App } from "./app.tsx";
document.addEventListener("DOMContentLoaded", () => {
const root = createRoot(document.getElementById("root"));
root.render(<App />);
});
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="../src/frontend.tsx"></script>
</body>
</html>
body {
background-color: red;
}
export function App() {
return <div>Hello World</div>;
}
開發模式
在本機建置時,透過在 Bun.serve()
中設定 development: true
來啟用開發模式。
import homepage from "./index.html";
import dashboard from "./dashboard.html";
Bun.serve({
routes: {
"/": homepage,
"/dashboard": dashboard,
}
development: true,
fetch(req) {
// ... api requests
},
});
當 development
為 true
時,Bun 將會
- 在回應中包含
SourceMap
標頭,以便開發人員工具可以顯示原始程式碼 - 停用最小化
- 在每次對 .html 檔案的請求時重新捆綁資源
生產模式
在生產環境中提供您的應用程式時,請在 Bun.serve()
中設定 development: false
。
- 啟用捆綁資源的記憶體內快取。Bun 將在首次請求
.html
檔案時延遲捆綁資源,並將結果快取在記憶體中,直到伺服器重新啟動。 - 啟用
Cache-Control
標頭和ETag
標頭 - 最小化 JavaScript/TypeScript/TSX/JSX 檔案
外掛程式
當捆綁靜態路由時,也支援 Bun 的 捆綁器外掛程式。
若要為 Bun.serve
配置外掛程式,請在您的 bunfig.toml
的 [serve.static]
區段中新增一個 plugins
陣列。
在 HTML 路由中使用 TailwindCSS
例如,透過安裝和新增 bun-plugin-tailwind
外掛程式,在您的路由上啟用 TailwindCSS
bun add bun-plugin-tailwind
[serve.static]
plugins = ["bun-plugin-tailwind"]
這將允許您在 HTML 和 CSS 檔案中使用 TailwindCSS 實用程式類別。您只需要在某處匯入 tailwindcss
。
<!doctype html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" href="tailwindcss" />
</head>
<body>
<!-- the rest of your HTML... -->
</body>
</html>
或在您的 CSS 中
@import "tailwindcss";
自訂外掛程式
任何匯出 有效捆綁器外掛程式物件(本質上是一個具有 name
和 setup
欄位的物件)的 JS 檔案或模組都可以放置在 plugins
陣列中。
[serve.static]
plugins = ["./my-plugin-implementation.ts"]
Bun 將延遲解析和載入每個外掛程式,並使用它們來捆綁您的路由。
注意:這目前在 bunfig.toml
中,以便在我們最終將其與 bun build
CLI 整合時,可以靜態地知道正在使用的外掛程式。這些外掛程式在 Bun.build()
的 JS API 中運作,但 CLI 中尚不支援。
運作方式
Bun 使用 HTMLRewriter
掃描 HTML 檔案中的 <script>
和 <link>
標籤,將它們用作 Bun 的捆綁器 的進入點,為 JavaScript/TypeScript/TSX/JSX 和 CSS 檔案產生最佳化捆綁包,並提供結果。
<script>
處理- 轉譯
<script>
標籤中的 TypeScript、JSX 和 TSX - 捆綁匯入的依賴項
- 為偵錯產生來源地圖
- 當
Bun.serve()
中的development
不是true
時進行最小化
<script type="module" src="./counter.tsx"></script>
- 轉譯
<link>
處理- 處理 CSS 匯入和
<link>
標籤 - 串連 CSS 檔案
- 重寫
url
和資源路徑,以在 URL 中包含內容可定址雜湊
<link rel="stylesheet" href="./styles.css" />
- 處理 CSS 匯入和
<img>
& 資源處理- 資源連結被重寫為在 URL 中包含內容可定址雜湊
- CSS 檔案中的小型資源會內嵌到
data:
URL 中,減少透過網路傳送的 HTTP 請求總數。
重寫 HTML
- 將所有
<script>
標籤合併為單個<script>
標籤,並在 URL 中包含內容可定址雜湊 - 將所有
<link>
標籤合併為單個<link>
標籤,並在 URL 中包含內容可定址雜湊 - 輸出新的 HTML 檔案
- 將所有
伺服
- 來自捆綁器的所有輸出檔案都公開為靜態路由,內部機制與您將
Response
物件傳遞給Bun.serve()
中的static
時相同。
- 來自捆綁器的所有輸出檔案都公開為靜態路由,內部機制與您將
這與 Bun.build
處理 HTML 檔案 的方式類似。
開發中
- 目前尚不支援
bun build
。未來將會支援。