@modern-js/main-doc 2.54.5 → 2.55.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. package/docs/en/apis/app/hooks/src/entry.mdx +42 -0
  2. package/docs/en/apis/app/hooks/src/entry.server.mdx +52 -0
  3. package/docs/en/apis/app/hooks/src/index_.mdx +4 -0
  4. package/docs/en/apis/app/runtime/core/bootstrap.mdx +4 -0
  5. package/docs/en/apis/app/runtime/core/create-app.mdx +5 -1
  6. package/docs/en/apis/app/runtime/core/create-root.mdx +22 -0
  7. package/docs/en/apis/app/runtime/core/render.mdx +42 -0
  8. package/docs/en/apis/app/runtime/ssr/renderStreaming.mdx +69 -0
  9. package/docs/en/apis/app/runtime/ssr/renderString.mdx +62 -0
  10. package/docs/en/apis/app/runtime/ssr/requestHandler.mdx +47 -0
  11. package/docs/en/apis/app/runtime/web-server/middleware.mdx +3 -0
  12. package/docs/en/components/debug-app.mdx +3 -3
  13. package/docs/en/configure/app/output/ssg.mdx +4 -0
  14. package/docs/en/configure/app/source/enable-async-entry.mdx +4 -4
  15. package/docs/en/configure/app/source/enable-custom-entry.mdx +41 -0
  16. package/docs/en/guides/advanced-features/ssr/cache.mdx +7 -2
  17. package/docs/en/guides/concept/entries.mdx +50 -36
  18. package/docs/en/guides/get-started/quick-start.mdx +24 -8
  19. package/docs/en/guides/topic-detail/framework-plugin/hook-list.mdx +30 -177
  20. package/docs/zh/apis/app/hooks/src/entry.mdx +42 -0
  21. package/docs/zh/apis/app/hooks/src/entry.server.mdx +52 -0
  22. package/docs/zh/apis/app/hooks/src/index_.mdx +4 -0
  23. package/docs/zh/apis/app/runtime/core/bootstrap.mdx +4 -0
  24. package/docs/zh/apis/app/runtime/core/create-app.mdx +5 -1
  25. package/docs/zh/apis/app/runtime/core/create-root.mdx +22 -0
  26. package/docs/zh/apis/app/runtime/core/render.mdx +43 -0
  27. package/docs/zh/apis/app/runtime/ssr/renderStreaming.mdx +69 -0
  28. package/docs/zh/apis/app/runtime/ssr/renderString.mdx +62 -0
  29. package/docs/zh/apis/app/runtime/ssr/requestHandler.mdx +47 -0
  30. package/docs/zh/apis/app/runtime/web-server/middleware.mdx +4 -0
  31. package/docs/zh/components/debug-app.mdx +3 -2
  32. package/docs/zh/configure/app/dev/client.mdx +1 -1
  33. package/docs/zh/configure/app/output/ssg.mdx +4 -0
  34. package/docs/zh/configure/app/source/enable-async-entry.mdx +4 -4
  35. package/docs/zh/configure/app/source/enable-custom-entry.mdx +41 -0
  36. package/docs/zh/guides/advanced-features/ssr/cache.mdx +6 -2
  37. package/docs/zh/guides/concept/entries.mdx +54 -41
  38. package/docs/zh/guides/get-started/quick-start.mdx +26 -10
  39. package/docs/zh/guides/topic-detail/framework-plugin/hook-list.mdx +29 -174
  40. package/package.json +5 -5
  41. package/docs/en/apis/app/hooks/src/pages.mdx +0 -186
  42. package/docs/zh/apis/app/hooks/src/pages.mdx +0 -187
  43. package/docs/zh/apis/monorepo/commands/deploy.mdx +0 -38
@@ -56,7 +56,9 @@ export default defineConfig({
56
56
  server: {
57
57
  ssr: true,
58
58
  },
59
- plugins: [appTools()],
59
+ plugins: [appTools({
60
+ bundler: 'webpack', // Set to 'experimental-rspack' to enable rspack ⚡️🦀
61
+ }),],
60
62
  });
61
63
  ```
62
64
 
@@ -91,15 +93,27 @@ $ pnpm run build
91
93
 
92
94
  > modern build
93
95
 
94
- info Staring production build...
95
- ready Client compiled in 50 ms
96
+ Modern.js Framework v2.55.0
97
+
98
+ info Starting production build...
99
+ info Type checker is enabled. It may take some time.
100
+ ready Client compiled in 6.19 s
96
101
  info Production file sizes:
97
102
 
98
- File Size Gzipped
99
- dist/static/js/lib-react.09721b5c.js 152.6 kB 49.0 kB
100
- dist/html/main/index.html 5.8 kB 2.5 kB
101
- dist/static/js/main.3568a38e.js 3.5 kB 1.4 kB
102
- dist/static/css/main.03221f72.css 1.4 kB 741 B
103
+ File Size Gzipped
104
+ dist/routes-manifest.json 0.74 kB 0.28 kB
105
+ dist/static/css/async/page.d7915515.css 1.4 kB 0.69 kB
106
+ dist/static/js/main.5ae469e7.js 3.0 kB 1.3 kB
107
+ dist/html/main/index.html 6.0 kB 2.6 kB
108
+ dist/static/js/async/page.ddc8a4c1.js 19.2 kB 6.7 kB
109
+ dist/static/js/34.171fffdb.js 21.3 kB 7.1 kB
110
+ dist/static/js/lib-router.8995a55e.js 55.3 kB 18.1 kB
111
+ dist/static/js/lib-lodash.53ec3384.js 71.4 kB 24.8 kB
112
+ dist/static/js/lib-react.b5856db9.js 140.0 kB 45.2 kB
113
+ dist/static/js/lib-polyfill.86c452b3.js 213.3 kB 69.9 kB
114
+
115
+ Total size: 531.8 kB
116
+ Gzipped size: 176.7 kB
103
117
  ```
104
118
 
105
119
  By default, the build artifacts are generated in `dist/`, with the following directory structure:
@@ -127,6 +141,8 @@ $ pnpm run serve
127
141
 
128
142
  > modern serve
129
143
 
144
+ Modern.js Framework v2.55.0
145
+
130
146
  info Starting production server...
131
147
 
132
148
  > Local: http://localhost:8080/
@@ -420,13 +420,13 @@ export const myPlugin = (): CliPlugin<AppTools> => ({
420
420
  },
421
421
  });
422
422
  ```
423
+ {/*
424
+ ### `checkEntryPoint`
423
425
 
424
- ### `modifyEntryImports`
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<{ imports: ImportStatement[]; entrypoint: Entrypoint; }>`
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
- modifyEntryImports({ entrypoint, imports }) {
439
- // add `import React from 'React'`
440
- imports.push({
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
- ### `modifyEntryExport`
446
+ ### `modifyEntrypoints`
457
447
 
458
- - Function: used to modify the `export` statement in the generated entry file
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<{ entrypoint: Entrypoint; exportStatement: string; }>`
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
- modifyEntryRuntimePlugins({ entrypoint, plugins }) {
498
- const name = 'customPlugin';
499
- const options = {
500
- /** serializable content */
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
- ### `modifyEntryRenderFunction`
471
+ ### `generateEntryCode`
519
472
 
520
- - Function: Used for modifying the `render` function in the generated entry files.
521
- - Execution stage: Executed before generating the entry files, triggered during the [`prepare`](#prepare) 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: `AsyncWaterfall<{ entrypoint: Entrypoint; code: string; }>`
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
- modifyEntryRenderFunction({ entrypoint, code }) {
533
- const customRender = `/** render function body */`;
534
- return {
535
- entrypoint,
536
- code: customRender,
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>; }, 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: hoistNonReactStatics(AppWrapper, 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`。 下面有分两种情况进行讨论:
@@ -3,6 +3,10 @@ title: bootstrap
3
3
  ---
4
4
  # bootstrap
5
5
 
6
+ :::warning
7
+ 即将废弃,推荐使用 [`render`](/apis/app/runtime/core/render)。
8
+ :::
9
+
6
10
  用于启动和挂载应用,通常情况下不做手动调用。只有在使用[自定义 Bootstrap](/guides/concept/entries#自定义-bootstrap) 时,才需要使用该 API。
7
11
 
8
12
  ## 使用姿势
@@ -3,7 +3,11 @@ title: createApp
3
3
  ---
4
4
  # createApp
5
5
 
6
- 用于创建自定义入口,定制运行时插件。只有在使用[自定义 App](/guides/concept/entries#自定义-app) 时,才需要使用该 API。
6
+ :::warning
7
+ 即将废弃,推荐使用 [`createRoot`](/apis/app/runtime/core/create-root)。
8
+ :::
9
+
10
+ 用于创建自定义入口,定制运行时插件。
7
11
 
8
12
  ## 使用姿势
9
13
 
@@ -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
+ ```