@modern-js/main-doc 2.54.6 → 2.55.0
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/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/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/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/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/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 +5 -5
- 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
@@ -420,13 +420,13 @@ export const myPlugin = (): CliPlugin<AppTools> => ({
|
|
420
420
|
},
|
421
421
|
});
|
422
422
|
```
|
423
|
+
{/*
|
424
|
+
### `checkEntryPoint`
|
423
425
|
|
424
|
-
|
425
|
-
|
426
|
-
- Function: Used for modifying or adding `import` statements in the generated entry files.
|
426
|
+
- Function: Used for increasing entry types.
|
427
427
|
- Execution stage: Executed before generating the entry files, triggered during the [`prepare`](#prepare) stage.
|
428
428
|
- Hook model: `AsyncWaterfall`
|
429
|
-
- Type: `AsyncWaterfall<{
|
429
|
+
- Type: `AsyncWaterfall<{ path: string; entry: false | string; }>`
|
430
430
|
- Example:
|
431
431
|
|
432
432
|
```ts
|
@@ -435,57 +435,20 @@ import type { CliPlugin, AppTools } from '@modern-js/app-tools';
|
|
435
435
|
export const myPlugin = (): CliPlugin<AppTools> => ({
|
436
436
|
setup(api) {
|
437
437
|
return {
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
value: 'react',
|
442
|
-
specifiers: [
|
443
|
-
{
|
444
|
-
imported: 'unmountComponentAtNode',
|
445
|
-
},
|
446
|
-
],
|
447
|
-
});
|
448
|
-
|
449
|
-
return { entrypoint, imports };
|
450
|
-
},
|
438
|
+
checkEntryPoint({ path, entry }) {
|
439
|
+
return { path, entry: entry || isNewEntry(path) };
|
440
|
+
}
|
451
441
|
};
|
452
442
|
},
|
453
443
|
});
|
454
444
|
```
|
455
445
|
|
456
|
-
### `
|
446
|
+
### `modifyEntrypoints`
|
457
447
|
|
458
|
-
- Function:
|
448
|
+
- Function: Used for modifying the entry information, for the newly added entries of the plugin, the corresponding entrypoint information can be modified through this hook.
|
459
449
|
- Execution stage: Before the entry file is generated, the [`prepare`](#prepare) phase triggers
|
460
450
|
- Hook model: `AsyncWaterfall`
|
461
|
-
- Type: `AsyncWaterfall<{
|
462
|
-
- Example:
|
463
|
-
|
464
|
-
```ts
|
465
|
-
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
|
466
|
-
|
467
|
-
export const myPlugin = (): CliPlugin<AppTools> => ({
|
468
|
-
setup(api) {
|
469
|
-
return {
|
470
|
-
modifyEntryExport({ entrypoint, exportStatement }) {
|
471
|
-
return {
|
472
|
-
entrypoint,
|
473
|
-
exportStatement: [`export const foo = 'test'`, exportStatement].join(
|
474
|
-
'\n',
|
475
|
-
),
|
476
|
-
};
|
477
|
-
},
|
478
|
-
};
|
479
|
-
},
|
480
|
-
});
|
481
|
-
```
|
482
|
-
|
483
|
-
### `modifyEntryRuntimePlugins`
|
484
|
-
|
485
|
-
- Function: Used for adding or modifying [Runtime plugins](#Runtime) in the generated entry files.
|
486
|
-
- Execution stage: Executed before generating the entry files, triggered during the [`prepare`](#prepare) stage.
|
487
|
-
- Hook model: `AsyncWaterfall`
|
488
|
-
- Type: `AsyncWaterfall<{ entrypoint: Entrypoint; plugins: RuntimePlugin[]; }>`
|
451
|
+
- Type: `AsyncWaterfall<{ entrypoints: Entrypoint[]; }>`
|
489
452
|
- Example:
|
490
453
|
|
491
454
|
```ts
|
@@ -494,33 +457,23 @@ import type { CliPlugin, AppTools } from '@modern-js/app-tools';
|
|
494
457
|
export const myPlugin = (): CliPlugin<AppTools> => ({
|
495
458
|
setup(api) {
|
496
459
|
return {
|
497
|
-
|
498
|
-
const
|
499
|
-
|
500
|
-
|
501
|
-
};
|
502
|
-
|
503
|
-
return {
|
504
|
-
plugins: [
|
505
|
-
...plugins,
|
506
|
-
{
|
507
|
-
name,
|
508
|
-
options: JSON.stringify(options),
|
509
|
-
},
|
510
|
-
],
|
511
|
-
};
|
460
|
+
async modifyEntrypoints({ entrypoints }) {
|
461
|
+
const newEntryPoints = entrypoints.map(entrypoint => {
|
462
|
+
...
|
463
|
+
});
|
464
|
+
return { entrypoints: newEntryPoints };
|
512
465
|
},
|
513
466
|
};
|
514
467
|
},
|
515
468
|
});
|
516
469
|
```
|
517
470
|
|
518
|
-
### `
|
471
|
+
### `generateEntryCode`
|
519
472
|
|
520
|
-
- Function: Used for modifying the
|
521
|
-
- Execution stage:
|
473
|
+
- Function: Used for modifying the generated entry file
|
474
|
+
- Execution stage: After generating the entry file and before creating the builder.
|
522
475
|
- Hook model: `AsyncWaterfall`
|
523
|
-
- Type: `
|
476
|
+
- Type: `AsyncWorkflow<{ entrypoints: Entrypoint[] }, void>`
|
524
477
|
- Example:
|
525
478
|
|
526
479
|
```ts
|
@@ -529,18 +482,18 @@ import type { CliPlugin, AppTools } from '@modern-js/app-tools';
|
|
529
482
|
export const myPlugin = (): CliPlugin<AppTools> => ({
|
530
483
|
setup(api) {
|
531
484
|
return {
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
485
|
+
async generateEntryCode({ entrypoints }) {
|
486
|
+
await Promise.all(
|
487
|
+
entrypoints.map(async entrypoint => {
|
488
|
+
...
|
489
|
+
})
|
490
|
+
);
|
538
491
|
},
|
539
492
|
};
|
540
493
|
},
|
541
494
|
});
|
542
495
|
```
|
543
|
-
|
496
|
+
*/}
|
544
497
|
### `modifyFileSystemRoutes`
|
545
498
|
|
546
499
|
- Function: Used for modifying the content of the generated front-end page routing files, which must be serializable.
|
@@ -608,32 +561,6 @@ export const myPlugin = (): CliPlugin<AppTools> => ({
|
|
608
561
|
});
|
609
562
|
```
|
610
563
|
|
611
|
-
### `modifyAsyncEntry`
|
612
|
-
|
613
|
-
- Function: Used for modifying the asynchronous module that wraps the entry file, see [source.enableAsyncEntry](/configure/app/source/enable-async-entry).
|
614
|
-
- Execution stage: Executed before generating the entry files, triggered during the [`prepare`](#prepare) stage.
|
615
|
-
- Hook model: `AsyncWaterfall`
|
616
|
-
- Type: `AsyncWaterfall<{ entrypoint: Entrypoint; code: string; }>`
|
617
|
-
- Example:
|
618
|
-
|
619
|
-
```ts
|
620
|
-
import type { CliPlugin, AppTools } from '@modern-js/app-tools';
|
621
|
-
|
622
|
-
export const myPlugin = (): CliPlugin<AppTools> => ({
|
623
|
-
setup(api) {
|
624
|
-
return {
|
625
|
-
modifyAsyncEntry({ entrypoint, code }) {
|
626
|
-
const customCode = `console.log('hello');`;
|
627
|
-
return {
|
628
|
-
entrypoint,
|
629
|
-
code: `${customCode}${code}`,
|
630
|
-
};
|
631
|
-
},
|
632
|
-
};
|
633
|
-
},
|
634
|
-
});
|
635
|
-
```
|
636
|
-
|
637
564
|
### `htmlPartials`
|
638
565
|
|
639
566
|
- Function: Used for customizing the generated HTML page template.
|
@@ -780,7 +707,7 @@ export const myPlugin = (): Plugin => ({
|
|
780
707
|
- Function: Modifies the components that need to be rendered.
|
781
708
|
- Execution stage: Rendering (SSR/CSR).
|
782
709
|
- Hook model: `Pipeline`
|
783
|
-
- Type: `Pipeline<{ App: React.ComponentType<any>; },
|
710
|
+
- Type: `Pipeline<{ App: React.ComponentType<any>;config: Record<string, any>; },React.ComponentType<any>>`
|
784
711
|
- Example:
|
785
712
|
|
786
713
|
:::note
|
@@ -790,13 +717,12 @@ When using the hoc hook, you need to copy the static properties of the original
|
|
790
717
|
```ts
|
791
718
|
import { createContext } from 'react';
|
792
719
|
import type { Plugin } from '@modern-js/runtime';
|
793
|
-
import hoistNonReactStatics from 'hoist-non-react-statics';
|
794
720
|
|
795
721
|
export const myPlugin = (): Plugin => ({
|
796
722
|
setup(api) {
|
797
723
|
const FooContext = createContext('');
|
798
724
|
return {
|
799
|
-
hoc({ App }, next) {
|
725
|
+
hoc({ App, config }, next) {
|
800
726
|
const AppWrapper = (props: any) => {
|
801
727
|
return (
|
802
728
|
<FooContext.Provider store={'test'}>
|
@@ -805,84 +731,11 @@ export const myPlugin = (): Plugin => ({
|
|
805
731
|
);
|
806
732
|
};
|
807
733
|
return next({
|
808
|
-
App:
|
734
|
+
App: AppWrapper,
|
735
|
+
config
|
809
736
|
});
|
810
737
|
},
|
811
738
|
};
|
812
739
|
},
|
813
740
|
});
|
814
741
|
```
|
815
|
-
|
816
|
-
{/* ### `provide`
|
817
|
-
|
818
|
-
- Function: Modifies the Elements that need to be rendered.
|
819
|
-
- Execution stage: Rendering (SSR/CSR).
|
820
|
-
- Hook model: `Pipeline`
|
821
|
-
- Type: `Pipeline<{ element: JSX.Element; props: AppProps; context: RuntimeContext }, JSX.Element>`
|
822
|
-
- Example:
|
823
|
-
|
824
|
-
```ts
|
825
|
-
import { createContext } from 'react';
|
826
|
-
import type { Plugin } from '@modern-js/runtime';
|
827
|
-
|
828
|
-
export const myPlugin = (): Plugin => ({
|
829
|
-
setup(api) {
|
830
|
-
const FooContext = createContext('');
|
831
|
-
|
832
|
-
return {
|
833
|
-
provide: ({ element }) => <div>{element}</div>,
|
834
|
-
};
|
835
|
-
},
|
836
|
-
});
|
837
|
-
```
|
838
|
-
|
839
|
-
### `client`
|
840
|
-
|
841
|
-
- Function: Customizes the client-side rendering process.
|
842
|
-
- Execution stage: Client-side rendering in the browser.
|
843
|
-
- Hook model: `AsyncPipeline`
|
844
|
-
- Type: `AsyncPipeline<{ App: React.ComponentType<any>; context?: RuntimeContext; rootElement: HTMLElement; }, void>`
|
845
|
-
- Example:
|
846
|
-
|
847
|
-
```ts
|
848
|
-
import ReactDOM from 'react-dom';
|
849
|
-
import type { Plugin } from '@modern-js/runtime';
|
850
|
-
|
851
|
-
export const myPlugin = (): Plugin => ({
|
852
|
-
setup(api) {
|
853
|
-
return {
|
854
|
-
client: async ({ App, rootElement }) => {
|
855
|
-
ReactDOM.render(
|
856
|
-
React.createElement(App, { context: { foo: 'test' } }),
|
857
|
-
rootElement,
|
858
|
-
);
|
859
|
-
},
|
860
|
-
};
|
861
|
-
},
|
862
|
-
});
|
863
|
-
```
|
864
|
-
|
865
|
-
### `server`
|
866
|
-
|
867
|
-
- Function: Customize the server-side rendering process.
|
868
|
-
- Execution Phase: SSR
|
869
|
-
- Hook model: `AsyncPipeline`
|
870
|
-
- Type: `AsyncPipeline<{ App: React.ComponentType<any>; context?: RuntimeContext; }, string>`
|
871
|
-
- Example:
|
872
|
-
|
873
|
-
```ts
|
874
|
-
import ReactDomServer from 'react-dom/server';
|
875
|
-
import type { Plugin } from '@modern-js/runtime';
|
876
|
-
|
877
|
-
export const myPlugin = (): Plugin => ({
|
878
|
-
setup(api) {
|
879
|
-
return {
|
880
|
-
server({ App, context }) {
|
881
|
-
return ReactDomServer.renderToString(
|
882
|
-
React.createElement(App, { context: { foo: 'test' } }),
|
883
|
-
);
|
884
|
-
},
|
885
|
-
};
|
886
|
-
},
|
887
|
-
});
|
888
|
-
``` */}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
---
|
2
|
+
title: entry.[tj]s
|
3
|
+
sidebar_position: 4
|
4
|
+
---
|
5
|
+
# entry.[tj]s
|
6
|
+
|
7
|
+
通常情况下[`routes/`](/apis/app/hooks/src/routes.html) 和 [`App.[tj]sx`](/apis/app/hooks/src/app) 钩子文件已经能满足我们的需求,当我们需要在组件渲染之前添加自定义行为或者完全接管 webpack 打包入口时,可以在 `src` 或者入口目录下放置 `entry.[tj]s`。 下面有分两种情况进行讨论:
|
8
|
+
|
9
|
+
:::info
|
10
|
+
使用该文件需要开启 [source.enableCustomEntry](/configure/app/source/enable-custom-entry)。
|
11
|
+
:::
|
12
|
+
|
13
|
+
## 在组件渲染前添加自定义行为
|
14
|
+
|
15
|
+
在 `src/entry.[tj]s` 中这样实现:
|
16
|
+
|
17
|
+
```js title=src/entry.tsx
|
18
|
+
import { createRoot } from '@modern-js/runtime/react';
|
19
|
+
import { render } from '@modern-js/runtime/browser';
|
20
|
+
|
21
|
+
const ModernRoot = createRoot();
|
22
|
+
|
23
|
+
async function beforeRender() {
|
24
|
+
// todo
|
25
|
+
}
|
26
|
+
|
27
|
+
beforeRender().then(() => {
|
28
|
+
render(<ModernRoot />);
|
29
|
+
});
|
30
|
+
```
|
31
|
+
|
32
|
+
## 完全接管 webpack 入口
|
33
|
+
|
34
|
+
当项目未安装 `@modern-js/runtime` 依赖时, `src/entry.[tj]sx?` 即为真正的 webpack 打包入口文件, 可以直接像使用 create-react-app 等脚手架一样组织代码:
|
35
|
+
|
36
|
+
```js title=src/entry.jsx
|
37
|
+
import React from 'react';
|
38
|
+
import ReactDOM from 'react-dom/client';
|
39
|
+
import App from './App';
|
40
|
+
|
41
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
|
42
|
+
```
|
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
title: entry.server.[tj]sx
|
3
|
+
sidebar_position: 5
|
4
|
+
---
|
5
|
+
|
6
|
+
# entry.server.[tj]sx
|
7
|
+
|
8
|
+
当项目开启 `server.ssr` 时,Modern.js 生成一个默认的 Server-Side 入口。示例代码如下:
|
9
|
+
|
10
|
+
```tsx title="entry.server.tsx"
|
11
|
+
import {
|
12
|
+
renderString,
|
13
|
+
createRequestHandler,
|
14
|
+
} from '@modern-js/runtime/ssr/server';
|
15
|
+
|
16
|
+
const handleRequest = async (request, ServerRoot, options) => {
|
17
|
+
const body = await renderString(request, <ServerRoot />, options);
|
18
|
+
|
19
|
+
return new Response(body, {
|
20
|
+
headers: {
|
21
|
+
'content-type': 'text/html; charset=utf-8',
|
22
|
+
},
|
23
|
+
});
|
24
|
+
};
|
25
|
+
|
26
|
+
export default createRequestHandler(handleRequest);
|
27
|
+
```
|
28
|
+
|
29
|
+
## 添加自定义行为
|
30
|
+
|
31
|
+
如果用户需自定义 Server-Side Rendering 入口,可以在 `src/entry.server.ts`、`src/{entryName}/entry.server.ts` 中自定义 server 入口
|
32
|
+
|
33
|
+
```tsx title="src/entry.server.tsx"
|
34
|
+
import { renderString, createRequestHandler } from '@edenx/runtime/ssr/server';
|
35
|
+
import type { HandleRequest } from '@edenx/runtime/ssr/server';
|
36
|
+
|
37
|
+
const handleRequest: HandleRequest = async (request, ServerRoot, options) => {
|
38
|
+
// do something before rendering
|
39
|
+
const body = await renderString(request, <ServerRoot />, options);
|
40
|
+
|
41
|
+
const newBody = body + '<div>Byte-Dance</div>';
|
42
|
+
|
43
|
+
return new Response(newBody, {
|
44
|
+
headers: {
|
45
|
+
'content-type': 'text/html; charset=UTF-8',
|
46
|
+
'x-custom-header': 'abc',
|
47
|
+
},
|
48
|
+
});
|
49
|
+
};
|
50
|
+
|
51
|
+
export default createRequestHandler(handleRequest);
|
52
|
+
```
|
@@ -4,6 +4,10 @@ sidebar_position: 4
|
|
4
4
|
---
|
5
5
|
# index.[tj]s
|
6
6
|
|
7
|
+
:::warning
|
8
|
+
即将废弃,推荐使用 [`entry.[tj]s`](/apis/app/hooks/src/entry)。
|
9
|
+
:::
|
10
|
+
|
7
11
|
应用使用自定义 `bootstrap` 时的入口标识。
|
8
12
|
|
9
13
|
通常情况下 [`App.[tj]sx`](/apis/app/hooks/src/app) 钩子文件已经能满足我们的需求,当我们需要在 `bootstrap` 之前添加自定义行为或者完全接管 webpack 打包入口时,可以在 `src` 或者入口目录下放置 `index.[tj]s`。 下面有分两种情况进行讨论:
|
@@ -0,0 +1,22 @@
|
|
1
|
+
---
|
2
|
+
title: createRoot
|
3
|
+
---
|
4
|
+
# createRoot
|
5
|
+
|
6
|
+
用于创建 Modern.js 提供的根组件,该根组件会自动注册 Runtime 插件,并完成 Runtime 插件初始化。
|
7
|
+
|
8
|
+
## 使用姿势
|
9
|
+
|
10
|
+
```ts
|
11
|
+
import { createRoot } from '@modern-js/runtime/react';
|
12
|
+
```
|
13
|
+
|
14
|
+
## 函数签名
|
15
|
+
|
16
|
+
```ts
|
17
|
+
export function createRoot(UserApp?: React.ComponentType | null): React.ComponentType<any>;
|
18
|
+
```
|
19
|
+
|
20
|
+
### 参数
|
21
|
+
|
22
|
+
- `UserApp` 可选参数,默认为 `App.tsx` 导出的组件
|
@@ -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
|
+
```
|