@modern-js/main-doc 2.67.5 → 2.67.6
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.
- package/docs/en/apis/app/hooks/server/server.mdx +10 -0
- package/docs/en/apis/app/hooks/src/routes.mdx +3 -3
- package/docs/en/apis/app/runtime/bff/use-hono-context.mdx +30 -0
- package/docs/en/components/enable-bff.mdx +1 -27
- package/docs/en/components/rsbuild-config-tooltip.mdx +2 -2
- package/docs/en/components/tech-stack-node-framework.mdx +1 -1
- package/docs/en/configure/app/dev/asset-prefix.mdx +2 -3
- package/docs/en/configure/app/dev/client.mdx +2 -3
- package/docs/en/configure/app/dev/hmr.mdx +2 -3
- package/docs/en/configure/app/dev/live-reload.mdx +2 -3
- package/docs/en/configure/app/dev/progress-bar.mdx +2 -3
- package/docs/en/configure/app/dev/setup-middlewares.mdx +2 -3
- package/docs/en/configure/app/dev/watch-files.mdx +2 -3
- package/docs/en/configure/app/dev/write-to-disk.mdx +2 -3
- package/docs/en/configure/app/html/app-icon.mdx +2 -3
- package/docs/en/configure/app/html/crossorigin.mdx +2 -3
- package/docs/en/configure/app/html/favicon.mdx +2 -3
- package/docs/en/configure/app/html/inject.mdx +2 -3
- package/docs/en/configure/app/html/meta.mdx +2 -3
- package/docs/en/configure/app/html/mount-id.mdx +2 -3
- package/docs/en/configure/app/html/output-structure.mdx +2 -3
- package/docs/en/configure/app/html/script-loading.mdx +2 -3
- package/docs/en/configure/app/html/tags.mdx +2 -3
- package/docs/en/configure/app/html/template-parameters.mdx +2 -3
- package/docs/en/configure/app/html/template.mdx +2 -3
- package/docs/en/configure/app/html/title.mdx +2 -3
- package/docs/en/configure/app/output/asset-prefix.mdx +2 -3
- package/docs/en/configure/app/output/charset.mdx +2 -3
- package/docs/en/configure/app/output/copy.mdx +2 -3
- package/docs/en/configure/app/output/css-modules.mdx +2 -3
- package/docs/en/configure/app/output/data-uri-limit.mdx +2 -3
- package/docs/en/configure/app/output/dist-path.mdx +2 -4
- package/docs/en/configure/app/output/externals.mdx +2 -3
- package/docs/en/configure/app/output/filename-hash.mdx +2 -3
- package/docs/en/configure/app/output/filename.mdx +2 -3
- package/docs/en/configure/app/output/inject-styles.mdx +2 -3
- package/docs/en/configure/app/output/inline-scripts.mdx +2 -3
- package/docs/en/configure/app/output/inline-styles.mdx +2 -3
- package/docs/en/configure/app/output/legal-comments.mdx +2 -3
- package/docs/en/configure/app/output/minify.mdx +2 -3
- package/docs/en/configure/app/output/override-browserslist.mdx +2 -3
- package/docs/en/configure/app/output/polyfill.mdx +2 -3
- package/docs/en/configure/app/output/source-map.mdx +2 -3
- package/docs/en/configure/app/performance/build-cache.mdx +2 -3
- package/docs/en/configure/app/performance/bundle-analyze.mdx +2 -3
- package/docs/en/configure/app/performance/chunk-split.mdx +2 -3
- package/docs/en/configure/app/performance/dns-prefetch.mdx +2 -3
- package/docs/en/configure/app/performance/preconnect.mdx +2 -3
- package/docs/en/configure/app/performance/prefetch.mdx +2 -3
- package/docs/en/configure/app/performance/preload.mdx +2 -3
- package/docs/en/configure/app/performance/print-file-size.mdx +2 -3
- package/docs/en/configure/app/performance/profile.mdx +2 -3
- package/docs/en/configure/app/performance/remove-console.mdx +2 -3
- package/docs/en/configure/app/performance/remove-moment-locale.mdx +2 -3
- package/docs/en/configure/app/security/nonce.mdx +2 -3
- package/docs/en/configure/app/security/sri.mdx +0 -1
- package/docs/en/configure/app/server/port.mdx +2 -3
- package/docs/en/configure/app/source/alias-strategy.mdx +2 -3
- package/docs/en/configure/app/source/alias.mdx +2 -3
- package/docs/en/configure/app/source/decorators.mdx +2 -3
- package/docs/en/configure/app/source/define.mdx +2 -3
- package/docs/en/configure/app/source/exclude.mdx +2 -3
- package/docs/en/configure/app/source/include.mdx +2 -3
- package/docs/en/configure/app/source/pre-entry.mdx +2 -3
- package/docs/en/configure/app/source/transform-import.mdx +2 -3
- package/docs/en/configure/app/tools/css-extract.mdx +2 -3
- package/docs/en/configure/app/tools/css-loader.mdx +2 -2
- package/docs/en/configure/app/tools/html-plugin.mdx +7 -3
- package/docs/en/configure/app/tools/lightningcss-loader.mdx +2 -3
- package/docs/en/configure/app/tools/postcss.mdx +2 -3
- package/docs/en/configure/app/tools/rspack.mdx +2 -3
- package/docs/en/configure/app/tools/style-loader.mdx +2 -3
- package/docs/en/configure/app/tools/swc.mdx +1 -1
- package/docs/en/guides/advanced-features/_meta.json +0 -1
- package/docs/en/guides/advanced-features/bff/extend-server.mdx +33 -82
- package/docs/en/guides/advanced-features/bff/frameworks.mdx +12 -68
- package/docs/en/guides/advanced-features/page-performance/_meta.json +1 -1
- package/docs/en/guides/advanced-features/page-performance/react-compiler.mdx +44 -0
- package/docs/en/guides/advanced-features/web-server.mdx +211 -20
- package/docs/en/guides/basic-features/deploy.mdx +3 -3
- package/docs/en/guides/basic-features/output-files.mdx +0 -28
- package/docs/en/tutorials/first-app/c04-routes.mdx +4 -2
- package/docs/en/tutorials/first-app/c05-loader.mdx +4 -1
- package/docs/zh/apis/app/hooks/server/server.mdx +10 -0
- package/docs/zh/apis/app/hooks/src/routes.mdx +3 -3
- package/docs/zh/apis/app/runtime/bff/use-hono-context.mdx +31 -0
- package/docs/zh/components/enable-bff.mdx +2 -27
- package/docs/zh/components/rsbuild-config-tooltip.mdx +2 -2
- package/docs/zh/components/tech-stack-node-framework.mdx +1 -1
- package/docs/zh/configure/app/dev/asset-prefix.mdx +2 -3
- package/docs/zh/configure/app/dev/client.mdx +2 -3
- package/docs/zh/configure/app/dev/hmr.mdx +2 -3
- package/docs/zh/configure/app/dev/live-reload.mdx +2 -3
- package/docs/zh/configure/app/dev/progress-bar.mdx +2 -3
- package/docs/zh/configure/app/dev/setup-middlewares.mdx +2 -3
- package/docs/zh/configure/app/dev/watch-files.mdx +2 -3
- package/docs/zh/configure/app/dev/write-to-disk.mdx +2 -3
- package/docs/zh/configure/app/html/app-icon.mdx +2 -3
- package/docs/zh/configure/app/html/crossorigin.mdx +2 -3
- package/docs/zh/configure/app/html/favicon.mdx +2 -3
- package/docs/zh/configure/app/html/inject.mdx +2 -3
- package/docs/zh/configure/app/html/meta.mdx +2 -3
- package/docs/zh/configure/app/html/mount-id.mdx +2 -3
- package/docs/zh/configure/app/html/output-structure.mdx +2 -3
- package/docs/zh/configure/app/html/script-loading.mdx +2 -3
- package/docs/zh/configure/app/html/tags.mdx +2 -3
- package/docs/zh/configure/app/html/template-parameters.mdx +2 -3
- package/docs/zh/configure/app/html/template.mdx +2 -3
- package/docs/zh/configure/app/html/title.mdx +2 -3
- package/docs/zh/configure/app/output/asset-prefix.mdx +2 -3
- package/docs/zh/configure/app/output/charset.mdx +2 -3
- package/docs/zh/configure/app/output/copy.mdx +2 -3
- package/docs/zh/configure/app/output/css-modules.mdx +2 -3
- package/docs/zh/configure/app/output/data-uri-limit.mdx +2 -3
- package/docs/zh/configure/app/output/dist-path.mdx +2 -4
- package/docs/zh/configure/app/output/externals.mdx +2 -3
- package/docs/zh/configure/app/output/filename-hash.mdx +2 -3
- package/docs/zh/configure/app/output/filename.mdx +2 -3
- package/docs/zh/configure/app/output/inject-styles.mdx +2 -3
- package/docs/zh/configure/app/output/inline-scripts.mdx +2 -3
- package/docs/zh/configure/app/output/inline-styles.mdx +2 -3
- package/docs/zh/configure/app/output/legal-comments.mdx +2 -3
- package/docs/zh/configure/app/output/minify.mdx +2 -3
- package/docs/zh/configure/app/output/override-browserslist.mdx +2 -3
- package/docs/zh/configure/app/output/polyfill.mdx +2 -3
- package/docs/zh/configure/app/output/source-map.mdx +2 -3
- package/docs/zh/configure/app/performance/build-cache.mdx +2 -3
- package/docs/zh/configure/app/performance/bundle-analyze.mdx +2 -3
- package/docs/zh/configure/app/performance/chunk-split.mdx +2 -3
- package/docs/zh/configure/app/performance/dns-prefetch.mdx +2 -3
- package/docs/zh/configure/app/performance/preconnect.mdx +2 -3
- package/docs/zh/configure/app/performance/prefetch.mdx +2 -3
- package/docs/zh/configure/app/performance/preload.mdx +2 -3
- package/docs/zh/configure/app/performance/print-file-size.mdx +2 -3
- package/docs/zh/configure/app/performance/profile.mdx +2 -3
- package/docs/zh/configure/app/performance/remove-console.mdx +2 -3
- package/docs/zh/configure/app/performance/remove-moment-locale.mdx +2 -3
- package/docs/zh/configure/app/security/nonce.mdx +2 -3
- package/docs/zh/configure/app/security/sri.mdx +0 -1
- package/docs/zh/configure/app/server/port.mdx +2 -3
- package/docs/zh/configure/app/source/alias-strategy.mdx +2 -3
- package/docs/zh/configure/app/source/alias.mdx +2 -3
- package/docs/zh/configure/app/source/decorators.mdx +2 -3
- package/docs/zh/configure/app/source/define.mdx +2 -3
- package/docs/zh/configure/app/source/exclude.mdx +2 -3
- package/docs/zh/configure/app/source/include.mdx +2 -3
- package/docs/zh/configure/app/source/pre-entry.mdx +2 -3
- package/docs/zh/configure/app/source/transform-import.mdx +2 -3
- package/docs/zh/configure/app/tools/css-extract.mdx +2 -3
- package/docs/zh/configure/app/tools/css-loader.mdx +2 -3
- package/docs/zh/configure/app/tools/html-plugin.mdx +6 -3
- package/docs/zh/configure/app/tools/lightningcss-loader.mdx +2 -3
- package/docs/zh/configure/app/tools/postcss.mdx +2 -3
- package/docs/zh/configure/app/tools/rspack.mdx +2 -3
- package/docs/zh/configure/app/tools/style-loader.mdx +2 -3
- package/docs/zh/configure/app/tools/swc.mdx +1 -1
- package/docs/zh/guides/advanced-features/_meta.json +0 -1
- package/docs/zh/guides/advanced-features/bff/extend-server.mdx +28 -76
- package/docs/zh/guides/advanced-features/bff/frameworks.mdx +6 -66
- package/docs/zh/guides/advanced-features/page-performance/_meta.json +1 -1
- package/docs/zh/guides/advanced-features/page-performance/react-compiler.mdx +44 -0
- package/docs/zh/guides/advanced-features/web-server.mdx +209 -25
- package/docs/zh/guides/basic-features/deploy.mdx +4 -3
- package/docs/zh/guides/basic-features/output-files.mdx +0 -28
- package/docs/zh/tutorials/first-app/c04-routes.mdx +4 -2
- package/docs/zh/tutorials/first-app/c05-loader.mdx +4 -1
- package/package.json +7 -4
- package/rspress.config.ts +16 -1
- package/src/components/RsbuildLink/index.tsx +2 -2
- package/src/index.ts +1 -5
- package/src/pages/index.tsx +3 -3
- package/docs/en/apis/app/hooks/api/middleware.mdx +0 -11
- package/docs/en/apis/app/runtime/bff/hook.mdx +0 -44
- package/docs/en/apis/app/runtime/bff/use-context.mdx +0 -38
- package/docs/en/configure/app/bff/enable-handle-web.mdx +0 -24
- package/docs/en/guides/advanced-features/custom-server.mdx +0 -218
- package/docs/zh/apis/app/hooks/api/middleware.mdx +0 -11
- package/docs/zh/apis/app/runtime/bff/hook.mdx +0 -44
- package/docs/zh/apis/app/runtime/bff/use-context.mdx +0 -38
- package/docs/zh/configure/app/bff/enable-handle-web.mdx +0 -24
- package/docs/zh/guides/advanced-features/custom-server.mdx +0 -216
@@ -1,35 +1,41 @@
|
|
1
1
|
# Extend BFF Server
|
2
2
|
|
3
|
-
In some applications, developers may want to handle all BFF functions uniformly, such as
|
3
|
+
In some applications, developers may want to handle all BFF functions uniformly, such as authentication, logging, data processing, etc.
|
4
4
|
|
5
|
-
Modern.js
|
5
|
+
Modern.js allows users to freely extend the BFF Server through [Middleware](/guides/advanced-features/web-server.html#middleware) method.
|
6
6
|
|
7
|
-
## Middleware
|
7
|
+
## Using Middleware
|
8
8
|
|
9
|
-
Developers can
|
9
|
+
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:
|
10
10
|
|
11
|
-
```ts title="
|
12
|
-
import {
|
13
|
-
|
11
|
+
```ts title="server/modern.server.ts"
|
12
|
+
import {
|
13
|
+
type MiddlewareHandler,
|
14
|
+
defineServerConfig,
|
15
|
+
} from '@modern-js/server-runtime';
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
res.status(400);
|
21
|
-
res.json({ code: -1, message: 'need login' });
|
22
|
-
} else {
|
23
|
-
next();
|
24
|
-
}
|
25
|
-
} else {
|
26
|
-
next();
|
17
|
+
const requireAuthForApi: MiddlewareHandler = async (c, next) => {
|
18
|
+
if (c.req.path.startsWith('/api') && c.req.path !== '/api/login') {
|
19
|
+
const sid = c.req.cookie('sid');
|
20
|
+
if (!sid) {
|
21
|
+
return c.json({ code: -1, message: 'need login' }, 400);
|
27
22
|
}
|
28
|
-
}
|
23
|
+
}
|
24
|
+
await next();
|
25
|
+
};
|
26
|
+
|
27
|
+
export default defineServerConfig({
|
28
|
+
middlewares: [
|
29
|
+
{
|
30
|
+
name: 'require-auth-for-api',
|
31
|
+
handler: requireAuthForApi,
|
32
|
+
},
|
33
|
+
]
|
29
34
|
});
|
35
|
+
|
30
36
|
```
|
31
37
|
|
32
|
-
Then add a
|
38
|
+
Then add a regular BFF function `api/lambda/hello.ts`:
|
33
39
|
|
34
40
|
```ts title="api/lambda/hello.ts"
|
35
41
|
export default async () => {
|
@@ -37,7 +43,7 @@ export default async () => {
|
|
37
43
|
};
|
38
44
|
```
|
39
45
|
|
40
|
-
Next, in the frontend
|
46
|
+
Next, in the frontend `src/routes/page.tsx`, add the interface access code and directly use the integrated method to call:
|
41
47
|
|
42
48
|
```ts title="src/routes/page.tsx"
|
43
49
|
import { useState, useEffect } from 'react';
|
@@ -59,14 +65,14 @@ export default () => {
|
|
59
65
|
};
|
60
66
|
```
|
61
67
|
|
62
|
-
Now run the `dev` command to start the project, and
|
68
|
+
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:
|
63
69
|
|
64
70
|

|
65
71
|
|
66
|
-
Finally, modify the frontend code
|
72
|
+
Finally, modify the frontend code `src/routes/page.tsx`, and call the login interface before accessing `/api/hello`:
|
67
73
|
|
68
74
|
:::note
|
69
|
-
|
75
|
+
This part does not implement a real login interface; the code is just for demonstration.
|
70
76
|
:::
|
71
77
|
|
72
78
|
```ts
|
@@ -92,63 +98,8 @@ export default () => {
|
|
92
98
|
};
|
93
99
|
```
|
94
100
|
|
95
|
-
Refresh the page
|
101
|
+
Refresh the page, and you can see that the access to `/api/hello` is successful:
|
96
102
|
|
97
103
|

|
98
104
|
|
99
|
-
The above code simulates
|
100
|
-
|
101
|
-
:::info
|
102
|
-
The way middleware is written may differ depending on the runtime framework. For details, see [Runtime Frameworks](/guides/advanced-features/bff/frameworks).
|
103
|
-
:::
|
104
|
-
|
105
|
-
## Define Server Instance
|
106
|
-
|
107
|
-
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.
|
108
|
-
|
109
|
-
import { Tabs, Tab as TabItem } from "@theme";
|
110
|
-
|
111
|
-
<Tabs>
|
112
|
-
<TabItem value="express" label="Express.js" default>
|
113
|
-
|
114
|
-
```ts title="api/app.ts"
|
115
|
-
import express from 'express';
|
116
|
-
|
117
|
-
const app = express();
|
118
|
-
app.use(async (req, res, next) => {
|
119
|
-
console.info(`access url: ${req.url}`);
|
120
|
-
next();
|
121
|
-
});
|
122
|
-
|
123
|
-
export default app;
|
124
|
-
```
|
125
|
-
|
126
|
-
</TabItem>
|
127
|
-
<TabItem value="koa" label="Koa.js">
|
128
|
-
|
129
|
-
```ts title="api/app.ts"
|
130
|
-
import koa from 'koa';
|
131
|
-
|
132
|
-
const app = new Koa();
|
133
|
-
app.use(async (ctx, next) => {
|
134
|
-
console.info(`access url: ${ctx.url}`);
|
135
|
-
await next();
|
136
|
-
});
|
137
|
-
|
138
|
-
export default app;
|
139
|
-
```
|
140
|
-
|
141
|
-
</TabItem>
|
142
|
-
</Tabs>
|
143
|
-
|
144
|
-
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.
|
145
|
-
|
146
|
-
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.
|
147
|
-
|
148
|
-
:::note
|
149
|
-
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.
|
150
|
-
:::
|
151
|
-
|
152
|
-
:::caution
|
153
|
-
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**.
|
154
|
-
:::
|
105
|
+
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.
|
@@ -1,81 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
---
|
2
|
+
sidebar_position: 3
|
3
|
+
title: Runtime Framework
|
4
|
+
---
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
## Accessing Request Context
|
6
|
+
# Runtime Framework
|
8
7
|
|
9
|
-
|
8
|
+
Modern.js uses [Hono.js](https://hono.dev/) as the BFF and Server runtime framework, so you can [extend BFF Server](/guides/advanced-features/bff/extend-server.html) based on the Hono.js ecosystem.
|
10
9
|
|
11
|
-
|
10
|
+
## Getting Request Context
|
12
11
|
|
13
|
-
|
14
|
-
<TabItem value="express" label="Express.js" default>
|
12
|
+
Sometimes in BFF functions, it's necessary to obtain the request context to handle more logic. In such cases, you can use `useHonoContext` to get it:
|
15
13
|
|
16
14
|
```ts title="api/lambda/hello.ts"
|
17
|
-
import {
|
15
|
+
import { useHonoContext } from '@modern-js/plugin-bff/hono'
|
18
16
|
export const get = async () => {
|
19
|
-
const
|
20
|
-
console.info(`access url: ${req.url}`);
|
17
|
+
const c = useHonoContext();
|
18
|
+
console.info(`access url: ${c.req.url}`);
|
21
19
|
return 'Hello Modern.js'
|
22
20
|
};
|
23
21
|
```
|
24
22
|
|
25
|
-
</TabItem>
|
26
|
-
<TabItem value="koa" label="Koa.js">
|
27
|
-
|
28
|
-
```ts title="api/lambda/hello.ts"
|
29
|
-
import { useContext } from '@modern-js/runtime/koa'
|
30
|
-
export const get = async () => {
|
31
|
-
const ctx = useContext();
|
32
|
-
console.info(`access url: ${req.url}`);
|
33
|
-
return 'Hello Modern.js'
|
34
|
-
};
|
35
|
-
```
|
36
|
-
|
37
|
-
</TabItem>
|
38
|
-
</Tabs>
|
39
|
-
|
40
|
-
:::info
|
41
|
-
For more details, refer to [useContext](/apis/app/runtime/bff/use-context).
|
42
|
-
:::
|
43
|
-
|
44
|
-
## Using Middleware
|
45
|
-
|
46
|
-
In BFF functions, you may need to use middleware to handle more logic. Depending on the runtime framework, you need to use different APIs:
|
47
|
-
|
48
|
-
<Tabs>
|
49
|
-
<TabItem value="express" label="Express.js" default>
|
50
|
-
|
51
|
-
```ts title="api/_app.ts"
|
52
|
-
import { hook } from '@modern-js/runtime/express';
|
53
|
-
|
54
|
-
export default hook(({ addMiddleware }) => {
|
55
|
-
addMiddleware((req, res, next) => {
|
56
|
-
req.query.id = 'koa';
|
57
|
-
next();
|
58
|
-
});
|
59
|
-
});
|
60
|
-
```
|
61
|
-
|
62
|
-
</TabItem>
|
63
|
-
<TabItem value="koa" label="Koa.js">
|
64
|
-
|
65
|
-
```ts title="api/_app.ts"
|
66
|
-
import { hook } from '@modern-js/runtime/koa';
|
67
|
-
|
68
|
-
export default hook(({ addMiddleware }) => {
|
69
|
-
addMiddleware(async (ctx, next) => {
|
70
|
-
ctx.req.query.id = 'koa';
|
71
|
-
await next();
|
72
|
-
});
|
73
|
-
});
|
74
|
-
```
|
75
|
-
|
76
|
-
</TabItem>
|
77
|
-
</Tabs>
|
78
|
-
|
79
23
|
:::info
|
80
|
-
For more details, refer to [
|
24
|
+
For more details, refer to [useHonoContext](/apis/app/runtime/bff/use-hono-context).
|
81
25
|
:::
|
@@ -1 +1 @@
|
|
1
|
-
["code-split", "inline-assets", "optimize-bundle"]
|
1
|
+
["code-split", "inline-assets", "optimize-bundle", "react-compiler"]
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# React Compiler
|
2
|
+
|
3
|
+
The React Compiler is an experimental compiler introduced in React 19 that can automatically optimize your React code.
|
4
|
+
|
5
|
+
Before starting to use the React Compiler, it is recommended to read the [React Compiler documentation](https://zh-hans.react.dev/learn/react-compiler) to understand its features, current status, and usage.
|
6
|
+
|
7
|
+
## How to Use
|
8
|
+
|
9
|
+
The steps to use the React Compiler in Modern.js are as follows:
|
10
|
+
|
11
|
+
1. Modern.js does not officially support React 19 yet, but you can install `react-compiler-runtime@rc` in React 17 or 18 projects to allow the compiled code to run on versions before 19.
|
12
|
+
|
13
|
+
2. Currently, the React Compiler only provides a Babel plugin, so you need to install `babel-plugin-react-compiler`.
|
14
|
+
|
15
|
+
3. Register the Babel plugin in your Modern.js configuration file:
|
16
|
+
|
17
|
+
```ts title="modern.config.ts"
|
18
|
+
import { appTools, defineConfig } from '@modern-js/app-tools';
|
19
|
+
|
20
|
+
export default defineConfig({
|
21
|
+
runtime: {
|
22
|
+
router: true,
|
23
|
+
},
|
24
|
+
tools: {
|
25
|
+
babel(_, { addPlugins }) {
|
26
|
+
addPlugins([
|
27
|
+
[
|
28
|
+
'babel-plugin-react-compiler',
|
29
|
+
{
|
30
|
+
target: '18',
|
31
|
+
},
|
32
|
+
],
|
33
|
+
]);
|
34
|
+
},
|
35
|
+
},
|
36
|
+
plugins: [
|
37
|
+
appTools({
|
38
|
+
bundler: 'rspack',
|
39
|
+
}),
|
40
|
+
],
|
41
|
+
});
|
42
|
+
```
|
43
|
+
|
44
|
+
> For detailed code, you can refer to the [Modern.js & React Compiler example project](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/react-compiler)
|
@@ -2,42 +2,233 @@
|
|
2
2
|
sidebar_position: 16
|
3
3
|
---
|
4
4
|
|
5
|
-
# Custom Web Server
|
5
|
+
# Custom Web Server
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
Modern.js encapsulates most server-side capabilities required by projects, typically eliminating the need for server-side development. However, in certain scenarios such as user authentication, request preprocessing, or adding page skeletons, custom server-side logic may still be necessary.
|
8
|
+
|
9
|
+
## Starting a Custom Web Server
|
10
|
+
|
11
|
+
:::info
|
12
|
+
You must ensure that the Modern.js version is x.67.5 or above.
|
9
13
|
:::
|
10
14
|
|
11
|
-
|
15
|
+
To start a custom web server, the following steps need to be taken:
|
16
|
+
1. Add and install the dependencies `@modern-js/server-runtime` and `ts-node` to `devDependencies`.
|
17
|
+
2. Add `server` to the `include` section of `tsconfig`.
|
18
|
+
3. Create a file `server/modern.server.ts` in the project directory, where you can write custom logic.
|
19
|
+
|
20
|
+
## Capabilities of the Custom Web Server
|
21
|
+
|
22
|
+
In the `server/modern.server.ts` file, you can add the following configurations to extend the Server:
|
23
|
+
- **Middleware**
|
24
|
+
- **Render Middleware**
|
25
|
+
- **Server-side Plugin**
|
26
|
+
|
27
|
+
In the **Plugin**, you can define **Middleware** and **RenderMiddleware**. The middleware loading process is illustrated in the following diagram:
|
12
28
|
|
13
|
-
|
29
|
+
<img
|
30
|
+
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/10eh7nuhpenuhog/server-md-wf.png"
|
31
|
+
style={{ width: '100%', maxWidth: '540px' }}
|
32
|
+
/>
|
33
|
+
|
34
|
+
### Basic Configuration
|
35
|
+
|
36
|
+
```ts title="server/modern.server.ts"
|
37
|
+
import { defineServerConfig } from '@modern-js/server-runtime';
|
38
|
+
|
39
|
+
export default defineServerConfig({
|
40
|
+
middlewares: [],
|
41
|
+
renderMiddlewares: [],
|
42
|
+
plugins: [],
|
43
|
+
});
|
44
|
+
```
|
45
|
+
|
46
|
+
|
47
|
+
### Type Definition
|
48
|
+
|
49
|
+
`defineServerConfig` type definition is as follows:
|
50
|
+
|
51
|
+
```ts
|
52
|
+
import type { MiddlewareHandler } from 'hono';
|
53
|
+
|
54
|
+
type MiddlewareOrder = 'pre' | 'post' | 'default';
|
55
|
+
type MiddlewareObj = {
|
56
|
+
name: string;
|
57
|
+
path?: string;
|
58
|
+
method?: 'options' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'all';
|
59
|
+
handler: MiddlewareHandler | MiddlewareHandler[];
|
60
|
+
before?: Array<MiddlewareObj['name']>;
|
61
|
+
order?: MiddlewareOrder;
|
62
|
+
};
|
63
|
+
type ServerConfig = {
|
64
|
+
middlewares?: MiddlewareObj[];
|
65
|
+
renderMiddlewares?: MiddlewareObj[];
|
66
|
+
plugins?: (ServerPlugin | ServerPluginLegacy)[];
|
67
|
+
}
|
68
|
+
```
|
69
|
+
|
70
|
+
|
71
|
+
### Middleware
|
72
|
+
|
73
|
+
Middleware supports executing custom logic before and after the **request handling** and **page routing** processes in Modern.js services.
|
74
|
+
If custom logic needs to handle both API routes and page routes, Middleware is the clear choice.
|
14
75
|
|
15
76
|
:::note
|
16
|
-
|
77
|
+
If you only need to handle BFF API routes, you can determine whether a request is for a BFF API by checking if `req.path` starts with the BFF `prefix`.
|
17
78
|
:::
|
18
79
|
|
19
|
-
|
80
|
+
Usage is as follows:
|
81
|
+
|
82
|
+
```ts title="server/modern.server.ts"
|
83
|
+
import { defineServerConfig, type MiddlewareHandler } from '@modern-js/server-runtime';
|
20
84
|
|
21
|
-
|
85
|
+
export const handler: MiddlewareHandler = async (c, next) => {
|
86
|
+
const monitors = c.get('monitors');
|
87
|
+
const start = Date.now();
|
22
88
|
|
23
|
-
|
24
|
-
|
25
|
-
|
89
|
+
await next();
|
90
|
+
|
91
|
+
const end = Date.now();
|
92
|
+
// Report Duration
|
93
|
+
monitors.timing('request_timing', end - start);
|
94
|
+
};
|
95
|
+
|
96
|
+
export default defineServerConfig({
|
97
|
+
middlewares: [
|
98
|
+
{
|
99
|
+
name: 'request-timing',
|
100
|
+
handler,
|
101
|
+
},
|
102
|
+
],
|
103
|
+
});
|
26
104
|
```
|
27
105
|
|
28
|
-
|
106
|
+
:::warning
|
107
|
+
You must execute the `next` function to proceed with the subsequent Middleware.
|
108
|
+
:::
|
109
|
+
|
29
110
|
|
30
|
-
|
31
|
-
import { serverPlugin } from '@modern-js/plugin-server';
|
111
|
+
### RenderMiddleware
|
32
112
|
|
33
|
-
|
34
|
-
|
113
|
+
If you only need to handle the logic before and after page rendering, modern.js also provides rendering middleware, which can be used as follows:
|
114
|
+
|
115
|
+
```ts title="server/modern.server.ts"
|
116
|
+
import { defineServerConfig, type MiddlewareHandler } from '@modern-js/server-runtime';
|
117
|
+
|
118
|
+
// Inject render performance metrics
|
119
|
+
const renderTiming: MiddlewareHandler = async (c, next) => {
|
120
|
+
const start = Date.now();
|
121
|
+
|
122
|
+
await next();
|
123
|
+
|
124
|
+
const end = Date.now();
|
125
|
+
c.res.headers.set('server-timing', `render; dur=${end - start}`);
|
126
|
+
};
|
127
|
+
|
128
|
+
// Modify the Response Body
|
129
|
+
const modifyResBody: MiddlewareHandler = async (c, next) => {
|
130
|
+
await next();
|
131
|
+
|
132
|
+
const { res } = c;
|
133
|
+
const text = await res.text();
|
134
|
+
const newText = text.replace('<body>', '<body> <h3>bytedance</h3>');
|
135
|
+
|
136
|
+
c.res = c.body(newText, {
|
137
|
+
status: res.status,
|
138
|
+
headers: res.headers,
|
139
|
+
});
|
140
|
+
};
|
141
|
+
|
142
|
+
export default defineServerConfig({
|
143
|
+
renderMiddlewares: [
|
144
|
+
{
|
145
|
+
name: 'render-timing',
|
146
|
+
handler: renderTiming,
|
147
|
+
},
|
148
|
+
{
|
149
|
+
name: 'modify-res-body',
|
150
|
+
handler: modifyResBody,
|
151
|
+
},
|
152
|
+
],
|
153
|
+
});
|
154
|
+
```
|
155
|
+
|
156
|
+
|
157
|
+
### Plugin
|
158
|
+
|
159
|
+
Modern.js supports adding the aforementioned middleware and rendering middleware for the Server in custom plugins, which can be used as follows:
|
160
|
+
|
161
|
+
|
162
|
+
```ts title="server/plugins/server.ts"
|
163
|
+
import type { ServerPluginLegacy } from '@modern-js/server-runtime';
|
164
|
+
|
165
|
+
export default (): ServerPluginLegacy => ({
|
166
|
+
name: 'serverPlugin',
|
167
|
+
setup(api) {
|
168
|
+
return {
|
169
|
+
prepare(serverConfig) {
|
170
|
+
const { middlewares, renderMiddlewares } = api.useAppContext();
|
171
|
+
|
172
|
+
// Inject server-side data for page dataLoader consumption
|
173
|
+
middlewares?.push({
|
174
|
+
name: 'server-plugin-middleware',
|
175
|
+
handler: async (c, next) => {
|
176
|
+
c.set('message', 'hi modern.js');
|
177
|
+
await next();
|
178
|
+
// ...
|
179
|
+
},
|
180
|
+
});
|
181
|
+
|
182
|
+
// redirect
|
183
|
+
renderMiddlewares?.push({
|
184
|
+
name: 'server-plugin-render-middleware',
|
185
|
+
handler: async (c, next) => {
|
186
|
+
const user = getUser(c.req);
|
187
|
+
if (!user) {
|
188
|
+
return c.redirect('/login');
|
189
|
+
}
|
190
|
+
|
191
|
+
await next();
|
192
|
+
},
|
193
|
+
});
|
194
|
+
return serverConfig;
|
195
|
+
},
|
196
|
+
};
|
197
|
+
},
|
35
198
|
});
|
36
199
|
```
|
37
200
|
|
38
|
-
Once enabled, a `server/index.ts` file will be automatically created in the project directory where custom logic can be implemented.
|
39
201
|
|
40
|
-
|
202
|
+
```ts title="server/modern.server.ts"
|
203
|
+
import { defineServerConfig } from '@modern-js/server-runtime';
|
204
|
+
import serverPlugin from './plugins/serverPlugin';
|
205
|
+
|
206
|
+
export default defineServerConfig({
|
207
|
+
plugins: [serverPlugin()],
|
208
|
+
});
|
209
|
+
```
|
210
|
+
|
211
|
+
|
212
|
+
```ts title="src/routes/page.data.ts"
|
213
|
+
import { useHonoContext } from '@modern-js/server-runtime';
|
214
|
+
import { defer } from '@modern-js/runtime/router';
|
215
|
+
|
216
|
+
export default () => {
|
217
|
+
const ctx = useHonoContext();
|
218
|
+
// SSR scenario consumes data injected by the Server Side
|
219
|
+
const message = ctx.get('message');
|
220
|
+
|
221
|
+
// ...
|
222
|
+
};
|
223
|
+
|
224
|
+
```
|
225
|
+
|
226
|
+
|
227
|
+
## Legacy API (Deprecated)
|
228
|
+
|
229
|
+
:::warning
|
230
|
+
The legacy API is compatible but no longer recommended. For extending server capabilities, please refer to [Custom Web Server](/guides/advanced-features/web-server.html#custom-web-server). For migration guidelines, see [Migrating to the New Version of Custom Web Server](/guides/advanced-features/web-server.html#migrate-to-the-new-version-of-custom-web-server).
|
231
|
+
:::
|
41
232
|
|
42
233
|
### Unstable Middleware
|
43
234
|
|
@@ -102,7 +293,7 @@ For detailed API and more usage, see [Hook](/apis/app/runtime/web-server/hook).
|
|
102
293
|
:::
|
103
294
|
|
104
295
|
|
105
|
-
## Migrate to the New Version of Custom Server
|
296
|
+
## Migrate to the New Version of Custom Web Server
|
106
297
|
|
107
298
|
### Migration Background
|
108
299
|
|
@@ -153,7 +344,7 @@ Differences between UnstableMiddleware Context and Hono Context:
|
|
153
344
|
| `c.request` | `c.req.raw` | Refer to [HonoRequest raw](https://hono.dev/docs/api/request#raw) documentation |
|
154
345
|
| `c.response` | `c.res` | Refer to [Hono Context res](https://hono.dev/docs/api/context#res) documentation |
|
155
346
|
| `c.route` | `c.get('route')` | Get application context information. |
|
156
|
-
| `loaderContext.get` | `honoContext.get` | After injecting data using `c.set`, consume in dataLoader: the old version uses `loaderContext.get`, refer to the new version in [Plugin](/guides/advanced-features/
|
347
|
+
| `loaderContext.get` | `honoContext.get` | After injecting data using `c.set`, consume in dataLoader: the old version uses `loaderContext.get`, refer to the new version in [Plugin](/guides/advanced-features/web-server.html#plugin) example |
|
157
348
|
|
158
349
|
|
159
350
|
#### Middleware
|
@@ -285,6 +285,7 @@ Add the following script to `packages/app/package.json` to run `build` command o
|
|
285
285
|
```
|
286
286
|
|
287
287
|
Add the following content to the `packages/app/vercel.json` file:
|
288
|
+
|
288
289
|
```json title="vercel.json"
|
289
290
|
{
|
290
291
|
"buildCommand": "npm run deploy",
|
@@ -298,7 +299,7 @@ Just submit your code and deploy it using the Vercel platform.
|
|
298
299
|
|
299
300
|
If you're creating a GitHub Pages for a repository without a custom domain, the page URL will follow this format: `http://<username>.github.io/<repository-name>`. Therefore, you need to add the following configuration in `modern.config.ts`:
|
300
301
|
|
301
|
-
```
|
302
|
+
```ts
|
302
303
|
import { defineConfig } from '@modern-js/app-tools';
|
303
304
|
|
304
305
|
export default defineConfig({
|
@@ -331,7 +332,6 @@ For branch deployment, follow these steps:
|
|
331
332
|
:::info
|
332
333
|
1. Running `MODERNJS_DEPLOY=ghPages modern deploy` will build the production output for GitHub in the .output directory.
|
333
334
|
2. You can refer to the [project](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/modern-js-deploy-csr)
|
334
|
-
|
335
335
|
:::
|
336
336
|
|
337
337
|
For GitHub Actions deployment, select Settings > Pages > Source > GitHub Actions, and add a workflow file to the project. You can refer to the [example](https://github.com/web-infra-dev/modern-js-examples/tree/main/examples/modern-js-deploy-csr).
|
@@ -407,7 +407,7 @@ Nginx is a high-performance HTTP and reverse proxy server that can handle static
|
|
407
407
|
|
408
408
|
If your project is a purely front-end project, you can also deploy the application through Nginx. Here is an example of an Nginx configuration to demonstrate how to host the output of a purely front-end project.
|
409
409
|
|
410
|
-
```
|
410
|
+
```nginx title="nginx.conf"
|
411
411
|
# user [user] [group];
|
412
412
|
worker_processes 1;
|
413
413
|
|
@@ -96,34 +96,6 @@ dist
|
|
96
96
|
└── qux.[hash].mp4
|
97
97
|
```
|
98
98
|
|
99
|
-
## Node.js Output Directory
|
100
|
-
|
101
|
-
When you enable SSR or SSG features in Modern.js, Modern.js will generate a Node.js bundle after the build and output it to the `bundles` directory.
|
102
|
-
|
103
|
-
```bash
|
104
|
-
dist
|
105
|
-
├── bundles
|
106
|
-
│ └── [name].js
|
107
|
-
├── static
|
108
|
-
└── html
|
109
|
-
```
|
110
|
-
|
111
|
-
Node.js files usually only contain JS files, no HTML or CSS. Also, JS file names will not contain hash.
|
112
|
-
|
113
|
-
You can modify the output path of Node.js files through the [output.distPath.server](/configure/app/output/dist-path) config.
|
114
|
-
|
115
|
-
For example, output Node.js files to the `server` directory:
|
116
|
-
|
117
|
-
```ts
|
118
|
-
export default {
|
119
|
-
output: {
|
120
|
-
distPath: {
|
121
|
-
server: 'server',
|
122
|
-
},
|
123
|
-
},
|
124
|
-
};
|
125
|
-
```
|
126
|
-
|
127
99
|
## Flatten the Directory
|
128
100
|
|
129
101
|
Sometimes you don't want the dist directory to have too many levels, you can set the directory to an empty string to flatten the generated directory.
|
@@ -118,10 +118,11 @@ import { Radio } from 'antd';
|
|
118
118
|
|
119
119
|
Then modify the top of the UI to add a set of radio group:
|
120
120
|
|
121
|
-
```tsx
|
121
|
+
```tsx
|
122
122
|
export default function Layout() {
|
123
123
|
return (
|
124
124
|
<div>
|
125
|
+
// [!code highlight:6]
|
125
126
|
<div className="h-16 p-2 flex items-center justify-center">
|
126
127
|
<Radio.Group onChange={handleSetList} value={currentList}>
|
127
128
|
<Radio value="/">All</Radio>
|
@@ -146,8 +147,9 @@ import { Outlet, useLocation, useNavigate } from '@modern-js/runtime/router';
|
|
146
147
|
|
147
148
|
Finally, add local state and related logic to the Layout component:
|
148
149
|
|
149
|
-
```tsx
|
150
|
+
```tsx
|
150
151
|
export default function Layout() {
|
152
|
+
// [!code highlight:8]
|
151
153
|
const navigate = useNavigate();
|
152
154
|
const location = useLocation();
|
153
155
|
const [currentList, setList] = useState(location.pathname || '/');
|