@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.
- 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/apis/app/runtime/web-server/middleware.mdx +3 -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/apis/app/runtime/web-server/middleware.mdx +4 -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
@@ -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
|
-
|
95
|
-
|
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
|
99
|
-
dist/
|
100
|
-
dist/
|
101
|
-
dist/static/js/main.
|
102
|
-
dist/
|
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
|
-
|
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
|
+
```
|