Hono——一个小型,简单且超快的Edges Web框架

Hono - [炎]在日语中的意思是火焰 - 是一个小型,简单且超快的Edges Web框架。它适用于任何JavaScript运行时:Cloudflare Workers,Fastly Compute@Edge,Deno,Bun,Vercel,Netlify,Lagon,AWS Lambda,Lambda@Edge和Node.js。

快,但不仅快。

文章目录

  • 快速入门
  • 特征
  • 用例
  • 谁在使用Hono?
  • 示例
  • 超快
  • Remix + Hono 示例
    • Session 会话管理
    • 静态资源
    • HTTPS Only
    • trailingSlash

快速入门

npm i --save hono

只需运行这个:

import { Hono } from 'hono'
const app = new Hono()

app.get('/', (c) => c.text('Hono!'))

export default app

特征

  • 超快 - 路由器 RegExpRouter 真的很快。不使用线性循环。快。
  • 轻量级 - hono/tiny 预设小于 12kB。Hono 的依赖关系为零,仅使用 Web 标准 API。
  • 多运行时 - 适用于Cloudflare Workers,Fastly Compute@Edge,Deno,Bun,Lagon,AWS Lambda或Node.js。相同的代码在所有平台上运行。
  • 能力 - Hono 具有内置中间件、自定义中间件、第三方中间件和助手。包括电池。
  • 令人愉快的DX ️ - 超级干净的API。一流的 TypeScript 支持。现在,我们有“类型”。

用例

Hono是一个简单的Web应用程序框架,类似于Express,没有前端。但它在 CDN Edge 上运行,允许您在与中间件结合使用时构建更大的应用程序。以下是一些用例示例:

  • 构建网络接口
  • 后端服务器代理
  • CDN 前端
  • 边缘应用
  • 库的基本服务器
  • 全栈应用

谁在使用Hono?

项目 平台 用途
cdnjs API 服务器 Cloudflare Workers 免费的开源 CDN 服务。Hono用于他们的API服务。
Polyfill.io Fastly Compute@Edge 提供必要的浏览器填充的 CDN 服务。Hono被用作核心服务器。
Ultra Deno 一个 React/Deno 框架。Hono 用于内部服务器。
Deno Benchmarks Deno 基于 V8 构建的安全 TypeScript 运行时。Hono用于基准测试。
Cloudflare 博客 Cloudflare Workers 文章中介绍的一些应用程序使用 Hono。

示例

使用 Hono 为 Cloudflare Workers 创建应用程序的演示。

超快

Hono是最快的,与Cloudflare Workers的其他路由器相比。

Hono x 402,820 ops/sec ±4.78% (80 runs sampled)
itty-router x 212,598 ops/sec ±3.11% (87 runs sampled)
sunder x 297,036 ops/sec ±4.76% (77 runs sampled)
worktop x 197,345 ops/sec ±2.40% (88 runs sampled)
Fastest is Hono
✨  Done in 28.06s.

查看更多基准测试: https://hono.dev/concepts/benchmarks

Hono 太小了。使用 hono/tiny 预设时,其大小在缩小时小于 12KB。有许多中间件和适配器,但它们仅在使用时才捆绑在一起。对于上下文,Express 的大小为 572KB。

$ npx wrangler dev --minify ./src/index.ts
 ⛅️ wrangler 2.20.0
--------------------
⬣ Listening at http://0.0.0.0:8787
- http://127.0.0.1:8787
- http://192.168.128.165:8787
Total Upload: 11.47 KiB / gzip: 4.34 KiB

Remix + Hono 示例

安装包:

npm add remix-hono

然后创建你的 Remix 服务器:

import { logDevReady } from "@remix-run/cloudflare";
import * as build from "@remix-run/dev/server-build";
import { Hono } from "hono";
// You can also use it with other runtimes
import { handle } from "hono/cloudflare-pages";
import { remix } from "remix-hono/handler";

if (process.env.NODE_ENV === "development") logDevReady(build);

/* type your Cloudflare bindings here */
type Bindings = {};

/* type your Hono variables (used with ctx.get/ctx.set) here */
type Variables = {};

type ContextEnv = { Bindings: Bindings; Variables: Variables };

const server = new Hono<ContextEnv>();

// Add the Remix middleware to your Hono server
server.use(
	"*",
	remix({
		build,
		mode: process.env.NODE_ENV as "development" | "production",
		// getLoadContext is optional, the default function is the same as here
		getLoadContext(ctx) {
			return ctx.env;
		},
	}),
);

// Create a Cloudflare Pages request handler for your Hono server
export const onRequest = handle(server);

现在,你可以添加 Hono 中间件了,比如基本的登录认证:

import { basicAuth } from "hono/basic-auth";

server.use(
	"*",
	basicAuth({ username: "hono", password: "remix" }),
	// Ensure Remix request handler is the last one
	remix(options),
);

Session 会话管理

有三种常见方法来管理 Cloudflare 上的会话。

第一种,使用 Worker KV 持久化会话。

import { session } from "remix-hono/session";
// Install the `@remix-run/*` package for your server adapter to grab the
// factory functions for session storage
import { createWorkerKVSessionStorage } from "@remix-run/cloudflare";

server.use(
	"*",
	session({
		autoCommit: true,
		createSessionStorage(context) {
			return createWorkersKVSessionStorage({
				kv: context.env.MY_KV_BINDING,
				cookie: {
					name: "session",
					httpOnly: true,
					secrets: [context.SESSION_SECRET],
				},
			});
		},
	}),
);

现在,可以通过 getSessionStoragegetSession 方法来获取会话对象了。

注意:如果 autoCommit 设置为 false, 你需要手动调用 sessionStorage.getSession()

import { getSessionStorage, getSession } from "remix-hono/session";

server.use(
	"*",
	remix<ContextEnv>({
		build,
		mode: process.env.NODE_ENV as "development" | "production",
		// getLoadContext is optional, the default function is the same as here
		getLoadContext(ctx) {
			let sessionStorage = getSessionStorage(ctx);
			let session = getSession(ctx);

			// Return them here to access them in your loaders and actions
			return { ...ctx.env, sessionStorage, session };
		},
	}),
);

第二种,使用 workerKVSession 来替代。

import { workerKVSession } from "remix-hono/cloudflare";

server.use(
	"*",
	workerKVSession({
		autoCommit: true, // same as in the session middleware
		cookie: {
			name: "session", // all cookie options as in createWorkerKVSessionStorage
			// In this function, you can access context.env to get the session secret
			secrets(context) {
				return [context.env.SECRET];
			},
		},
		// The name of the binding using for the KVNamespace
		binding: "KV_BINDING",
	}),
);

第三种,使用cookieSession

import { cookieSession } from "remix-hono/cloudflare";

server.use(
	"*",
	cookieSession({
		autoCommit: true, // same as in the session middleware
		cookie: {
			name: "session", // all cookie options as in createCookieSessionStorage
			// In this function, you can access context.env to get the session secret
			secrets(context) {
				return [context.env.SECRET];
			},
		},
	}),
);

静态资源

如果需要将 public 目录下的(除了 public/build 之外)资源通过服务提供,可以使用这样的中间件:

import { staticAssets } from "remix-hono/cloudflare";
import { remix } from "remix-hono/handler";

server.use(
	"*",
	staticAssets(),
	// Add Remix request handler as the last middleware
	remix(options),
);

HTTPS Only

强制使用 HTTPS:

import { httpsOnly } from "remix-hono/security";

server.use("*", httpsOnly());

trailingSlash

尾部 / 处理:

import { trailingSlash } from "remix-hono/trailing-slash";

// By default, trailing slashes are disabled, so `https://company.tld/about/`
// will be redirect to `https://company.tld/about`
server.use("*", trailingSlash());
server.use("*", trailingSlash({ enabled: false }));

// You can also enable trailing slashes, so `https://company.tld/about` will be
// redirect to `https://company.tld/about/` instead
server.use("*", trailingSlash({ enabled: true }));

你可能感兴趣的:(前端)