Remix + Hono

Remix 是一个用于构建 Web 应用程序的 Web 框架,可以在边缘运行。

Hono 是一个用于边缘的小巧且超快的 Web 框架。

此适配器允许您将 Hono 与 Remix 一起使用,以便您可以使用两者各自的优势。

让 Hono 为您的 HTTP 服务器及其中间件提供动力,然后使用 Remix 构建您的 Web 应用程序。

安装

安装包

npm add remix-hono

以下包是可选依赖项,您需要根据您正在使用的 remix-hono 功能来安装它们。

  • 如果您使用 Cloudflare 集成,则使用 @remix-run/cloudflare
  • 如果您使用 i18n 中间件,则使用 i18nextremix-i18next
  • 如果您使用 typedEnv,则使用 zod

[!注意] 如果您不使用这些包,实际上不需要安装它们,但是如果您使用依赖于这些包的功能,则需要自行安装它们(它们不会自动安装)。

使用

创建您的 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 c.get/c.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(c) {
			return c.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),
);

仅此而已,您的应用程序现在将具有基本身份验证保护,这非常适合预览应用程序。

会话管理

除了 remix Hono 中间件之外,还有另外三个中间件可用于处理 Remix 会话。

由于 Remix 会话通常使用来自环境的密钥,因此您需要访问 Hono c.env 以使用它们。如果您使用 Worker KV 会话存储,则还需要将 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(c) {
			return createWorkersKVSessionStorage({
				kv: c.env.MY_KV_BINDING,
				cookie: {
					name: "session",
					httpOnly: true,
					secrets: [c.SESSION_SECRET],
				},
			});
		},
	}),
);

现在,在您的会话中间件之后设置 Remix 中间件,并使用辅助函数 getSessionStoragegetSession 来访问 SessionStorage 和 Session 对象。

注意 只有在会话中间件选项中将 autoCommit 设置为 true 时,Session 对象才会被定义。如果将其设置为 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(c) {
			let sessionStorage = getSessionStorage(c);
			let session = getSession(c);

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

session 中间件是通用的,允许您使用任何会话存储机制。如果您想使用 Worker KV 会话存储,则可以使用 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 c.env to get the session secret
			secrets(c) {
				return [c.env.SECRET];
			},
		},
		// The name of the binding using for the KVNamespace
		binding: "KV_BINDING",
	}),
);

如果您想使用 Cookie 会话存储,则可以使用 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 c.env to get the session secret
			secrets(c) {
				return [c.env.SECRET];
			},
		},
	}),
);

workerKVSessioncookieSession 中,您都使用从 remix-hono/session 导入的 getSessiongetSessionStorage

Cloudflare 上的静态资源

如果您将 Remix Hono 与 Cloudflare 一起使用,则需要从 public 文件夹(除了 public/build)提供静态文件。staticAssets 中间件用于此目的。

如果您尚未安装 @remix-run/cloudflare,请先安装它。

npm add @remix-run/cloudflare

然后在您的服务器中使用中间件。

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),
);

i18next 集成

如果您使用 remix-i18next 来支持 Remix 应用程序中的 i18n,则 i18next 中间件允许您将其设置为中间件,您可以在以后的 getLoadContext 函数中使用它来将 localet 函数传递给您的加载器和操作。

如果您还没有安装 i18nextremix-i18next,请先安装它们。

npm add i18next remix-i18next

然后在您的服务器中使用中间件。

import { i18next } from "remix-hono/i18next";

// Same options as in remix-i18next
server.use("*", i18next(options));

然后,在您的 getLoadContext 函数中,您可以使用辅助函数 i18next.getLocalei18next.getFixedT 来访问 localet 函数。

server.use(
	"*",
	remix({
		build,
		mode: process.env.NODE_ENV as "development" | "production",
		// getLoadContext is optional, the default function is the same as here
		getLoadContext(c) {
			// get the locale from the context
			let locale = i18next.getLocale(c);
			// get t function for the default namespace
			let t = await i18next.getFixedT(c);
			// get t function for a specific namespace
			let errorT = await i18next.getFixedT(c, "error");
			return { env: c.env, locale, t, errorT };
		},
	}),
);

还有一个 i18next.get 函数,它在您需要时返回 RemixI18Next 实例。

仅限 HTTPS

您可以使用 httpsOnly 中间件强制您的服务器仅使用 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 }));

使用 Zod 进行类型化环境变量

typedEnv 辅助函数允许您获取任何运行时的环境变量,并使用 Zod 根据模式对其进行验证。

如果您还没有安装 Zod,请先安装它。

npm add zod

然后在任何中间件或请求处理程序中使用此辅助函数。

import { typedEnv } from "remix-hono/typed-env";

// Define your schema
const Schema = z.object({ SECRET: z.string() });

// Use the helper
server.get("/about", (c) => {
	let env = typedEnv(c, Schema);
	let secret = env.SECRET; // or typedEnv(c, Schema, "SECRET");
	// do something here
});

作者

许可证

  • MIT 许可证