@modern-js/main-doc 2.54.6 → 2.56.0
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/apis/app/hooks/src/entry.mdx +42 -0
- package/docs/en/apis/app/hooks/src/entry.server.mdx +52 -0
- package/docs/en/apis/app/hooks/src/index_.mdx +4 -0
- package/docs/en/apis/app/runtime/core/bootstrap.mdx +4 -0
- package/docs/en/apis/app/runtime/core/create-app.mdx +5 -1
- package/docs/en/apis/app/runtime/core/create-root.mdx +22 -0
- package/docs/en/apis/app/runtime/core/render.mdx +42 -0
- package/docs/en/apis/app/runtime/ssr/renderStreaming.mdx +69 -0
- package/docs/en/apis/app/runtime/ssr/renderString.mdx +62 -0
- package/docs/en/apis/app/runtime/ssr/requestHandler.mdx +47 -0
- package/docs/en/components/debug-app.mdx +3 -3
- package/docs/en/configure/app/dev/live-reload.mdx +27 -0
- package/docs/en/configure/app/dev/setup-middlewares.mdx +69 -0
- package/docs/en/configure/app/dev/watch-files.mdx +59 -0
- package/docs/en/configure/app/dev/write-to-disk.mdx +38 -0
- package/docs/en/configure/app/output/ssg.mdx +4 -0
- package/docs/en/configure/app/source/enable-async-entry.mdx +4 -4
- package/docs/en/configure/app/source/enable-custom-entry.mdx +41 -0
- package/docs/en/guides/advanced-features/ssr/cache.mdx +7 -2
- package/docs/en/guides/basic-features/data/data-fetch.mdx +1 -1
- package/docs/en/guides/basic-features/routes.mdx +1 -1
- package/docs/en/guides/concept/entries.mdx +50 -36
- package/docs/en/guides/get-started/quick-start.mdx +24 -8
- package/docs/en/guides/topic-detail/framework-plugin/hook-list.mdx +30 -177
- package/docs/zh/apis/app/hooks/src/entry.mdx +42 -0
- package/docs/zh/apis/app/hooks/src/entry.server.mdx +52 -0
- package/docs/zh/apis/app/hooks/src/index_.mdx +4 -0
- package/docs/zh/apis/app/runtime/core/bootstrap.mdx +4 -0
- package/docs/zh/apis/app/runtime/core/create-app.mdx +5 -1
- package/docs/zh/apis/app/runtime/core/create-root.mdx +22 -0
- package/docs/zh/apis/app/runtime/core/render.mdx +43 -0
- package/docs/zh/apis/app/runtime/ssr/renderStreaming.mdx +69 -0
- package/docs/zh/apis/app/runtime/ssr/renderString.mdx +62 -0
- package/docs/zh/apis/app/runtime/ssr/requestHandler.mdx +47 -0
- package/docs/zh/components/debug-app.mdx +3 -2
- package/docs/zh/configure/app/dev/client.mdx +1 -1
- package/docs/zh/configure/app/dev/live-reload.mdx +27 -0
- package/docs/zh/configure/app/dev/setup-middlewares.mdx +69 -0
- package/docs/zh/configure/app/dev/watch-files.mdx +59 -0
- package/docs/zh/configure/app/dev/write-to-disk.mdx +38 -0
- package/docs/zh/configure/app/output/ssg.mdx +4 -0
- package/docs/zh/configure/app/source/enable-async-entry.mdx +4 -4
- package/docs/zh/configure/app/source/enable-custom-entry.mdx +41 -0
- package/docs/zh/guides/advanced-features/ssr/cache.mdx +6 -2
- package/docs/zh/guides/basic-features/data/data-fetch.mdx +1 -1
- package/docs/zh/guides/basic-features/routes.mdx +1 -1
- package/docs/zh/guides/concept/entries.mdx +54 -41
- package/docs/zh/guides/get-started/quick-start.mdx +26 -10
- package/docs/zh/guides/topic-detail/framework-plugin/hook-list.mdx +29 -174
- package/package.json +7 -7
- package/docs/en/apis/app/hooks/src/pages.mdx +0 -186
- package/docs/zh/apis/app/hooks/src/pages.mdx +0 -187
- package/docs/zh/apis/monorepo/commands/deploy.mdx +0 -38
@@ -0,0 +1,43 @@
|
|
1
|
+
---
|
2
|
+
title: render
|
3
|
+
---
|
4
|
+
# render
|
5
|
+
|
6
|
+
用于渲染项目组件。
|
7
|
+
|
8
|
+
## 使用姿势
|
9
|
+
|
10
|
+
```ts
|
11
|
+
import { render } from '@modern-js/runtime/browser';
|
12
|
+
|
13
|
+
render(<ModernRoot />);
|
14
|
+
```
|
15
|
+
|
16
|
+
## 函数签名
|
17
|
+
|
18
|
+
```ts
|
19
|
+
export function render(App: React.ReactElement, id?: HTMLElement | string): Promise<any>;
|
20
|
+
```
|
21
|
+
|
22
|
+
### 参数
|
23
|
+
|
24
|
+
- `App`:通过 [`createRoot`](./create-root) 创建的 ReactElement 实例。
|
25
|
+
- `id`:要挂载的 DOM 根元素 id,如 `"root"`。
|
26
|
+
|
27
|
+
## 示例
|
28
|
+
|
29
|
+
```tsx
|
30
|
+
import { createRoot } from '@modern-js/runtime/react';
|
31
|
+
import { render } from '@modern-js/runtime/browser';
|
32
|
+
|
33
|
+
const ModernRoot = createRoot();
|
34
|
+
|
35
|
+
async function beforeRender() {
|
36
|
+
// todo
|
37
|
+
}
|
38
|
+
|
39
|
+
beforeRender().then(() => {
|
40
|
+
render(<ModernRoot />);
|
41
|
+
});
|
42
|
+
```
|
43
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
---
|
2
|
+
title: renderStreaming
|
3
|
+
---
|
4
|
+
|
5
|
+
# renderStreaming
|
6
|
+
|
7
|
+
用于 React v18+ Streaming SSR 渲染出可读流, 配合 `createRequestHandler` 使用
|
8
|
+
|
9
|
+
## 使用
|
10
|
+
|
11
|
+
```tsx title="src/entry.server.tsx"
|
12
|
+
import {
|
13
|
+
renderStreaming,
|
14
|
+
createRequestHandler,
|
15
|
+
} from '@modern-js/runtime/ssr/server';
|
16
|
+
|
17
|
+
const handleRequest = async (request, ServerRoot, options) => {
|
18
|
+
const stream = await renderStreaming(request, <ServerRoot />, options);
|
19
|
+
|
20
|
+
return new Response(stream, {
|
21
|
+
headers: {
|
22
|
+
'content-type': 'text/html; charset=utf-8',
|
23
|
+
},
|
24
|
+
});
|
25
|
+
};
|
26
|
+
|
27
|
+
export default createRequestHandler(handleRequest);
|
28
|
+
```
|
29
|
+
|
30
|
+
## 函数签名
|
31
|
+
|
32
|
+
```ts
|
33
|
+
export type RenderStreaming = (
|
34
|
+
request: Request,
|
35
|
+
serverRoot: React.ReactElement,
|
36
|
+
optinos: RenderOptions,
|
37
|
+
) => Promise<ReadableStream>;
|
38
|
+
```
|
39
|
+
|
40
|
+
## 示例
|
41
|
+
|
42
|
+
```tsx title="src/entry.server.tsx"
|
43
|
+
import {
|
44
|
+
renderStreaming,
|
45
|
+
createRequestHandler,
|
46
|
+
} from '@modern-js/runtime/ssr/server';
|
47
|
+
|
48
|
+
const handleRequest = async (request, ServerRoot, options) => {
|
49
|
+
// do something before render
|
50
|
+
const stream = await renderStreaming(request, <ServerRoot />, options);
|
51
|
+
|
52
|
+
// docs: https://developer.mozilla.org/en-US/docs/Web/API/TransformStream
|
53
|
+
const transformStream = new TransformStream({
|
54
|
+
transform(chunk, controller) {
|
55
|
+
// do some transform
|
56
|
+
},
|
57
|
+
});
|
58
|
+
|
59
|
+
stream.pipeThrough(transformStream);
|
60
|
+
|
61
|
+
return new Response(transformStream.readable, {
|
62
|
+
headers: {
|
63
|
+
'content-type': 'text/html; charset=utf-8',
|
64
|
+
},
|
65
|
+
});
|
66
|
+
};
|
67
|
+
|
68
|
+
export default createRequestHandler(handleRequest);
|
69
|
+
```
|
@@ -0,0 +1,62 @@
|
|
1
|
+
---
|
2
|
+
title: renderString
|
3
|
+
---
|
4
|
+
|
5
|
+
# renderString
|
6
|
+
|
7
|
+
用于 React String SSR 渲染出字符串,配合 `createRequestHandler` 使用
|
8
|
+
|
9
|
+
## 使用
|
10
|
+
|
11
|
+
```tsx title="src/entry.server.tsx"
|
12
|
+
import {
|
13
|
+
renderString,
|
14
|
+
createRequestHandler,
|
15
|
+
} from '@modern-js/runtime/ssr/server';
|
16
|
+
|
17
|
+
const handleRequest = async (request, ServerRoot, options) => {
|
18
|
+
const body = await renderString(request, <ServerRoot />, options);
|
19
|
+
|
20
|
+
return new Response(body, {
|
21
|
+
headers: {
|
22
|
+
'content-type': 'text/html; charset=utf-8',
|
23
|
+
},
|
24
|
+
});
|
25
|
+
};
|
26
|
+
|
27
|
+
export default createRequestHandler(handleRequest);
|
28
|
+
```
|
29
|
+
|
30
|
+
## 函数签名
|
31
|
+
|
32
|
+
```ts
|
33
|
+
export type RenderString = (
|
34
|
+
request: Request,
|
35
|
+
serverRoot: React.ReactElement,
|
36
|
+
optinos: RenderOptions,
|
37
|
+
) => Promise<string>;
|
38
|
+
```
|
39
|
+
|
40
|
+
## 示例
|
41
|
+
|
42
|
+
```tsx title="src/entry.server.tsx"
|
43
|
+
import {
|
44
|
+
renderString,
|
45
|
+
createRequestHandler,
|
46
|
+
} from '@modern-js/runtime/ssr/server';
|
47
|
+
|
48
|
+
const handleRequest = async (request, ServerRoot, options) => {
|
49
|
+
// do something before render
|
50
|
+
const body = await renderString(request, <ServerRoot />, options);
|
51
|
+
|
52
|
+
const newBody = body + '<div>Byte-Dance</div>';
|
53
|
+
|
54
|
+
return new Response(newBody, {
|
55
|
+
headers: {
|
56
|
+
'content-type': 'text/html; charset=utf-8',
|
57
|
+
},
|
58
|
+
});
|
59
|
+
};
|
60
|
+
|
61
|
+
export default createRequestHandler(handleRequest);
|
62
|
+
```
|
@@ -0,0 +1,47 @@
|
|
1
|
+
---
|
2
|
+
title: createRequestHandler
|
3
|
+
---
|
4
|
+
|
5
|
+
# createRequestHandler
|
6
|
+
|
7
|
+
用于自定义 Server-Side Rendering 入口返回 requestHandler
|
8
|
+
|
9
|
+
## 使用
|
10
|
+
|
11
|
+
```tsx title="src/entry.server.tsx"
|
12
|
+
import {
|
13
|
+
renderString,
|
14
|
+
createRequestHandler,
|
15
|
+
} from '@modern-js/runtime/ssr/server';
|
16
|
+
|
17
|
+
const handleRequest = async (request, ServerRoot, options) => {
|
18
|
+
const body = await renderString(request, <ServerRoot />, options);
|
19
|
+
|
20
|
+
return new Response(body, {
|
21
|
+
headers: {
|
22
|
+
'content-type': 'text/html; charset=utf-8',
|
23
|
+
},
|
24
|
+
});
|
25
|
+
};
|
26
|
+
|
27
|
+
export default createRequestHandler(handleRequest);
|
28
|
+
```
|
29
|
+
|
30
|
+
## 函数签名
|
31
|
+
|
32
|
+
```ts
|
33
|
+
export type HandleRequest = (
|
34
|
+
request: Request,
|
35
|
+
ServerRoot: React.ComponentType
|
36
|
+
options: HandleRequestOptions,
|
37
|
+
) => Promise<Response>;
|
38
|
+
|
39
|
+
export type RequestHandler = (
|
40
|
+
request: Request,
|
41
|
+
options: RequestHandlerOptions,
|
42
|
+
) => Promise<Response>;
|
43
|
+
|
44
|
+
export type CreateRequestHandler = (
|
45
|
+
handleRequest: HandleRequest,
|
46
|
+
) => Promise<RequestHandler>;
|
47
|
+
```
|
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
sidebar_label: liveReload
|
3
|
+
---
|
4
|
+
|
5
|
+
# dev.liveReload
|
6
|
+
|
7
|
+
- **类型:** `boolean`
|
8
|
+
- **默认值:** `true`
|
9
|
+
|
10
|
+
是否在源文件变更时自动刷新页面。
|
11
|
+
|
12
|
+
默认情况下,Modern.js 会优先使用 HMR 来更新模块。当 HMR 功能被禁用,或者某些场景 HMR 无法生效时,会自动降级到 liveReload。
|
13
|
+
|
14
|
+
请查看 [模块热更新](https://rsbuild.dev/zh/guide/advanced/hmr) 来了解更多内容。
|
15
|
+
|
16
|
+
## 禁用 liveReload
|
17
|
+
|
18
|
+
如果你需要禁用 liveReload,可以将 `dev.hmr` 和 `dev.liveReload` 同时设置为 `false`,此时页面上不会发起 Web Socket 请求到 dev server,也不会在文件变更时自动刷新页面。
|
19
|
+
|
20
|
+
```js
|
21
|
+
export default {
|
22
|
+
dev: {
|
23
|
+
hmr: false,
|
24
|
+
liveReload: false,
|
25
|
+
},
|
26
|
+
};
|
27
|
+
```
|
@@ -0,0 +1,69 @@
|
|
1
|
+
---
|
2
|
+
sidebar_label: setupMiddlewares
|
3
|
+
---
|
4
|
+
|
5
|
+
# dev.setupMiddlewares
|
6
|
+
|
7
|
+
- **类型:**
|
8
|
+
|
9
|
+
```ts
|
10
|
+
type ServerAPIs = {
|
11
|
+
sockWrite: (
|
12
|
+
type: string,
|
13
|
+
data?: string | boolean | Record<string, any>,
|
14
|
+
) => void;
|
15
|
+
};
|
16
|
+
|
17
|
+
type SetupMiddlewares = Array<
|
18
|
+
(
|
19
|
+
middlewares: {
|
20
|
+
unshift: (...handlers: RequestHandler[]) => void;
|
21
|
+
push: (...handlers: RequestHandler[]) => void;
|
22
|
+
},
|
23
|
+
server: ServerAPIs,
|
24
|
+
) => void
|
25
|
+
>;
|
26
|
+
```
|
27
|
+
|
28
|
+
- **默认值:** `undefined`
|
29
|
+
|
30
|
+
提供执行自定义函数和应用自定义中间件的能力。
|
31
|
+
|
32
|
+
中间件的执行顺序是: `unshift` => 内置中间件 => `push`。
|
33
|
+
|
34
|
+
```js
|
35
|
+
export default {
|
36
|
+
dev: {
|
37
|
+
setupMiddlewares: [
|
38
|
+
(middlewares, server) => {
|
39
|
+
middlewares.unshift((req, res, next) => {
|
40
|
+
next();
|
41
|
+
});
|
42
|
+
|
43
|
+
middlewares.push((req, res, next) => {
|
44
|
+
next();
|
45
|
+
});
|
46
|
+
},
|
47
|
+
],
|
48
|
+
},
|
49
|
+
};
|
50
|
+
```
|
51
|
+
|
52
|
+
一些特殊场景需求可能需要使用服务器 API:
|
53
|
+
|
54
|
+
- sockWrite。允许向 HMR 客户端传递一些消息,HMR 客户端将根据接收到的消息类型进行不同的处理。如果你发送一个 "content-changed " 的消息,页面将会重新加载。
|
55
|
+
|
56
|
+
```js
|
57
|
+
export default {
|
58
|
+
dev: {
|
59
|
+
setupMiddlewares: [
|
60
|
+
(middlewares, server) => {
|
61
|
+
// 添加自定义 watcher 并在文件更新时触发页面刷新
|
62
|
+
watcher.on('change', (changed) => {
|
63
|
+
server.sockWrite('content-changed');
|
64
|
+
});
|
65
|
+
},
|
66
|
+
],
|
67
|
+
},
|
68
|
+
};
|
69
|
+
```
|
@@ -0,0 +1,59 @@
|
|
1
|
+
---
|
2
|
+
sidebar_label: watchFiles
|
3
|
+
---
|
4
|
+
|
5
|
+
# dev.watchFiles
|
6
|
+
|
7
|
+
- **类型:**
|
8
|
+
|
9
|
+
```ts
|
10
|
+
type WatchFiles = {
|
11
|
+
paths: string | string[];
|
12
|
+
// chokidar 选项
|
13
|
+
options?: WatchOptions;
|
14
|
+
};
|
15
|
+
```
|
16
|
+
|
17
|
+
- **默认值:** `undefined`
|
18
|
+
|
19
|
+
监视指定文件和目录的变化。当文件发生变化时,页面将重新加载。
|
20
|
+
|
21
|
+
如果 `dev.hmr` 和 `dev.liveReload` 都设置为 false,则 `watchFiles` 将被忽略。
|
22
|
+
|
23
|
+
:::tip
|
24
|
+
WatchFiles 中文件发生变化时,不会触发配置文件的重新加载及重新编译。
|
25
|
+
:::
|
26
|
+
|
27
|
+
### 示例
|
28
|
+
|
29
|
+
你可以配置一个 glob 模式 / 目录 / 文件的列表,用于监视文件变化。
|
30
|
+
|
31
|
+
```js
|
32
|
+
export default {
|
33
|
+
dev: {
|
34
|
+
watchFiles: {
|
35
|
+
// 监视单个文件
|
36
|
+
paths: 'public/demo.txt',
|
37
|
+
// 使用 glob 模式
|
38
|
+
paths: 'src/**/*.txt',
|
39
|
+
// 监视多个文件路径
|
40
|
+
paths: ['src/**/*.txt', 'public/**/*'],
|
41
|
+
},
|
42
|
+
},
|
43
|
+
};
|
44
|
+
```
|
45
|
+
|
46
|
+
你也可以通过传入一个包含 `paths` 和 `options` 属性的对象,来指定 [chokidar](https://github.com/paulmillr/chokidar#api) 选项。
|
47
|
+
|
48
|
+
```js
|
49
|
+
export default {
|
50
|
+
dev: {
|
51
|
+
watchFiles: {
|
52
|
+
paths: 'src/**/*.txt',
|
53
|
+
options: {
|
54
|
+
usePolling: false,
|
55
|
+
},
|
56
|
+
},
|
57
|
+
},
|
58
|
+
};
|
59
|
+
```
|
@@ -0,0 +1,38 @@
|
|
1
|
+
---
|
2
|
+
sidebar_label: writeToDisk
|
3
|
+
---
|
4
|
+
|
5
|
+
# dev.writeToDisk
|
6
|
+
|
7
|
+
- **类型:** `boolean | ((filename: string) => boolean)`
|
8
|
+
- **默认值:** `(file: string) => !file.includes('.hot-update.')`
|
9
|
+
|
10
|
+
用于控制是否将开发环境的构建产物写入到磁盘上。
|
11
|
+
|
12
|
+
## 写入内存
|
13
|
+
|
14
|
+
你可以选择将构建产物构建产物保存在 dev server 的内存中,从而减少文件操作产生的开销。
|
15
|
+
|
16
|
+
只需要将 `dev.writeToDisk` 配置项设置为 `false` 即可:
|
17
|
+
|
18
|
+
```ts
|
19
|
+
export default {
|
20
|
+
dev: {
|
21
|
+
writeToDisk: false,
|
22
|
+
},
|
23
|
+
};
|
24
|
+
```
|
25
|
+
|
26
|
+
## 匹配部分文件
|
27
|
+
|
28
|
+
你也可以将 `dev.writeToDisk` 设置为函数来匹配一部分文件,函数返回 `false` 时不会写入文件,返回值 `true` 时会将文件写入磁盘。
|
29
|
+
|
30
|
+
例如,Modern.js 会默认将文件写入磁盘,并排除热更新临时文件:
|
31
|
+
|
32
|
+
```ts
|
33
|
+
export default {
|
34
|
+
dev: {
|
35
|
+
writeToDisk: (file) => !file.includes('.hot-update.'),
|
36
|
+
},
|
37
|
+
};
|
38
|
+
```
|
@@ -35,15 +35,15 @@ export default defineConfig({
|
|
35
35
|
node_modules
|
36
36
|
└─ .modern-js
|
37
37
|
└─ main
|
38
|
-
├─ bootstrap.jsx #
|
39
|
-
├─ index.js #
|
38
|
+
├─ bootstrap.jsx # 异步入口文件(asynchronous boundary)
|
39
|
+
├─ index.js # 真正的入口代码
|
40
40
|
└─ index.html
|
41
41
|
```
|
42
42
|
|
43
|
-
其中 `
|
43
|
+
其中 `bootstrap.js` 的内容如下:
|
44
44
|
|
45
45
|
```js
|
46
|
-
import('./
|
46
|
+
import('./index.jsx');
|
47
47
|
```
|
48
48
|
|
49
49
|
此时,就可以在当前页面中消费任意的远程模块了。
|
@@ -0,0 +1,41 @@
|
|
1
|
+
---
|
2
|
+
sidebar_label: enableCustomEntry
|
3
|
+
---
|
4
|
+
|
5
|
+
# source.enableCustomEntry
|
6
|
+
|
7
|
+
- **类型:** `boolean`
|
8
|
+
- **默认值:** `false`
|
9
|
+
|
10
|
+
该选项用于使用 Modern.js 自定义入口场景。
|
11
|
+
|
12
|
+
开启此选项后,Modern.js 将使用 `src/entry.[jt]sx` 文件作为项目的入口, 具体使用姿势可参考[页面入口](/guides/concept/entries.html)。
|
13
|
+
|
14
|
+
## 示例
|
15
|
+
|
16
|
+
首先,在配置文件中开启此选项:
|
17
|
+
|
18
|
+
```ts title="modern.config.ts"
|
19
|
+
export default defineConfig({
|
20
|
+
source: {
|
21
|
+
enableCustomEntry: true,
|
22
|
+
},
|
23
|
+
});
|
24
|
+
```
|
25
|
+
|
26
|
+
创建 `src/entry.tsx` 文件:
|
27
|
+
|
28
|
+
```tsx
|
29
|
+
import { createRoot } from '@modern-js/runtime/react';
|
30
|
+
import { render } from '@modern-js/runtime/browser';
|
31
|
+
|
32
|
+
const ModernRoot = createRoot();
|
33
|
+
|
34
|
+
async function beforeRender() {
|
35
|
+
// todo
|
36
|
+
}
|
37
|
+
|
38
|
+
beforeRender().then(() => {
|
39
|
+
render(<ModernRoot />);
|
40
|
+
});
|
41
|
+
```
|
@@ -55,10 +55,10 @@ export interface CacheControl {
|
|
55
55
|
```ts
|
56
56
|
export type CacheOptionProvider = (
|
57
57
|
req: IncomingMessage,
|
58
|
-
) => Promise<CacheControl> | CacheControl;
|
58
|
+
) => Promise<CacheControl | false> | CacheControl | false;
|
59
59
|
```
|
60
60
|
|
61
|
-
有时开发者需要通过 req 来自定义缓存 key
|
61
|
+
有时开发者需要通过 req 来自定义缓存 key,或者特定 url 时缓存不生效,可以配置为函数的形式进行处理, 例如以下代码:
|
62
62
|
|
63
63
|
```ts title="server/cache.ts"
|
64
64
|
|
@@ -69,6 +69,10 @@ const provider: CacheOptionProvider = (req) => {
|
|
69
69
|
|
70
70
|
const key = computedKey(url, headers, ...);
|
71
71
|
|
72
|
+
if(url.includes('no-cache=1')) {
|
73
|
+
return false;
|
74
|
+
}
|
75
|
+
|
72
76
|
return {
|
73
77
|
maxAge: 500, // ms
|
74
78
|
staleWhileRevalidate: 1000, // ms
|