@modern-js/main-doc 2.60.6 → 2.62.0
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/apis/app/runtime/core/use-runtime-context.mdx +86 -33
- package/docs/en/components/init-app.mdx +0 -1
- package/docs/en/components/init-rspack-app.mdx +0 -1
- package/docs/en/guides/advanced-features/source-build.mdx +11 -4
- package/docs/en/guides/basic-features/deploy.mdx +104 -2
- package/docs/en/guides/basic-features/render/ssr.mdx +23 -1
- package/docs/en/guides/concept/entries.mdx +58 -5
- package/docs/en/guides/get-started/introduction.mdx +1 -38
- package/docs/en/guides/get-started/tech-stack.mdx +1 -1
- package/docs/zh/apis/app/runtime/core/use-runtime-context.mdx +86 -33
- package/docs/zh/components/default-mwa-generate.mdx +0 -1
- package/docs/zh/components/init-app.mdx +0 -1
- package/docs/zh/components/init-rspack-app.mdx +0 -1
- package/docs/zh/guides/advanced-features/source-build.mdx +11 -4
- package/docs/zh/guides/basic-features/deploy.mdx +103 -5
- package/docs/zh/guides/basic-features/render/ssr.mdx +23 -1
- package/docs/zh/guides/concept/entries.mdx +52 -4
- package/docs/zh/guides/get-started/introduction.mdx +1 -36
- package/docs/zh/guides/get-started/tech-stack.mdx +1 -1
- package/package.json +4 -4
- package/src/i18n/enUS.ts +0 -7
- package/src/i18n/zhCN.ts +0 -7
- package/src/pages/index.tsx +3 -32
- package/docs/en/guides/topic-detail/generator/_meta.json +0 -17
- package/docs/en/guides/topic-detail/generator/create/_meta.json +0 -1
- package/docs/en/guides/topic-detail/generator/create/config.mdx +0 -59
- package/docs/en/guides/topic-detail/generator/create/option.md +0 -146
- package/docs/en/guides/topic-detail/generator/create/use.mdx +0 -48
- package/docs/en/guides/topic-detail/generator/new/_meta.json +0 -1
- package/docs/en/guides/topic-detail/generator/new/config.md +0 -115
- package/docs/en/guides/topic-detail/generator/new/option.md +0 -67
- package/docs/en/guides/topic-detail/generator/new/use.md +0 -75
- package/docs/en/guides/topic-detail/generator/plugin/_meta.json +0 -11
- package/docs/en/guides/topic-detail/generator/plugin/api/afterForged.md +0 -49
- package/docs/en/guides/topic-detail/generator/plugin/api/context.md +0 -184
- package/docs/en/guides/topic-detail/generator/plugin/api/input.md +0 -124
- package/docs/en/guides/topic-detail/generator/plugin/api/onForged.md +0 -310
- package/docs/en/guides/topic-detail/generator/plugin/category.md +0 -88
- package/docs/en/guides/topic-detail/generator/plugin/context.md +0 -104
- package/docs/en/guides/topic-detail/generator/plugin/structure.md +0 -106
- package/docs/en/guides/topic-detail/generator/plugin/use.md +0 -33
- package/docs/zh/guides/topic-detail/generator/_meta.json +0 -17
- package/docs/zh/guides/topic-detail/generator/create/_meta.json +0 -1
- package/docs/zh/guides/topic-detail/generator/create/config.mdx +0 -60
- package/docs/zh/guides/topic-detail/generator/create/option.md +0 -146
- package/docs/zh/guides/topic-detail/generator/create/use.mdx +0 -48
- package/docs/zh/guides/topic-detail/generator/new/_meta.json +0 -1
- package/docs/zh/guides/topic-detail/generator/new/config.md +0 -116
- package/docs/zh/guides/topic-detail/generator/new/option.md +0 -67
- package/docs/zh/guides/topic-detail/generator/new/use.md +0 -74
- package/docs/zh/guides/topic-detail/generator/plugin/_meta.json +0 -11
- package/docs/zh/guides/topic-detail/generator/plugin/api/afterForged.md +0 -50
- package/docs/zh/guides/topic-detail/generator/plugin/api/context.md +0 -184
- package/docs/zh/guides/topic-detail/generator/plugin/api/input.md +0 -124
- package/docs/zh/guides/topic-detail/generator/plugin/api/onForged.md +0 -310
- package/docs/zh/guides/topic-detail/generator/plugin/category.md +0 -93
- package/docs/zh/guides/topic-detail/generator/plugin/context.md +0 -105
- package/docs/zh/guides/topic-detail/generator/plugin/structure.md +0 -106
- package/docs/zh/guides/topic-detail/generator/plugin/use.md +0 -33
@@ -1,9 +1,6 @@
|
|
1
|
-
---
|
2
|
-
title: useRuntimeContext
|
3
|
-
---
|
4
1
|
# useRuntimeContext
|
5
2
|
|
6
|
-
|
3
|
+
This function is primarily used to obtain the runtime context and can only be used in the function component.
|
7
4
|
|
8
5
|
## Usage
|
9
6
|
|
@@ -12,7 +9,7 @@ import { useRuntimeContext } from '@modern-js/runtime';
|
|
12
9
|
|
13
10
|
export function App() {
|
14
11
|
const runtimeContext = useRuntimeContext();
|
15
|
-
return <div>Hello World</div
|
12
|
+
return <div>Hello World</div>
|
16
13
|
}
|
17
14
|
```
|
18
15
|
|
@@ -20,44 +17,100 @@ export function App() {
|
|
20
17
|
|
21
18
|
```ts
|
22
19
|
type RuntimeContext = {
|
23
|
-
|
24
|
-
params: Record<string, string>;
|
25
|
-
pathname: string;
|
26
|
-
query: Record<string, string>;
|
27
|
-
headers: IncomingHttpHeaders;
|
28
|
-
cookie: string;
|
29
|
-
};
|
30
|
-
store: ReduckStore;
|
31
|
-
router: RemixRouter;
|
20
|
+
context: RequestContext;
|
32
21
|
};
|
33
|
-
|
34
|
-
function useRuntimeContext(): RuntimeContext;
|
35
22
|
```
|
36
23
|
|
37
|
-
###
|
24
|
+
### context
|
38
25
|
|
39
|
-
|
40
|
-
- `params`: dynamic parameters in the request path.
|
41
|
-
- `pathname`: the pathname of the request.
|
42
|
-
- `query`: the query of the request.
|
43
|
-
- `headers`: the header info of the request.
|
44
|
-
- `cookie`: the cookie of the request.
|
45
|
-
- `store`: when the `runtime.state` is enabled, this value is the Reduck global `store`.
|
46
|
-
- `router`: When the `runtime.router` is enabled, this value exists.
|
47
|
-
- `location`: The current location reflected by the router. The same as [`useLocation`] the return value of (/apis/app/runtime/router/router.html#uselocation).
|
48
|
-
- `navigate`: Navigate to the given path. The same as the return value of [`useNavigate`](/apis/app/runtime/router/router.html#usenavigate).
|
26
|
+
Used to get [Request Context](#request-context).
|
49
27
|
|
50
28
|
## Example
|
51
29
|
|
52
|
-
|
53
|
-
import { useRuntimeContext } from '@modern-js/runtime';
|
54
|
-
import { fooModel } from '@/common/models';
|
30
|
+
### Distinguish the runtime environment
|
55
31
|
|
32
|
+
```ts
|
56
33
|
function App() {
|
57
|
-
const {
|
34
|
+
const { context } = useRuntimeContext();
|
58
35
|
|
59
|
-
|
36
|
+
if (context.isBrowser === true) {
|
37
|
+
// browser-side execution logic
|
38
|
+
console.log('browser render')
|
39
|
+
} else {
|
40
|
+
// The server-side executes logic, which can access the unique 'logger' attribute
|
41
|
+
context.logger.info('server render')
|
42
|
+
}
|
43
|
+
}
|
44
|
+
```
|
60
45
|
|
61
|
-
|
46
|
+
### Request context
|
47
|
+
|
48
|
+
When SSR is enabled, uniform request contexts can be obtained in both the node environment and the browser-side environment.
|
49
|
+
|
50
|
+
The slightly different is that the node environment also supports setting response headers, response codes, and provides Logger logs and Metrics management.
|
51
|
+
|
52
|
+
:::tip
|
53
|
+
when ssr is disabled, only the part of information that can be obtained in the browser environment is included.
|
54
|
+
|
55
|
+
:::
|
56
|
+
|
57
|
+
import { Tabs, Tab as TabItem } from "@theme";
|
58
|
+
|
59
|
+
<Tabs
|
60
|
+
defaultValue="RequestContext"
|
61
|
+
values={[
|
62
|
+
{ label: 'RequestContext', value: 'RequestContext', },
|
63
|
+
{ label: 'ServerContext', value: 'ServerContext', },
|
64
|
+
{ label: 'ClientContext', value: 'ClientContext', },
|
65
|
+
]
|
66
|
+
}>
|
67
|
+
<TabItem value="RequestContext">
|
68
|
+
|
69
|
+
```ts
|
70
|
+
type RequestContext = ServerContext | ClientContext;
|
71
|
+
```
|
72
|
+
|
73
|
+
</TabItem>
|
74
|
+
<TabItem value="ServerContext">
|
75
|
+
|
76
|
+
```ts
|
77
|
+
interface ServerContext {
|
78
|
+
isBrowser: false;
|
79
|
+
request: {
|
80
|
+
userAgent: string;
|
81
|
+
cookie: string;
|
82
|
+
cookieMap: Record<string, any>;
|
83
|
+
query: Record<string, any>;
|
84
|
+
url: string;
|
85
|
+
host: string;
|
86
|
+
headers?: IncomingHttpHeaders;
|
87
|
+
};
|
88
|
+
response: {
|
89
|
+
setHeader: (key: string, value: string) => void;
|
90
|
+
status: (code: number) => void;
|
91
|
+
}
|
92
|
+
logger: Logger;
|
93
|
+
metrics: Metrics;
|
94
|
+
}
|
95
|
+
```
|
96
|
+
|
97
|
+
</TabItem>
|
98
|
+
<TabItem value="ClientContext">
|
99
|
+
|
100
|
+
```ts
|
101
|
+
interface ClientContext {
|
102
|
+
isBrowser: true;
|
103
|
+
request: {
|
104
|
+
userAgent: string;
|
105
|
+
cookie: string;
|
106
|
+
cookieMap: Record<string, any>;
|
107
|
+
query: Record<string, any>;
|
108
|
+
url: string;
|
109
|
+
host: string;
|
110
|
+
headers?: IncomingHttpHeaders;
|
111
|
+
};
|
62
112
|
}
|
63
113
|
```
|
114
|
+
|
115
|
+
</TabItem>
|
116
|
+
</Tabs>
|
@@ -1,7 +1,6 @@
|
|
1
1
|
`@modern-js/create` provides an interactive Q & A interface to initialize the project based on the results, with initialization performed according to the default settings:
|
2
2
|
|
3
3
|
```bash
|
4
|
-
? Please select the type of project you want to create: Web App
|
5
4
|
? Please select the programming language: TS
|
6
5
|
? Please select the package manager: pnpm
|
7
6
|
```
|
@@ -124,13 +124,10 @@ Project reference provides the following capabilities:
|
|
124
124
|
|
125
125
|
### Example
|
126
126
|
|
127
|
-
In the example mentioned earlier, since the app project references the lib sub-project, we need to configure the `
|
127
|
+
In the example mentioned earlier, since the app project references the lib sub-project, we need to configure the `references` options in the app project's `tsconfig.json` to point to the relative directory of the lib:
|
128
128
|
|
129
129
|
```json title="app/tsconfig.json"
|
130
130
|
{
|
131
|
-
"compilerOptions": {
|
132
|
-
"composite": true
|
133
|
-
},
|
134
131
|
"references": [
|
135
132
|
{
|
136
133
|
"path": "../lib"
|
@@ -139,6 +136,16 @@ In the example mentioned earlier, since the app project references the lib sub-p
|
|
139
136
|
}
|
140
137
|
```
|
141
138
|
|
139
|
+
At the same time, we need to set `composite` to `true` in the lib project's `tsconfig.json`:
|
140
|
+
|
141
|
+
```json title="lib/A/tsconfig.json"
|
142
|
+
{
|
143
|
+
"compilerOptions": {
|
144
|
+
"composite": true
|
145
|
+
},
|
146
|
+
}
|
147
|
+
```
|
148
|
+
|
142
149
|
After adding these two options, the project reference is already configured. You can restart VS Code to see the effects of the configuration.
|
143
150
|
|
144
151
|
Note that the above example is a simplified one. In real monorepo projects, there may be more complex dependency relationships. You need to add a complete `references` configuration for the functionality to work correctly.
|
@@ -27,8 +27,7 @@ MODERNJS_DEPLOY=netlify npx modern deploy
|
|
27
27
|
When deploying on the deployment platforms officially supported by Modern.js, there is no need to specify environment variables.
|
28
28
|
:::
|
29
29
|
|
30
|
-
|
31
|
-
## Node.js
|
30
|
+
## Using ModernJS built-in Node.js Server
|
32
31
|
|
33
32
|
### Single Repo
|
34
33
|
|
@@ -284,3 +283,106 @@ Add the following content to the `packages/app/vercel.json` file:
|
|
284
283
|
```
|
285
284
|
|
286
285
|
Just submit your code and deploy it using the Vercel platform.
|
286
|
+
|
287
|
+
## Using Self-Built Node.js Server
|
288
|
+
|
289
|
+
Typically, we recommend using the built-in Node.js server of Modern.js to deploy applications. It supports hosting both pure frontend and full-stack projects, ensuring consistent performance in both development and production environments.
|
290
|
+
|
291
|
+
If your project is purely frontend, you can also deploy the application to the self-built Node.js server. Below is an example of using a Koa server to host the output of a pure frontend project.
|
292
|
+
|
293
|
+
For instance, if you have a Node.js server repository, you can copy the output of the project into this repository. The structure would look like this:
|
294
|
+
|
295
|
+
```bash
|
296
|
+
.
|
297
|
+
├── .output
|
298
|
+
│ ├── html
|
299
|
+
│ └── static
|
300
|
+
└── server.js
|
301
|
+
```
|
302
|
+
|
303
|
+
In `server.js`, assume you have the following code:
|
304
|
+
|
305
|
+
```ts title="server.js"
|
306
|
+
import Koa from 'koa';
|
307
|
+
|
308
|
+
const app = new Koa();
|
309
|
+
app.use(async (ctx, next) => {
|
310
|
+
ctx.body = 'Hello Modern.js';
|
311
|
+
});
|
312
|
+
app.listen(3000);
|
313
|
+
```
|
314
|
+
|
315
|
+
Now, you can add some code to include the logic for accessing static resources and HTML files in `server.js`. We need to use the `mime-types` package to get the MIME types of static resources, so let's install the dependency first:
|
316
|
+
|
317
|
+
import { PackageManagerTabs } from '@theme';
|
318
|
+
|
319
|
+
<PackageManagerTabs command="add mime-types" />
|
320
|
+
|
321
|
+
```ts title="server.js"
|
322
|
+
const Koa = require('koa');
|
323
|
+
const fs = require('fs');
|
324
|
+
const path = require('path');
|
325
|
+
const mime = require('mime-types');
|
326
|
+
|
327
|
+
const app = new Koa();
|
328
|
+
app.use(async (ctx, next) => {
|
329
|
+
if (ctx.path.startsWith('/static')) {
|
330
|
+
ctx.type = mime.lookup(ctx.path);
|
331
|
+
ctx.body = fs.createReadStream(path.resolve(__dirname, `.output${ctx.path}`));
|
332
|
+
} else if (ctx.path === '/') {
|
333
|
+
ctx.type = 'html';
|
334
|
+
ctx.body = fs.createReadStream(path.resolve(__dirname, '.output/html/main/index.html'));
|
335
|
+
}
|
336
|
+
});
|
337
|
+
app.listen(3000);
|
338
|
+
```
|
339
|
+
|
340
|
+
:::note
|
341
|
+
The above code is a basic example. Your application might have multiple entry points and require different HTML files for different paths. A custom Node.js server would also involve more complex logic.
|
342
|
+
|
343
|
+
Please note that if your project uses Modern.js conventional routing or if you have set up client-side routing with React Router, you must access HTML files through the correct `baseURL`.
|
344
|
+
|
345
|
+
In Modern.js, the default `baseURL` is `'/'`. You can configure it by modifying [`server.baseUrl`](/configure/app/server/base-url) in `modern.config.ts`.
|
346
|
+
|
347
|
+
:::danger
|
348
|
+
For projects with client-side routing, you can never access HTML files through the `/index.html` path.
|
349
|
+
:::
|
350
|
+
|
351
|
+
## Nignx
|
352
|
+
|
353
|
+
Nginx is a high-performance HTTP and reverse proxy server that can handle static files, reverse proxy, load balancing, and other functions. Deploying on Nginx typically requires configuring the `nginx.conf` file.
|
354
|
+
|
355
|
+
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.
|
356
|
+
|
357
|
+
```conf title="nginx.conf"
|
358
|
+
# user [user] [group];
|
359
|
+
worker_processes 1;
|
360
|
+
|
361
|
+
events {
|
362
|
+
worker_connections 1024;
|
363
|
+
}
|
364
|
+
|
365
|
+
http {
|
366
|
+
include mime.types;
|
367
|
+
default_type application/octet-stream;
|
368
|
+
|
369
|
+
server {
|
370
|
+
listen 8080;
|
371
|
+
server_name localhost;
|
372
|
+
|
373
|
+
location / {
|
374
|
+
# root [projectPath]/.output/html/main;
|
375
|
+
index index.html;
|
376
|
+
try_files $uri $uri/ =404;
|
377
|
+
}
|
378
|
+
|
379
|
+
location /static {
|
380
|
+
# alias [projectPath]/.output/static;
|
381
|
+
}
|
382
|
+
}
|
383
|
+
}
|
384
|
+
```
|
385
|
+
|
386
|
+
In the above configuration, you need to replace `[projectPath]` with your project path and `[user]` and `[group]` with your current user and user group.
|
387
|
+
|
388
|
+
You can copy the above configuration into the `nginx.conf` file in the Nginx installation directory and then start the Nginx service. You can also start the configuration file in a specified path using `nginx -c`, in which case you need to ensure that the path configured in the `include` directive is correct.
|
@@ -113,7 +113,29 @@ If a Client Loader is defined for the route, it will be used to re-fetch the dat
|
|
113
113
|
|
114
114
|
### Component Rendering Error
|
115
115
|
|
116
|
-
If
|
116
|
+
If the Data Loader executes correctly but the component rendering fails, SSR rendering will partially or completely fail, as shown in the following code:
|
117
|
+
|
118
|
+
```tsx
|
119
|
+
import { Await, useLoaderData } from '@modern-js/runtime/router';
|
120
|
+
import { Suspense } from 'react';
|
121
|
+
|
122
|
+
const Page = () => {
|
123
|
+
const data = useLoaderData();
|
124
|
+
const isNode = typeof window === 'undefined';
|
125
|
+
const undefinedVars = data.unDefined;
|
126
|
+
const definedVars = data.defined;
|
127
|
+
|
128
|
+
return (
|
129
|
+
<div>
|
130
|
+
{isNode ? undefinedVars.msg : definedVars.msg}
|
131
|
+
</div>
|
132
|
+
);
|
133
|
+
};
|
134
|
+
|
135
|
+
export default Page;
|
136
|
+
```
|
137
|
+
|
138
|
+
In this case, Modern.js will fallback the page to CSR and use the existing data from the Data Loader to render. If the rendering still fails, the `<ErrorBoundary>` component will be rendered.
|
117
139
|
|
118
140
|
:::tip
|
119
141
|
The behavior of component rendering errors is unaffected by `loaderFailureMode` and will not execute the Client Loader on the browser side.
|
@@ -12,7 +12,7 @@ In this chapter, you will learn about the entry convention in Modern.js and how
|
|
12
12
|
|
13
13
|
In a Modern.js project, each entry corresponds to an independent page and a server-side route. By default, Modern.js automatically determines the entry of a page based on directory conventions, but also supports customizing the entry through configuration options.
|
14
14
|
|
15
|
-
Many configuration options provided by Modern.js are divided by entry, such as page title, HTML template, page meta information, whether to enable SSR/SSG, server-side routing rules, etc.
|
15
|
+
Many configuration options provided by Modern.js are divided by entry, such as page title, HTML template, page meta information, whether to enable SSR/SSG, server-side routing rules, etc. If you want to learn more about the technical details of entries, please refer to the [In-Depth](#in-depth) section.
|
16
16
|
|
17
17
|
## Single Entry and Multiple Entries
|
18
18
|
|
@@ -169,7 +169,7 @@ const ModernRoot = createRoot();
|
|
169
169
|
render(<ModernRoot />);
|
170
170
|
```
|
171
171
|
|
172
|
-
In the code above, the component returned by the `createRoot` function is either the component generated from the `routes/` directory or the component exported by `App.tsx`.
|
172
|
+
In the code above, the component returned by the `createRoot` function is either the component generated from the `routes/` directory or the component exported by `App.tsx`.
|
173
173
|
|
174
174
|
The `render` function is used to handle rendering and mounting of the component. For example, if you want to execute some asynchronous tasks before rendering, you can achieve it like this:
|
175
175
|
|
@@ -245,10 +245,63 @@ export default defineConfig({
|
|
245
245
|
});
|
246
246
|
```
|
247
247
|
|
248
|
-
It is worth noting that, by default, Modern.js considers entries specified through the configuration as **framework mode entries** and will automatically generate the actual compilation entry.
|
248
|
+
It is worth noting that, by default, Modern.js considers entries specified through the configuration as **framework mode entries** and will automatically generate the actual compilation entry.
|
249
249
|
|
250
250
|
If your application is migrating from build tools like Webpack or Vite to the Modern.js framework, you typically need to enable the `disableMount` option in the entry configuration. In this case, Modern.js will treat the entry as a **build mode entry**.
|
251
251
|
|
252
|
+
## In-Depth
|
253
|
+
|
254
|
+
The concept of page entry is derived from the concept of [Entrypoint](https://webpack.js.org/concepts/entry-points/) in webpack. It is mainly used to configure the JavaScript or any other modules to be executed during the application startup. Webpack usually corresponds each entry to an HTML file in the output. The modules imported by the entry will be bundled and split into multiple chunks in the output. For a JavaScript module, it might be compiled into several chunks like `dist/static/js/index.ea39u8.js`.
|
255
|
+
|
256
|
+
Here's a summary of the differences between the concepts of entry and route:
|
257
|
+
|
258
|
+
- **Entry**:Contains multiple modules to be executed during application startup.
|
259
|
+
- **Client Router**:In Modern.js, it is usually implemented by `react-router`, determining which React component to load and render based on the browser's current URL using the History API.
|
260
|
+
- **Server Router**:The server can mimic the behavior of [devServer](https://webpack.js.org/configuration/dev-server/#devserverhistoryapifallback), replacing all 404 responses with the index.html page to implement client-side routing, or implement any routing logic as needed.
|
261
|
+
|
262
|
+
Their relationships are as follows:
|
263
|
+
|
264
|
+
- Each webpack website project can contain multiple entries.
|
265
|
+
- Each entry contains several modules (source files).
|
266
|
+
- Each entry usually corresponds to an HTML file in the output.
|
267
|
+
- Each HTML file can contain multiple client-side routing solutions (for example, using `react-router` and `@tanstack/react-router` in the same page).
|
268
|
+
- Each HTML file can be mapped to multiple server-side routes.
|
269
|
+
- Each HTML file can contain multiple client-side routing solutions, and when accessing different routes of a single-entry application, the same HTML file is actually used.
|
270
|
+
|
271
|
+
## Troubleshooting
|
272
|
+
|
273
|
+
1. **Does each `react-router` defined client route generate a separate HTML file?**
|
274
|
+
|
275
|
+
No. Each entry usually only generates one HTML file, and if a single entry contains multiple client routing systems, it will share the same HTML file.
|
276
|
+
|
277
|
+
2. **Does the convention routing project in the `routes/` directory generate multiple HTML files?**
|
278
|
+
|
279
|
+
No. Modern.js will scan the `routes/` directory during startup and automatically generate client-side routes based on the file conventions. The HTML file generated corresponds to the `routes/` directory.
|
280
|
+
|
281
|
+
3. **Does the Server Side Rendering (SSR) project generate multiple HTML files in the output?**
|
282
|
+
|
283
|
+
A Server Side Rendering (SSR) project does not necessarily need to generate an HTML file in the output. It can only include the server-side JavaScript output. At this point, the `react-router` routing will be executed on the server side, and the HTML content will be rendered and responded while a request is triggered.
|
284
|
+
|
285
|
+
At the same time, Modern.js will also generate a complete client-side HTML file for each entry in the output, which can be used to fallback to client-side rendering when the SSR fails.
|
286
|
+
|
287
|
+
Another special case is a Single Entry Static Site Generation (SSG) project, even if it is built with a convention routing, Modern.js will also generate an HTML file for each `page.tsx` file.
|
288
|
+
|
289
|
+
Note that even if SSR is used, React still needs to go through the hydration phase, so the routing defined by `react-router` will still be executed on the client side.
|
290
|
+
|
291
|
+
4. **What are the exceptions to generating multiple HTML files?**
|
292
|
+
|
293
|
+
You can configure [html-rspack-plugin](https://rspack.dev/plugins/rspack/html-rspack-plugin#generate-multiple-html-files) to generate multiple HTML files for each entry, or let multiple entries share the same HTML file.
|
294
|
+
|
295
|
+
5. **What is a Multi-Page Application (MPA)?**
|
296
|
+
|
297
|
+
The "page" in a Multi-Page Application (MPA) refers to a static HTML file.
|
298
|
+
|
299
|
+
Generally, any application that outputs multiple entries and multiple HTML files can be called a Multi-Page Application.
|
300
|
+
|
301
|
+
Narrowly speaking, a Multi-Page Application does not contain client-side routing, and navigation between pages is usually achieved through elements like `<a>` tags. But in practice, Multi-Page Applications also often need to configure client-side routing to meet different needs.
|
302
|
+
|
303
|
+
Conversely, a application with `react-router` defined routes that generates only one HTML file is called a Single-Page Application (SPA).
|
304
|
+
|
252
305
|
## Deprecated
|
253
306
|
|
254
307
|
Currently, if the entry directory meets the following conditions, it will also be considered an application entry:
|
@@ -262,7 +315,7 @@ The `index.[jt]sx?` file supported **Custom Bootstrap** and **Build Mode Entry**
|
|
262
315
|
|
263
316
|
### Custom Bootstrap
|
264
317
|
|
265
|
-
When there is an `index.[jt]sx` file in the entry, and the file's default export is a function, Modern.js will pass the default `bootstrap` function as an argument and use the exported function to replace the default `bootstrap`.
|
318
|
+
When there is an `index.[jt]sx` file in the entry, and the file's default export is a function, Modern.js will pass the default `bootstrap` function as an argument and use the exported function to replace the default `bootstrap`.
|
266
319
|
|
267
320
|
This allows developers to customize mounting components to DOM or add custom behaviors before mounting. For example:
|
268
321
|
|
@@ -277,4 +330,4 @@ export default (App: React.ComponentType, bootstrap: () => void) => {
|
|
277
330
|
|
278
331
|
### Build Mode Entry
|
279
332
|
|
280
|
-
When an `index.[jt]sx` file exists in the entry directory and does not export a function via export default, this entry will also be considered a build mode entry.
|
333
|
+
When an `index.[jt]sx` file exists in the entry directory and does not export a function via export default, this entry will also be considered a build mode entry.
|
@@ -5,44 +5,7 @@ sidebar_position: 1
|
|
5
5
|
|
6
6
|
# Introduction to Modern.js
|
7
7
|
|
8
|
-
**Modern.js is
|
9
|
-
|
10
|
-
Currently, Modern.js includes two solutions, targeting web application development and npm package development:
|
11
|
-
|
12
|
-
import { SolutionCards } from '@site/src/components/SolutionCards';
|
13
|
-
|
14
|
-
<SolutionCards
|
15
|
-
cards={[
|
16
|
-
{
|
17
|
-
title: 'Modern.js Framework',
|
18
|
-
description: 'For web application development',
|
19
|
-
link: 'http://modernjs.dev/en/',
|
20
|
-
},
|
21
|
-
{
|
22
|
-
title: 'Modern.js Module',
|
23
|
-
description: 'For npm package development',
|
24
|
-
link: 'http://modernjs.dev/module-tools/en/',
|
25
|
-
},
|
26
|
-
]}
|
27
|
-
/>
|
28
|
-
|
29
|
-
As part of the Modern.js engineering system, each of the above solutions can be used separately and has its own independent documentation site. Developers can choose one or more solutions as needed.
|
30
|
-
|
31
|
-
## About Documentation
|
32
|
-
|
33
|
-
**The current documentation site corresponds to the Modern.js framework**, which is used to developing web applications.
|
34
|
-
|
35
|
-
- If you need to develop an npm package, please refer to the [Modern.js Module documentation](https://modernjs.dev/module-tools).
|
36
|
-
- If you need a build tool to bundle web applications, [Rsbuild](https://rsbuild.dev/) is recommended.
|
37
|
-
- If you need to develop a documentation site, [Rspress](https://rspress.dev/) is recommended.
|
38
|
-
|
39
|
-
:::tip
|
40
|
-
Since the Modern.js framework is the most widely used, in this documentation site, we will omit "framework" and directly refer to it as Modern.js.
|
41
|
-
:::
|
42
|
-
|
43
|
-
## Modern.js Framework
|
44
|
-
|
45
|
-
**The Modern.js framework is a progressive web framework based on React**. At ByteDance, we use Modern.js to build upper-level frameworks that have supported the development of thousands of web applications.
|
8
|
+
**Modern.js is a progressive web framework based on React**. At ByteDance, we use Modern.js to build upper-level frameworks that have supported the development of thousands of web applications.
|
46
9
|
|
47
10
|
Modern.js can provide developers with an ultimate **Development Experience** and enable applications to have better **User Experience**.
|
48
11
|
|
@@ -12,7 +12,7 @@ In this document, you can learn about the main technology stack involved in the
|
|
12
12
|
|
13
13
|
Modern.js uses [React 18](https://react.dev/) to build user interfaces and is also compatible with React 17.
|
14
14
|
|
15
|
-
Rsbuild supports building Vue applications. If you need to use Vue, you can refer to ["Rsbuild - Vue"](https://rsbuild.dev/guide/framework/
|
15
|
+
Rsbuild supports building Vue applications. If you need to use Vue, you can refer to ["Rsbuild - Vue"](https://rsbuild.dev/guide/framework/vue).
|
16
16
|
|
17
17
|
## Routing
|
18
18
|
|
@@ -1,6 +1,3 @@
|
|
1
|
-
---
|
2
|
-
title: useRuntimeContext
|
3
|
-
---
|
4
1
|
# useRuntimeContext
|
5
2
|
|
6
3
|
该函数主要用于获取 Runtime 上下文,只能在函数组件中使用。
|
@@ -12,7 +9,7 @@ import { useRuntimeContext } from '@modern-js/runtime';
|
|
12
9
|
|
13
10
|
export function App() {
|
14
11
|
const runtimeContext = useRuntimeContext();
|
15
|
-
return <div>Hello World</div
|
12
|
+
return <div>Hello World</div>
|
16
13
|
}
|
17
14
|
```
|
18
15
|
|
@@ -20,44 +17,100 @@ export function App() {
|
|
20
17
|
|
21
18
|
```ts
|
22
19
|
type RuntimeContext = {
|
23
|
-
|
24
|
-
params: Record<string, string>;
|
25
|
-
pathname: string;
|
26
|
-
query: Record<string, string>;
|
27
|
-
headers: IncomingHttpHeaders;
|
28
|
-
cookie: string;
|
29
|
-
};
|
30
|
-
store: ReduckStore;
|
31
|
-
router: RemixRouter;
|
20
|
+
context: RequestContext;
|
32
21
|
};
|
33
|
-
|
34
|
-
function useRuntimeContext(): RuntimeContext;
|
35
22
|
```
|
36
23
|
|
37
|
-
###
|
24
|
+
### context
|
38
25
|
|
39
|
-
|
40
|
-
- `params`:请求路径中的动态参数。
|
41
|
-
- `pathname`:请求的 pathname。
|
42
|
-
- `query`:请求的查询字符串对象。
|
43
|
-
- `headers`:请求头信息。
|
44
|
-
- `cookie`:请求的 cookie 信息。
|
45
|
-
- `store`:在开启了 state 插件的时候,该值为 Reduck 全局 `store`。
|
46
|
-
- `router`:在开启 router 插件的时候存在。
|
47
|
-
- `location`:当前路由对应的位置信息。同 [`useLocation`](/apis/app/runtime/router/router.html#uselocation) 返回值。
|
48
|
-
- `navigate`:导航到给定路径。同 [`useNavigate`](/apis/app/runtime/router/router.html#usenavigate) 返回值。
|
26
|
+
用于获取[请求上下文](#请求上下文)。
|
49
27
|
|
50
|
-
##
|
28
|
+
## 使用示例
|
51
29
|
|
52
|
-
|
53
|
-
import { useRuntimeContext } from '@modern-js/runtime';
|
54
|
-
import { fooModel } from '@/common/models';
|
30
|
+
### 区分运行环境
|
55
31
|
|
32
|
+
```ts
|
56
33
|
function App() {
|
57
|
-
const {
|
34
|
+
const { context } = useRuntimeContext();
|
35
|
+
|
36
|
+
if (context.isBrowser === true) {
|
37
|
+
// 浏览器端执行逻辑
|
38
|
+
console.log('browser render')
|
39
|
+
} else {
|
40
|
+
// 服务器端执行逻辑 logger 功能需开启
|
41
|
+
context.logger.info('server render')
|
42
|
+
}
|
43
|
+
}
|
44
|
+
```
|
45
|
+
|
46
|
+
### 请求上下文
|
47
|
+
|
48
|
+
开启 SSR 时,在 Node 环境和浏览器端环境可以获取到同构的请求上下文。
|
49
|
+
|
50
|
+
稍有不同的是 Node 环境还支持设置响应头、响应码,并提供了 Logger 日志与 Metrics 打点。
|
51
|
+
|
52
|
+
:::tip
|
53
|
+
当 SSR 未开启时,仅包含可在浏览器端获取的部分信息。
|
54
|
+
|
55
|
+
:::
|
56
|
+
|
57
|
+
import { Tabs, Tab as TabItem } from "@theme";
|
58
|
+
|
59
|
+
<Tabs
|
60
|
+
defaultValue="RequestContext"
|
61
|
+
values={[
|
62
|
+
{ label: 'RequestContext', value: 'RequestContext', },
|
63
|
+
{ label: 'ServerContext', value: 'ServerContext', },
|
64
|
+
{ label: 'ClientContext', value: 'ClientContext', },
|
65
|
+
]
|
66
|
+
}>
|
67
|
+
<TabItem value="RequestContext">
|
58
68
|
|
59
|
-
|
69
|
+
```ts
|
70
|
+
type RequestContext = ServerContext | ClientContext;
|
71
|
+
```
|
72
|
+
|
73
|
+
</TabItem>
|
74
|
+
<TabItem value="ServerContext">
|
60
75
|
|
61
|
-
|
76
|
+
```ts
|
77
|
+
interface ServerContext {
|
78
|
+
isBrowser: false;
|
79
|
+
request: {
|
80
|
+
userAgent: string;
|
81
|
+
cookie: string;
|
82
|
+
cookieMap: Record<string, any>;
|
83
|
+
query: Record<string, any>;
|
84
|
+
url: string;
|
85
|
+
host: string;
|
86
|
+
headers?: IncomingHttpHeaders;
|
87
|
+
};
|
88
|
+
response: {
|
89
|
+
setHeader: (key: string, value: string) => void;
|
90
|
+
status: (code: number) => void;
|
91
|
+
};
|
92
|
+
logger: Logger;
|
93
|
+
metrics: Metrics;
|
62
94
|
}
|
63
95
|
```
|
96
|
+
|
97
|
+
</TabItem>
|
98
|
+
<TabItem value="ClientContext">
|
99
|
+
|
100
|
+
```ts
|
101
|
+
interface ClientContext {
|
102
|
+
isBrowser: true;
|
103
|
+
request: {
|
104
|
+
userAgent: string;
|
105
|
+
cookie: string;
|
106
|
+
cookieMap: Record<string, any>;
|
107
|
+
query: Record<string, any>;
|
108
|
+
url: string;
|
109
|
+
host: string;
|
110
|
+
headers?: IncomingHttpHeaders;
|
111
|
+
};
|
112
|
+
}
|
113
|
+
```
|
114
|
+
|
115
|
+
</TabItem>
|
116
|
+
</Tabs>
|