Skip to content

feat: hono bff doc #7125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/olive-chicken-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@modern-js/bff-generator': patch
---

feat: migrate to Hono bff
feat: 迁移到 Hono bff

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: modern.server.[tj]s
sidebar_position: 1
---

# modern.server.[tj]s

This file extends the Modern.js Server. In this file, you can configure [Middleware](/guides/advanced-features/custom-server.html#middleware), [RenderMiddleware](/guides/advanced-features/custom-server.html#rendermiddleware), or [Plugin](/guides/advanced-features/custom-server.html#plugin) for the Server that starts with the Modern.js project.

You can intercept and handle requests and responses, perform authentication and role checks, preprocess requests, and handle exceptions, etc. You can also insert specific business logic into the built-in processing logic (including route matching, resource addressing, header injection, page rendering, and static web hosting).
44 changes: 0 additions & 44 deletions packages/document/main-doc/docs/en/apis/app/runtime/bff/hook.mdx

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: useHonoContext
---
# useHonoContext

Used to obtain Hono context in an integrated BFF function.

## Usage

```ts
import { useHonoContext } from '@modern-js/plugin-bff/hono';
```

## Function Signature

`function useHonoContext(): Context`

## Example

Developers can use `context` to obtain more request information, such as setting response headers:

```ts
import { useHonoContext } from '@modern-js/plugin-bff/hono';

export async function get() {
const c = useHonoContext();
c.res.headers.set('x-bff-api', 'true');
// ...
}
```
28 changes: 1 addition & 27 deletions packages/document/main-doc/docs/en/components/enable-bff.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,14 @@ import { PackageManagerTabs } from '@theme';
```bash
? Please select the operation you want to perform Enable optional features
? Please select the feature to enable Enable "BFF"
? Please select BFF type Framework mode
```

:::note
Currently, it is recommended to create BFF in framework mode. We will remove the BFF type concept in the future.
:::

3. Depending on the chosen runtime framework, add the following code to `modern.config.[tj]s`:

import { Tabs, Tab as TabItem } from "@theme";

<Tabs>
<TabItem value="express" label="Express.js" default>

```ts title="modern.config.ts"
import { expressPlugin } from '@modern-js/plugin-express';
import { bffPlugin } from '@modern-js/plugin-bff';

export default defineConfig({
plugins: [expressPlugin(), bffPlugin()],
});
```

</TabItem>
<TabItem value="koa" label="Koa.js">

```ts title="modern.config.ts"
import { koaPlugin } from '@modern-js/plugin-koa';
import { bffPlugin } from '@modern-js/plugin-bff';

export default defineConfig({
plugins: [koaPlugin(), bffPlugin()],
plugins: [bffPlugin()],
});
```

</TabItem>
</Tabs>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Modern.js supports [Express.js](https://expressjs.com/) and [Koa.js](https://koajs.com/) as optional BFF runtime frameworks. Please refer to the [BFF - Frameworks](/guides/advanced-features/bff/frameworks.html) for more information.
Modern.js Server and BFF use [Hono.js](https://hono.dev/) as the runtime framework, and you can extend the Server based on the Hono.js ecosystem. Please refer to [Custom Server](/guides/advanced-features/custom-server.html).
Original file line number Diff line number Diff line change
@@ -1,43 +1,49 @@
# Extend BFF Server

In some applications, developers may want to handle all BFF functions uniformly, such as for authentication, logging, data processing, etc.
In some applications, developers may want to handle all BFF functions uniformly, such as authentication, logging, data processing, etc.

Modern.js provides two methods that allow developers to extend the BFF Server freely according to the runtime framework.
Modern.js allows users to freely extend the BFF Server through the [Custom Server](/guides/advanced-features/custom-server.html) method.

## Middleware
## Using Middleware

Developers can write middleware in the `api/_app.ts` file to extend the BFF Server. Taking Express as the runtime framework, here is an example of how to write a middleware to add permission checks:
Developers can use middleware by configuring middlewares in `server/modern.server.ts`. The following describes how to write a BFF middleware manually to add permission verification:

```ts title="api/_app.ts"
import { hook } from '@modern-js/runtime/server';
import { Request, Response, NextFunction } from 'express';
```ts title="server/modern.server.ts"
import {
type MiddlewareHandler,
defineServerConfig,
} from '@modern-js/server-runtime';

export default hook(({ addMiddleware }) => {
addMiddleware(async (req: Request, res: Response, next: NextFunction) => {
if (req.url !== '/api/login') {
const sid = req?.cookies?.sid;
if (!sid) {
res.status(400);
res.json({ code: -1, message: 'need login' });
} else {
next();
}
} else {
next();
const requireAuthForApi: MiddlewareHandler = async (c, next) => {
if (c.req.path.startsWith('/api') && c.req.path !== '/api/login') {
const sid = c.req.cookie('sid');
if (!sid) {
return c.json({ code: -1, message: 'need login' }, 400);
}
});
}
await next();
};

export default defineServerConfig({
middlewares: [
{
name: 'require-auth-for-api',
handler: requireAuthForApi,
},
]
});

```

Then add a standard BFF function `api/lambda/hello.ts`:
Then add a regular BFF function `api/lambda/hello.ts`:

```ts title="api/lambda/hello.ts"
export default async () => {
return 'Hello Modern.js';
};
```

Next, in the frontend, add the code to access the API in `src/routes/page.tsx`, directly using the integrated method for the call:
Next, in the frontend `src/routes/page.tsx`, add the interface access code and directly use the integrated method to call:

```ts title="src/routes/page.tsx"
import { useState, useEffect } from 'react';
Expand All @@ -59,14 +65,14 @@ export default () => {
};
```

Now run the `dev` command to start the project, and visit `http://localhost:8080/`. You will find that the request to `/api/hello` is intercepted:
Now run the `dev` command to start the project, and access `http://localhost:8080/` to find that the request for `/api/hello` has been intercepted:

![Network](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/network2.png)

Finally, modify the frontend code in `src/routes/page.tsx` to call the login interface before accessing `/api/hello`:
Finally, modify the frontend code `src/routes/page.tsx`, and call the login interface before accessing `/api/hello`:

:::note
Here the login interface is not actually implemented; the code is just for demonstration.
This part does not implement a real login interface; the code is just for demonstration.
:::

```ts
Expand All @@ -92,63 +98,8 @@ export default () => {
};
```

Refresh the page to see that the access to `/api/hello` is successful:
Refresh the page, and you can see that the access to `/api/hello` is successful:

![Network](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/network3.png)

The above code simulates adding middleware in `api/_app.ts` to implement simple login functionality. Similarly, other functionalities can be implemented in this hook file to extend the BFF Server.

:::info
The way middleware is written may differ depending on the runtime framework. For details, see [Runtime Frameworks](/guides/advanced-features/bff/frameworks).
:::

## Define Server Instance

In addition to middleware, you can also define a BFF Server instance via the `api/app.ts`. Developers need to export an instance that can be recognized by the runtime framework plugin. Here is a simple demonstration of how to define a server instance with Koa and Express.

import { Tabs, Tab as TabItem } from "@theme";

<Tabs>
<TabItem value="express" label="Express.js" default>

```ts title="api/app.ts"
import express from 'express';

const app = express();
app.use(async (req, res, next) => {
console.info(`access url: ${req.url}`);
next();
});

export default app;
```

</TabItem>
<TabItem value="koa" label="Koa.js">

```ts title="api/app.ts"
import koa from 'koa';

const app = new Koa();
app.use(async (ctx, next) => {
console.info(`access url: ${ctx.url}`);
await next();
});

export default app;
```

</TabItem>
</Tabs>

In complex BFF logic, defining a server instance allows for easier organization of code logic and directory structure design through a single entry point. In this file, you can perform initialization logic, add global middleware, declare routes, and even extend the original framework.

The routes defined by the BFF functions will be registered after the routes defined in the `app.ts` file. Therefore, you can also intercept the routes defined by the BFF functions here for preprocessing or early responses.

:::note
At this time, if `api/_app.ts` exists in the application, the defined middleware will be executed after the middleware exported by the `api/app.ts` instance. In most cases, middleware can cover most customization needs for BFF functions. Only when the application's server-side logic is more complex do you need to customize the server instance.
:::

:::caution
When `api/app.ts` does not exist in the application, Modern.js will default to adding [koa-body](https://www.npmjs.com/package/koa-body). When `api/app.ts` does exist in the application, if developers wish to use BFF functions with bodies, they will need to **add `koa-body` themselves**.
:::
The above code simulates defining middleware in `server/Modern.server.ts` and implements a simple login function. Similarly, other functionalities can be implemented in this configuration file to extend the BFF Server.
Loading