@bleedingdev/modern-js-main-doc 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/docs/en/components/deploy-command.mdx +1 -0
  2. package/docs/en/components/hono.mdx +3 -3
  3. package/docs/en/components/init-app.mdx +1 -5
  4. package/docs/en/components/prerequisites.mdx +1 -1
  5. package/docs/en/configure/app/bff/effect.mdx +34 -36
  6. package/docs/en/configure/app/source/react-compiler.mdx +2 -0
  7. package/docs/en/guides/advanced-features/bff/data-platform.mdx +2 -2
  8. package/docs/en/guides/advanced-features/bff/frameworks.mdx +33 -21
  9. package/docs/en/guides/advanced-features/bff/function.mdx +2 -2
  10. package/docs/en/guides/advanced-features/bff/operators.mdx +17 -17
  11. package/docs/en/guides/basic-features/render/ssr-cache.mdx +14 -1
  12. package/docs/en/guides/get-started/ultramodern.mdx +14 -97
  13. package/docs/en/plugin/server-plugins/api.mdx +1 -0
  14. package/docs/zh/components/bff-operator-code.mdx +1 -1
  15. package/docs/zh/components/deploy-command.mdx +1 -0
  16. package/docs/zh/components/hono.mdx +3 -3
  17. package/docs/zh/components/prerequisites.mdx +1 -1
  18. package/docs/zh/configure/app/bff/effect.mdx +28 -33
  19. package/docs/zh/configure/app/source/react-compiler.mdx +2 -0
  20. package/docs/zh/guides/advanced-features/bff/data-platform.mdx +2 -2
  21. package/docs/zh/guides/advanced-features/bff/frameworks.mdx +31 -20
  22. package/docs/zh/guides/advanced-features/bff/function.mdx +2 -2
  23. package/docs/zh/guides/advanced-features/bff/operators.mdx +17 -17
  24. package/docs/zh/guides/basic-features/render/ssr-cache.mdx +14 -1
  25. package/docs/zh/guides/get-started/ultramodern.mdx +17 -83
  26. package/docs/zh/plugin/server-plugins/api.mdx +1 -0
  27. package/package.json +10 -10
  28. package/src/sandbox/csr-auth/src/routes/Auth-tsx.txt +10 -6
  29. package/src/sandbox/csr-auth/src/routes/page-tsx.txt +1 -0
  30. package/ultramodern-preset/package.json +2 -2
@@ -8,6 +8,7 @@ Usage: modern deploy [options]
8
8
  Options:
9
9
  -c --config <config> Specify configuration file path, either relative or absolute
10
10
  -s --skip-build Skip the build stage
11
+ --deploy-target <target> Deploy target (node, vercel, netlify, ghPages, cloudflare); overrides deploy.target and MODERNJS_DEPLOY
11
12
  -h, --help Display command help
12
13
  ```
13
14
 
@@ -21,7 +21,7 @@ For more details, refer to [useHonoContext](/apis/app/runtime/bff/use-backend-co
21
21
  When getting cookies in BFF functions, you need to get the request context through `useHonoContext`, then use `c.req.header('cookie')` to get the Cookie string and parse it manually:
22
22
 
23
23
  ```ts title="api/lambda/cookies.ts"
24
- import { Api, Get } from '@modern-js/plugin-bff/hono-server';
24
+ import { Api, Get } from '@modern-js/plugin-bff/server';
25
25
  import { useHonoContext } from '@modern-js/server-runtime';
26
26
 
27
27
  // Helper function to parse Cookie string
@@ -64,7 +64,7 @@ The `c.req.cookie()` method does not exist in the current version. You need to u
64
64
  When using Hono as the runtime framework, you can define interfaces through [Api functions](/guides/advanced-features/bff/operators.html):
65
65
 
66
66
  ```ts title="api/lambda/user.ts"
67
- import { Api, Get, Query } from '@modern-js/plugin-bff/hono-server';
67
+ import { Api, Get, Query } from '@modern-js/plugin-bff/server';
68
68
  import { z } from 'zod';
69
69
 
70
70
  const QuerySchema = z.object({
@@ -93,7 +93,7 @@ For more details about Api functions and operators, refer to [Creating Extensibl
93
93
  Hono supports a rich middleware ecosystem, and you can use middleware in BFF functions:
94
94
 
95
95
  ```ts title="api/lambda/user.ts"
96
- import { Api, Get, Middleware } from '@modern-js/plugin-bff/hono-server';
96
+ import { Api, Get, Middleware } from '@modern-js/plugin-bff/server';
97
97
 
98
98
  export const getUser = Api(
99
99
  Get('/user'),
@@ -71,11 +71,7 @@ Now, the project structure is as follows:
71
71
  ```
72
72
 
73
73
  The default workspace starts shell-only and installs the published BleedingDev
74
- package aliases:
75
-
76
- ```bash
77
- pnpm dlx @bleedingdev/modern-js-ultramodern-create my-super-app
78
- ```
74
+ package aliases.
79
75
 
80
76
  From a generated SuperApp workspace, add a business MicroVertical in place:
81
77
 
@@ -9,7 +9,7 @@ import NodeVersion from '@site-docs-en/components/nodeVersion.mdx';
9
9
  It is recommended to use [pnpm](https://pnpm.io/installation) to manage dependencies:
10
10
 
11
11
  ```bash
12
- mise use pnpm@11.24.0
12
+ mise use pnpm@11.27.1
13
13
  ```
14
14
 
15
15
  :::note
@@ -47,21 +47,33 @@ import EnableBFFCaution from "@site-docs-en/components/enable-bff-caution";
47
47
 
48
48
  :::caution Install the Effect peers yourself
49
49
  `effect` and `@effect/opentelemetry` are **optional exact peer dependencies** of
50
- `@modern-js/plugin-bff`, not dependencies. The plugin no longer bundles a copy —
51
- Effect 4 derives `Context` / `Service` keys per module instance, so a bundled copy
52
- would give your app a second Effect identity. Before setting
53
- `runtimeFramework: 'effect'` or importing `@modern-js/plugin-bff/effect`,
54
- `/effect-server`, `/effect-edge` or `/effect-client`, install the exact cohort:
50
+ `@modern-js/bff-effect`. Install them in the application so its API modules and
51
+ the framework use the same Effect instance. Before setting
52
+ `runtimeFramework: 'effect'` or importing `@modern-js/bff-effect/effect`,
53
+ `/effect-edge` or `/effect-client`, install the exact cohort:
55
54
 
56
55
  ```bash
57
- pnpm add effect@4.0.0-rc.112 @effect/opentelemetry@4.0.0-rc.112
56
+ pnpm add effect@4.0.0-rc.117 @effect/opentelemetry@4.0.0-rc.117
58
57
  ```
59
58
 
60
59
  The pin is exact because UltraModern ships Effect as one lockstep cohort. Apps
61
- using only `runtimeFramework: 'hono'` or the `./data-platform` lane need neither
62
- package.
60
+ using only native `runtimeFramework: 'hono'` or
61
+ `@modern-js/bff-effect/data-platform` need neither package.
63
62
  :::
64
63
 
64
+ Use `bffPlugin` from `@modern-js/plugin-bff-build-extensions` to register the
65
+ Effect runtime. It composes the native BFF plugin. Install
66
+ `@modern-js/bff-effect` and `@modern-js/plugin-bff-extensions` from the same
67
+ framework cohort as application production dependencies, so the adapter remains
68
+ available after development dependencies are removed. The build plugin can be a
69
+ development dependency. See the [runtime configuration example](/guides/advanced-features/bff/frameworks).
70
+
71
+ Native `@modern-js/plugin-bff/server` exports Hono APIs. For Node Effect APIs,
72
+ import framework helpers such as `defineEffectBff` from
73
+ `@modern-js/bff-effect/effect` and namespaces from the corresponding `effect/*`
74
+ modules. Worker handlers and worker request context use
75
+ `@modern-js/bff-effect/effect-edge`.
76
+
65
77
  Generated UltraModern workspaces use this runtime as the only generated HTTP API
66
78
  path. The API contract lives at `shared/api.ts`, the server runtime lives at
67
79
  `api/index.ts`, clients live under `src/api/*-client.ts`, and generated checks
@@ -173,7 +185,6 @@ export default defineConfig({
173
185
  endpoint: '/_data/batch',
174
186
  maxBatchSize: 16,
175
187
  maxBatchBytes: 64 * 1024,
176
- flushIntervalMs: 8,
177
188
  maxConcurrency: 4,
178
189
  requestTimeoutMs: 10000,
179
190
  allowedMethods: ['GET'],
@@ -207,9 +218,9 @@ export default defineConfig({
207
218
  });
208
219
  ```
209
220
 
210
- `batch.flushIntervalMs` controls the client-side micro-batch window in the generated Effect client. `maxConcurrency` and `requestTimeoutMs` are applied by the server batch gateway when dispatching items.
221
+ `maxConcurrency` and `requestTimeoutMs` control the server batch gateway. Native `HttpApiClient` calls send individual requests; they do not automatically batch requests.
211
222
 
212
- The generated `api.client.*` API only exists for loader-materialized `@api/index` imports. Directly importing the server entry (`api/index`) exposes the Effect BFF definition; its `client` property is a placeholder that fails on operation access.
223
+ Import a shared `HttpApi` contract and pass it to `HttpApiClient.make` or `makeEffectHttpApiClient`. The client is fully type-inferred; `defineEffectBff` exposes server handlers and does not contain a client.
213
224
 
214
225
  ## Effect cohort
215
226
 
@@ -218,14 +229,10 @@ through `pnpm-workspace.yaml` overrides. For the current UltraModern cohort,
218
229
  generated apps use:
219
230
 
220
231
  ```yaml
221
- trustPolicyExclude:
222
- - 'effect@4.0.0-rc.112'
223
- - '@effect/opentelemetry@4.0.0-rc.112'
224
-
225
232
  overrides:
226
- '@effect/opentelemetry': 4.0.0-rc.112
227
- '@effect/vitest': 4.0.0-rc.112
228
- effect: 4.0.0-rc.112
233
+ '@effect/opentelemetry': 4.0.0-rc.117
234
+ '@effect/vitest': 4.0.0-rc.117
235
+ effect: 4.0.0-rc.117
229
236
  ```
230
237
 
231
238
  Do not add a different direct `effect` version in an app package. A mismatched
@@ -233,10 +240,7 @@ Effect prerelease can fail while building layers or HTTP middleware because runt
233
240
  services come from different package instances. The strict 24-hour release-age
234
241
  gate applies to installed packages; the current cohort has no Effect age
235
242
  exemption, and override-only `@effect/vitest` is not an installed approval
236
- target. `trustPolicyExclude` is a separate policy:
237
- its exact `effect` and `@effect/opentelemetry` exceptions cover their
238
- trusted-publisher to provenance metadata transition and are not release-age
239
- approvals.
243
+ target.
240
244
 
241
245
  ## Contract tests
242
246
 
@@ -244,7 +248,7 @@ Strict Effect APIs should test the declared `HttpApi` contract, not a raw
244
248
  request handler. Edge-compatible tests can use the framework helper:
245
249
 
246
250
  ```ts
247
- import { createEffectBffTestHandler } from '@modern-js/plugin-bff/effect-edge';
251
+ import { createEffectBffTestHandler } from '@modern-js/bff-effect/effect-edge';
248
252
  import apiModule from '../api/index';
249
253
 
250
254
  const testApi = await createEffectBffTestHandler({
@@ -259,12 +263,9 @@ If you manually compose an Effect web handler in a low-level proof, provide the
259
263
  platform services explicitly:
260
264
 
261
265
  ```ts
262
- import {
263
- HttpApiBuilder,
264
- HttpRouter,
265
- HttpServer,
266
- Layer,
267
- } from '@modern-js/plugin-bff/effect-server';
266
+ import * as Layer from 'effect/Layer';
267
+ import { HttpRouter, HttpServer } from 'effect/unstable/http';
268
+ import { HttpApiBuilder } from 'effect/unstable/httpapi';
268
269
 
269
270
  const handler = HttpRouter.toWebHandler(
270
271
  HttpApiBuilder.layer(api).pipe(
@@ -284,13 +285,10 @@ current Effect v4 beta cohort, `HttpRouter.middleware(...)` returns a `Layer`
284
285
  directly:
285
286
 
286
287
  ```ts
287
- import {
288
- Effect,
289
- HttpApiBuilder,
290
- HttpMiddleware,
291
- HttpRouter,
292
- Layer,
293
- } from '@modern-js/plugin-bff/effect-server';
288
+ import * as Effect from 'effect/Effect';
289
+ import * as Layer from 'effect/Layer';
290
+ import { HttpMiddleware, HttpRouter } from 'effect/unstable/http';
291
+ import { HttpApiBuilder } from 'effect/unstable/httpapi';
294
292
 
295
293
  const corsLayer = HttpRouter.middleware(
296
294
  Effect.succeed(
@@ -11,6 +11,8 @@ Whether to enable [React Compiler](https://react.dev/learn/react-compiler). Reac
11
11
 
12
12
  Modern.js implements this capability based on the Rust-based React Compiler built into Rspack's `builtin:swc-loader` (equivalent to setting SWC's `jsc.transform.reactCompiler`), reusing Rspack's built-in SWC transform chain without introducing Babel.
13
13
 
14
+ The compiler only runs for browser environments (`output.target: 'web'`). Server environments (`node`, the `web-worker` SSR worker and BFF code) render once per request and gain nothing from memoization, so they are never compiled.
15
+
14
16
  :::tip
15
17
  This option is disabled by default. It must be enabled explicitly for any React version, including React 19.
16
18
  :::
@@ -17,7 +17,7 @@ Modern.js Effect API runtime now supports a request-envelope based data platform
17
17
 
18
18
  ## Runtime contract helpers
19
19
 
20
- Use `@modern-js/plugin-bff/data-platform` helpers to build and validate contracts:
20
+ Use `@modern-js/bff-effect/data-platform` helpers to build and validate contracts:
21
21
 
22
22
  ```ts
23
23
  import {
@@ -30,7 +30,7 @@ import {
30
30
  validateHydrationEnvelope,
31
31
  createInvalidationEvent,
32
32
  shouldApplyInvalidation,
33
- } from '@modern-js/plugin-bff/data-platform';
33
+ } from '@modern-js/bff-effect/data-platform';
34
34
  ```
35
35
 
36
36
  ## Effect runtime validation
@@ -5,10 +5,10 @@ title: Runtime Framework
5
5
 
6
6
  # Runtime Framework
7
7
 
8
- Modern.js supports two BFF runtime frameworks:
8
+ Modern.js and the UltraModern BFF extension provide two runtime frameworks:
9
9
 
10
- - `effect` (default): use [Effect HttpApi](https://effect.website/) runtime from `api/index`.
11
- - `hono`: use file-convention BFF handlers from `api/lambda/**`.
10
+ - `hono` is the native plugin default and uses file-convention handlers from `api/lambda/**`.
11
+ - `effect` is the UltraModern extension default and uses [Effect HttpApi](https://effect.website/) from `api/index`.
12
12
 
13
13
  `effect` and `hono` are strict runtime modes. There is no automatic fallback between them.
14
14
 
@@ -19,12 +19,18 @@ Generated UltraModern workspaces use strict Effect APIs: author HTTP APIs in
19
19
 
20
20
  ## Switch to Effect runtime
21
21
 
22
+ Use the fork build plugin below. It includes the native BFF plugin and registers
23
+ the Effect adapter. The application needs `@modern-js/bff-effect` and
24
+ `@modern-js/plugin-bff-extensions` as production dependencies from the same
25
+ framework cohort. Install the exact Effect peers described in
26
+ [`bff.effect`](/configure/app/bff/effect).
27
+
22
28
  ```ts title="modern.config.ts"
23
- import { bffPlugin } from '@modern-js/plugin-bff';
24
- import { defineConfig } from '@modern-js/app-tools';
29
+ import { bffPlugin } from '@modern-js/plugin-bff-build-extensions';
30
+ import { appTools, defineConfig } from '@modern-js/app-tools';
25
31
 
26
32
  export default defineConfig({
27
- plugins: [bffPlugin()],
33
+ plugins: [appTools(), bffPlugin()],
28
34
  bff: {
29
35
  runtimeFramework: 'effect',
30
36
  effect: {
@@ -46,7 +52,7 @@ import {
46
52
  HttpApiEndpoint,
47
53
  HttpApiGroup,
48
54
  Schema,
49
- } from '@modern-js/plugin-bff/effect-client';
55
+ } from '@modern-js/bff-effect/effect-client';
50
56
 
51
57
  export const bffApi = HttpApi.make('MyApi').add(
52
58
  HttpApiGroup.make('hello').add(
@@ -60,14 +66,12 @@ export const bffApi = HttpApi.make('MyApi').add(
60
66
  Implement your Effect API entry at `api/index.ts`:
61
67
 
62
68
  ```ts title="api/index.ts"
63
- import {
64
- Schema,
65
- Effect,
66
- HttpApiBuilder,
67
- defineEffectBff,
68
- Layer,
69
- ServiceMap,
70
- } from '@modern-js/plugin-bff/effect-server';
69
+ import { defineEffectBff } from '@modern-js/bff-effect/effect';
70
+ import * as Context from 'effect/Context';
71
+ import * as Effect from 'effect/Effect';
72
+ import * as Layer from 'effect/Layer';
73
+ import * as Schema from 'effect/Schema';
74
+ import { HttpApiBuilder } from 'effect/unstable/httpapi';
71
75
  import { bffApi } from '../shared/api';
72
76
 
73
77
  class GreetingUnavailableError extends Schema.TaggedError<GreetingUnavailableError>()(
@@ -77,7 +81,7 @@ class GreetingUnavailableError extends Schema.TaggedError<GreetingUnavailableErr
77
81
  },
78
82
  ) {}
79
83
 
80
- class GreetingService extends ServiceMap.Service<GreetingService>()('GreetingService', {
84
+ class GreetingService extends Context.Service<GreetingService>()('GreetingService', {
81
85
  make: Effect.succeed({
82
86
  hello: Effect.fn('GreetingService.hello')(function* () {
83
87
  if (Date.now() < 0) {
@@ -112,19 +116,27 @@ const layer = HttpApiBuilder.layer(bffApi).pipe(
112
116
  export default defineEffectBff({ api: bffApi, layer });
113
117
  ```
114
118
 
115
- Call Effect endpoints from browser code via `@api/index`:
119
+ Create a native, fully inferred client from the shared contract:
116
120
 
117
121
  ```ts title="src/routes/page.tsx"
118
- import api from '@api/index';
122
+ import { Effect, makeEffectHttpApiClient } from '@modern-js/bff-effect/effect-client';
123
+ import { bffApi } from '../../shared/api';
119
124
 
120
- const response = await api.client.hello.ping({});
125
+ const response = await Effect.runPromise(
126
+ makeEffectHttpApiClient(bffApi, { baseUrl: '/api' }).pipe(
127
+ Effect.flatMap(client => client.hello.ping({})),
128
+ ),
129
+ );
121
130
  ```
122
131
 
123
- The `api.client.*` surface is materialized by the BFF loader for `@api/index` imports. Do not import `api/index` directly and expect `client` to run in server code, scripts, or tests; direct entry imports expose the server runtime definition, and `client` is only a typed placeholder there.
132
+ Requests, responses, and declared errors are inferred from `bffApi`. No client generation or server-entry import is needed.
124
133
 
125
134
  For UltraModern, Effect `HttpApi` plus Effect BFF is the single blessed authored HTTP path. Use `HttpApi` endpoints with `query`, `params`, `payload`, `success`, and declared errors such as `HttpApiSchema.status(...)`; implement them with `HttpApiBuilder.group(...).handle(...)` and `HttpApiBuilder.layer(...).pipe(Layer.provide(...))`, then default-export the entry as `defineEffectBff({ api, layer })`. See `packages/server/bff-effect/tests/effect-edge-runtime.test.ts` for the live runtime shape.
126
135
 
127
- Hono and `api/lambda/**` are internal compatibility only and feature-frozen.
136
+ Native Hono applications import operators from `@modern-js/plugin-bff/server`.
137
+ UltraModern-generated applications keep their strict Effect API model. Worker
138
+ handlers use `@modern-js/bff-effect/effect-edge`, including its worker request
139
+ context exports; Node handlers use the Effect entry shown above.
128
140
 
129
141
  import Hono from '@site-docs-en/components/hono';
130
142
 
@@ -191,7 +191,7 @@ Parameters following the dynamic path are an object called `RequestOption`, whic
191
191
  In a standard function without dynamic routes, `RequestOption` can be obtained from the first parameter, for example:
192
192
 
193
193
  ```ts title="api/lambda/hello.ts"
194
- import type { RequestOption } from '@modern-js/plugin-bff/hono-server';
194
+ import type { RequestOption } from '@modern-js/plugin-bff/server';
195
195
 
196
196
  export async function post({
197
197
  query,
@@ -204,7 +204,7 @@ export async function post({
204
204
  Custom types can also be used here:
205
205
 
206
206
  ```ts title="api/lambda/hello.ts"
207
- import type { RequestOption } from '@modern-js/plugin-bff/hono-server';
207
+ import type { RequestOption } from '@modern-js/plugin-bff/server';
208
208
 
209
209
  type IQuery = {
210
210
  // some types
@@ -36,7 +36,7 @@ import BFFOperatorCode from '@site-docs/components/bff-operator-code';
36
36
  <BFFOperatorCode>
37
37
 
38
38
  ```typescript title="api/lambda/user.ts"
39
- import { Api, Post, Query, Data } from '@modern-js/plugin-bff/hono-server';
39
+ import { Api, Post, Query, Data } from '@modern-js/plugin-bff/server';
40
40
  import { z } from 'zod';
41
41
 
42
42
  const UserSchema = z.object({
@@ -89,7 +89,7 @@ As shown in the example below, you can specify the route and HTTP Method through
89
89
  <BFFOperatorCode>
90
90
 
91
91
  ```typescript title="api/lambda/user.ts"
92
- import { Api, Get, Query, Data } from '@modern-js/plugin-bff/hono-server';
92
+ import { Api, Get, Query, Data } from '@modern-js/plugin-bff/server';
93
93
 
94
94
  // Specify the interface route, Modern.js sets `bff.prefix` to `/api` by default,
95
95
  // so the interface route is `/api/user`, and the HTTP Method is GET.
@@ -107,7 +107,7 @@ When the route is not specified, the interface route is defined according to the
107
107
  <BFFOperatorCode>
108
108
 
109
109
  ```typescript title="api/lambda/user.ts"
110
- import { Api, Get, Query, Data } from '@modern-js/plugin-bff/hono-server';
110
+ import { Api, Get, Query, Data } from '@modern-js/plugin-bff/server';
111
111
 
112
112
  // No interface route specified, according to file convention and function name, the interface is api/user, HTTP Method is get.
113
113
  export const get = Api(Query(UserSchema), async ({ query }) => query);
@@ -144,7 +144,7 @@ Using the `Query` function, you can define the type of query. After using the `Q
144
144
 
145
145
  ```typescript title="api/lambda/user.ts"
146
146
  // Server-side code
147
- import { Api, Query } from '@modern-js/plugin-bff/hono-server';
147
+ import { Api, Query } from '@modern-js/plugin-bff/server';
148
148
  import { z } from 'zod';
149
149
 
150
150
  const UserSchema = z.object({
@@ -176,7 +176,7 @@ URL query parameters are strings by default. If you need numeric types, you need
176
176
  <BFFOperatorCode>
177
177
 
178
178
  ```typescript title="api/lambda/user.ts"
179
- import { Api, Get, Query } from '@modern-js/plugin-bff/hono-server';
179
+ import { Api, Get, Query } from '@modern-js/plugin-bff/server';
180
180
  import { z } from 'zod';
181
181
 
182
182
  const QuerySchema = z.object({
@@ -216,7 +216,7 @@ If you use the Data function, you must follow the HTTP protocol. When the HTTP M
216
216
  <BFFOperatorCode>
217
217
 
218
218
  ```typescript title="api/lambda/user.ts"
219
- import { Api, Data } from '@modern-js/plugin-bff/hono-server';
219
+ import { Api, Data } from '@modern-js/plugin-bff/server';
220
220
  import { z } from 'zod';
221
221
 
222
222
  const DataSchema = z.object({
@@ -249,7 +249,7 @@ Route parameters can implement dynamic routes and get parameters from the path.
249
249
  <BFFOperatorCode>
250
250
 
251
251
  ```typescript
252
- import { Api, Get, Params } from '@modern-js/plugin-bff/hono-server';
252
+ import { Api, Get, Params } from '@modern-js/plugin-bff/server';
253
253
  import { z } from 'zod';
254
254
 
255
255
  const UserSchema = z.object({
@@ -274,7 +274,7 @@ You can define the request headers required by the interface through the `Header
274
274
  <BFFOperatorCode>
275
275
 
276
276
  ```typescript
277
- import { Api, Headers } from '@modern-js/plugin-bff/hono-server';
277
+ import { Api, Headers } from '@modern-js/plugin-bff/server';
278
278
  import { z } from 'zod';
279
279
 
280
280
  const headerSchema = z.object({
@@ -336,7 +336,7 @@ The `Middleware` operator can be configured multiple times, and the execution or
336
336
  <BFFOperatorCode>
337
337
 
338
338
  ```typescript
339
- import { Api, Query, Middleware } from '@modern-js/plugin-bff/hono-server';
339
+ import { Api, Query, Middleware } from '@modern-js/plugin-bff/server';
340
340
  import { z } from 'zod';
341
341
 
342
342
  const UserSchema = z.object({
@@ -376,7 +376,7 @@ The `Pipe` operator can be configured multiple times. The execution order of fun
376
376
  <BFFOperatorCode>
377
377
 
378
378
  ```typescript
379
- import { Api, Query, Pipe } from '@modern-js/plugin-bff/hono-server';
379
+ import { Api, Query, Pipe } from '@modern-js/plugin-bff/server';
380
380
  import { z } from 'zod';
381
381
 
382
382
  const UserSchema = z.object({
@@ -408,7 +408,7 @@ Also,
408
408
  <BFFOperatorCode>
409
409
 
410
410
  ```typescript
411
- import { Api, Query, Pipe } from '@modern-js/plugin-bff/hono-server';
411
+ import { Api, Query, Pipe } from '@modern-js/plugin-bff/server';
412
412
  import { z } from 'zod';
413
413
 
414
414
  const UserSchema = z.object({
@@ -443,7 +443,7 @@ If you need to do more custom operations on the response, you can pass a functio
443
443
  <BFFOperatorCode>
444
444
 
445
445
  ```typescript
446
- import { Api, Query, Pipe } from '@modern-js/plugin-bff/hono-server';
446
+ import { Api, Query, Pipe } from '@modern-js/plugin-bff/server';
447
447
  import { z } from 'zod';
448
448
 
449
449
  const UserSchema = z.object({
@@ -487,7 +487,7 @@ You can specify the status code returned by the interface through the `HttpCode(
487
487
  <BFFOperatorCode>
488
488
 
489
489
  ```typescript
490
- import { Api, Query, Data, HttpCode } from '@modern-js/plugin-bff/hono-server';
490
+ import { Api, Query, Data, HttpCode } from '@modern-js/plugin-bff/server';
491
491
  import { z } from 'zod';
492
492
 
493
493
  const UserSchema = z.object({
@@ -523,7 +523,7 @@ Supports setting response headers through the `SetHeaders(headers: Record<string
523
523
  <BFFOperatorCode>
524
524
 
525
525
  ```typescript
526
- import { Api, Get, SetHeaders } from '@modern-js/plugin-bff/hono-server';
526
+ import { Api, Get, SetHeaders } from '@modern-js/plugin-bff/server';
527
527
 
528
528
  export default Api(
529
529
  Get('/hello'),
@@ -543,7 +543,7 @@ Supports redirecting the interface through `Redirect(url: string)`:
543
543
  <BFFOperatorCode>
544
544
 
545
545
  ```typescript
546
- import { Api, Get, Redirect } from '@modern-js/plugin-bff/hono-server';
546
+ import { Api, Get, Redirect } from '@modern-js/plugin-bff/server';
547
547
 
548
548
  export default Api(
549
549
  Get('/hello'),
@@ -561,7 +561,7 @@ As mentioned above, through operators, you can get `query`, `data`, `params`, et
561
561
  <BFFOperatorCode>
562
562
 
563
563
  ```typescript title="api/lambda/user.ts"
564
- import { Api, Get, Query } from '@modern-js/plugin-bff/hono-server';
564
+ import { Api, Get, Query } from '@modern-js/plugin-bff/server';
565
565
  import { useHonoContext } from '@modern-js/server-runtime';
566
566
  import { z } from 'zod';
567
567
 
@@ -610,7 +610,7 @@ In frontend development, some server interfaces (such as some configuration inte
610
610
  <BFFOperatorCode>
611
611
 
612
612
  ```typescript
613
- import { Api, SetHeaders } from '@modern-js/plugin-bff/hono-server';
613
+ import { Api, SetHeaders } from '@modern-js/plugin-bff/server';
614
614
 
615
615
  export const get = Api(
616
616
  // Cache will only take effect when using integrated calls or fetch for requests
@@ -35,7 +35,7 @@ export interface CacheControl {
35
35
  }
36
36
  ```
37
37
 
38
- Here, `customKey` is the custom cache key. By default, Modern.js uses the request `pathname` as the cache key, but developers can define it when necessary.
38
+ Here, `customKey` is the custom cache key. By default, the cache key is derived from the request's origin, normalized pathname (trailing slash removed), and query string. When `customKey` is set, it fully replaces the default key: the `customKey` callback receives the normalized pathname (not the `CacheOptionProvider`'s `req`) and is responsible for the whole partition (e.g. by tenant, host, or query) — it must not embed raw cookies or other credentials into the returned key.
39
39
 
40
40
  **Function Type**
41
41
 
@@ -106,6 +106,19 @@ export const cacheOption: CacheOption = {
106
106
 
107
107
  The above `/home` and `/about` are patterns, meaning `/home/abc` will also match. You can use regex in these patterns, such as `/home/.+`.
108
108
 
109
+ ### Cache Policy
110
+
111
+ The following policy is enforced automatically and cannot be overridden by the returned `CacheControl`:
112
+
113
+ - Only `GET` requests are cached.
114
+ - A request carrying a `Cookie` or `Authorization` header skips the cache unless `customKey` is set, since a custom key is treated as an explicit partitioning contract.
115
+ - A request with `Cache-Control: private`, `no-cache`, or `no-store` skips the cache.
116
+ - A response is only stored when it is `200`, has no `private`/`no-cache`/`no-store` in `Cache-Control`, has no `Set-Cookie`, and has no nonempty `Vary` header; otherwise any existing cache entry for that key is deleted instead of being written.
117
+ - If a `stale` revalidation produces a response that is no longer cacheable (for example, it became per-user), that already-served stale response is unaffected, but the cache entry is evicted so subsequent requests no longer hit it.
118
+ - A `CacheOptionProvider` returning `false` still disables caching entirely for that request, independent of the policy above.
119
+
120
+ Cache keys are namespaced (`__ssr__cache:v2:...`). Older un-namespaced entries — including ones already stored in a custom `Container` — are never read back; they simply age out under the container's own eviction/TTL. There is no global cache flush.
121
+
109
122
  ### Cache Container
110
123
 
111
124
  By default, the server uses memory for caching. Typically, services are deployed in a Serverless container, creating a new process for each access, making it impossible to use the previous cache.