@modern-js/main-doc 2.49.4 → 2.51.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/runtime/web-server/middleware.mdx +7 -1
- package/docs/en/apis/app/runtime/web-server/unstable_middleware.mdx +134 -0
- package/docs/en/guides/advanced-features/web-server.mdx +41 -5
- package/docs/en/guides/basic-features/deploy.mdx +176 -0
- package/docs/zh/apis/app/runtime/web-server/middleware.mdx +7 -0
- package/docs/zh/apis/app/runtime/web-server/unstable_middleware.mdx +133 -0
- package/docs/zh/guides/advanced-features/web-server.mdx +35 -2
- package/docs/zh/guides/basic-features/deploy.mdx +177 -0
- package/package.json +5 -5
@@ -1,10 +1,17 @@
|
|
1
1
|
---
|
2
2
|
title: Middleware
|
3
3
|
---
|
4
|
+
|
4
5
|
# Middleware
|
5
6
|
|
6
7
|
Used to extend the built-in Web Server of Modern.js, unlike [Hook](/apis/app/runtime/web-server/hook), Middleware can directly operate Node's origin request and response, and can be extended using the framework plugin.
|
7
8
|
|
9
|
+
:::note
|
10
|
+
In the next major release, Modern.js will use new middleware to replace this approach.
|
11
|
+
|
12
|
+
It is recommended to use [UnstableMiddleware](/apis/app/runtime/web-server/unstable_middleware) to handle page requests.
|
13
|
+
:::
|
14
|
+
|
8
15
|
:::note
|
9
16
|
For more detail, see [Extend Web Server](/guides/advanced-features/web-server).
|
10
17
|
|
@@ -125,7 +132,6 @@ export const middleware: SomeType = (ctx, next) => {
|
|
125
132
|
|
126
133
|
By default, the framework extension capability of Web Server is turned off after installing the framework extension plugin. If you want to use the framework extension, you can turn it on through ['server.enableFrameworkExt'](/configure/app/server/enable-framework-ext.html).
|
127
134
|
|
128
|
-
|
129
135
|
:::info
|
130
136
|
The type name exported by the framework extension may not 'Middleware', but is named by the framework extension plugin.
|
131
137
|
:::
|
@@ -0,0 +1,134 @@
|
|
1
|
+
---
|
2
|
+
title: Unstable Middleware
|
3
|
+
---
|
4
|
+
|
5
|
+
# Unstable Middleware
|
6
|
+
|
7
|
+
Used to extend the built-in Web Server in Modern.js.
|
8
|
+
UnstableMiddleware will replace [Middleware](/apis/app/runtime/web-server/middleware) in the future.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
```ts title="server/index.ts"
|
13
|
+
import { UnstableMiddleware } from '@modern-js/runtime/server';
|
14
|
+
|
15
|
+
export const unstableMiddlewares: UnstableMiddleware[] = [];
|
16
|
+
```
|
17
|
+
|
18
|
+
## Types
|
19
|
+
|
20
|
+
**UnstableMiddleware**
|
21
|
+
|
22
|
+
```ts
|
23
|
+
type UnstableMiddleware<
|
24
|
+
V extends Record<string, unknown> = Record<string, unknown>,
|
25
|
+
> = (
|
26
|
+
c: UnstableMiddlewareContext<V>,
|
27
|
+
next: UnstableNext,
|
28
|
+
) => Promise<void | Response>;
|
29
|
+
```
|
30
|
+
|
31
|
+
**UnstableMiddlewareContext**
|
32
|
+
|
33
|
+
```ts
|
34
|
+
type Body = ReadableStream | ArrayBuffer | string | null;
|
35
|
+
|
36
|
+
type UnstableMiddlewareContext<
|
37
|
+
V extends Record<string, unknown> = Record<string, unknown>,
|
38
|
+
> = {
|
39
|
+
request: Request;
|
40
|
+
response: Response;
|
41
|
+
get: Get<V>;
|
42
|
+
set: Set<V>;
|
43
|
+
header: (name: string, value: string, options?: { append?: boolean }) => void;
|
44
|
+
status: (code: number) => void;
|
45
|
+
redirect: (location: string, status?: number) => Response;
|
46
|
+
body: (data: Body, init?: ResponseInit) => Response;
|
47
|
+
html: (
|
48
|
+
data: string | Promise<string>,
|
49
|
+
init?: ResponseInit,
|
50
|
+
) => Response | Promise<Response>;
|
51
|
+
};
|
52
|
+
```
|
53
|
+
|
54
|
+
**UnstableNext**
|
55
|
+
|
56
|
+
```ts
|
57
|
+
type UnstableNext = () => Promise<void>;
|
58
|
+
```
|
59
|
+
|
60
|
+
## Examples
|
61
|
+
|
62
|
+
### Web Server Timing
|
63
|
+
|
64
|
+
```ts
|
65
|
+
import { UnstableMiddleware } from '@modern-js/runtime/server';
|
66
|
+
|
67
|
+
const time: UnstableMiddleware = async (c, next) => {
|
68
|
+
const start = Date.now();
|
69
|
+
|
70
|
+
await next();
|
71
|
+
|
72
|
+
const end = Date.now();
|
73
|
+
|
74
|
+
console.log(`${end - start}`);
|
75
|
+
};
|
76
|
+
|
77
|
+
export const unstableMiddlewares: UnstableMiddleware = [time];
|
78
|
+
```
|
79
|
+
|
80
|
+
### Injecting Server Data for DataLoader Consumption
|
81
|
+
|
82
|
+
```ts title="shared/index.ts"
|
83
|
+
export type Vars = {
|
84
|
+
message: string;
|
85
|
+
};
|
86
|
+
```
|
87
|
+
|
88
|
+
```ts title="server/index.ts"
|
89
|
+
import {
|
90
|
+
UnstableMiddleware,
|
91
|
+
UnstableMiddlewareContext,
|
92
|
+
} from '@modern-js/runtime/server';
|
93
|
+
import type { Vars } from '../shared/index';
|
94
|
+
|
95
|
+
const setPayload: UnstableMiddleware = async (
|
96
|
+
c: UnstableMiddlewareContext<Vars>,
|
97
|
+
next,
|
98
|
+
) => {
|
99
|
+
c.set('message', 'facker');
|
100
|
+
|
101
|
+
await next();
|
102
|
+
};
|
103
|
+
|
104
|
+
export const unstableMiddlewares: UnstableMiddleware = [setPayload];
|
105
|
+
```
|
106
|
+
|
107
|
+
```ts title="src/routes/page.data.ts"
|
108
|
+
import type { Payload } from '../../shared/index';
|
109
|
+
import { LoaderFunctionArgs } from '@modern-js/runtime/router';
|
110
|
+
|
111
|
+
export const loader = async ({ context }: LoaderFunctionArgs<Vars>) => {
|
112
|
+
const message = context?.get('message');
|
113
|
+
|
114
|
+
// ...
|
115
|
+
};
|
116
|
+
```
|
117
|
+
|
118
|
+
### Redirect
|
119
|
+
|
120
|
+
```ts
|
121
|
+
import { UnstableMiddleware } from '@modern-js/runtime/server';
|
122
|
+
|
123
|
+
const auth: UnstableMiddleware = async (c, next) => {
|
124
|
+
const user = getUser(c.request);
|
125
|
+
|
126
|
+
if (!user) {
|
127
|
+
return c.redirect('/login');
|
128
|
+
}
|
129
|
+
|
130
|
+
await next();
|
131
|
+
};
|
132
|
+
|
133
|
+
export const unstableMiddlewares: UnstableMiddleware = [auth];
|
134
|
+
```
|
@@ -50,15 +50,18 @@ The Hook provided by Modern.js is used to control the built-in logic in the Web
|
|
50
50
|
Currently, two Hooks are provided: `AfterMatch` and `AfterRender`, which can be used to modify the rendering results. It can be written in `server/index.ts` as follows:
|
51
51
|
|
52
52
|
```ts
|
53
|
-
import type {
|
53
|
+
import type {
|
54
|
+
AfterMatchHook,
|
55
|
+
AfterRenderHook,
|
56
|
+
} from '@modern-js/runtime/server';
|
54
57
|
|
55
58
|
export const afterMatch: AfterMatchHook = (ctx, next) => {
|
56
59
|
next();
|
57
|
-
}
|
60
|
+
};
|
58
61
|
|
59
62
|
export const afterRender: AfterRenderHook = (ctx, next) => {
|
60
63
|
next();
|
61
|
-
}
|
64
|
+
};
|
62
65
|
```
|
63
66
|
|
64
67
|
Projects should follow these best practices when using Hook:
|
@@ -75,12 +78,18 @@ For more detail, see [Hook](/apis/app/runtime/web-server/hook).
|
|
75
78
|
|
76
79
|
For some projects, there may be more requirements at the server level, Modern.js provides Middleware to add pre-middleware for Web Server. It can only run in a Node environment, so if the project is deployed to another environment, such as a Worker environment, Middleware cannot be used.
|
77
80
|
|
81
|
+
:::note
|
82
|
+
In the next major release, Modern.js will use new middleware to replace this approach.
|
83
|
+
|
84
|
+
It is recommended to use [UnstableMiddleware](/guides/advanced-features/web-server.html#unstablemiddleware) to handle page requests.
|
85
|
+
:::
|
86
|
+
|
78
87
|
Modern.js provides a set of APIs by default for projects to use:
|
79
88
|
|
80
89
|
```ts
|
81
|
-
import {
|
90
|
+
import { Middleware } from '@modern-js/runtime/server';
|
82
91
|
|
83
|
-
export const middleware:
|
92
|
+
export const middleware: Middleware = (context, next) => {
|
84
93
|
const { source: { req, res } } = context;
|
85
94
|
console.log(req.url);
|
86
95
|
next();
|
@@ -99,6 +108,33 @@ Projects should follow these best practices when using Middleware:
|
|
99
108
|
|
100
109
|
**In general, in CSR projects, using Hook can basically meet all the needs of simple scenarios. In SSR projects, Middleware can be used for more complex Node extensions.**
|
101
110
|
|
111
|
+
### UnstableMiddleware
|
112
|
+
|
113
|
+
Modern.js will provide new Middleware to add pre-processing middleware to the Web Server, supporting the execution of custom logic before and after handling the page.
|
114
|
+
|
115
|
+
```ts title="server/index.ts"
|
116
|
+
import {
|
117
|
+
UnstableMiddleware,
|
118
|
+
UnstableMiddlewareContext,
|
119
|
+
} from '@modern-js/runtime/server';
|
120
|
+
|
121
|
+
const time: UnstableMiddleware = async (c: UnstableMiddlewareContext, next) => {
|
122
|
+
const start = Date.now();
|
123
|
+
|
124
|
+
await next();
|
125
|
+
|
126
|
+
const end = Date.now();
|
127
|
+
|
128
|
+
console.log(`dur=${end - start}`);
|
129
|
+
};
|
130
|
+
|
131
|
+
export const unstableMiddleware: UnstableMiddleware[] = [time];
|
132
|
+
```
|
133
|
+
|
134
|
+
:::note
|
135
|
+
For detailed API and more usage, please refer to [UnstableMiddleware](/apis/app/runtime/web-server/unstable_middleware)
|
136
|
+
:::
|
137
|
+
|
102
138
|
## Managed Page Requests with BFF
|
103
139
|
|
104
140
|
The second way is to use BFF to Managed page rendering. In this way, all requests will first hit the BFF service.
|
@@ -0,0 +1,176 @@
|
|
1
|
+
---
|
2
|
+
sidebar_position: 15
|
3
|
+
---
|
4
|
+
|
5
|
+
# Deploy
|
6
|
+
|
7
|
+
Currently, Modern.js can run in the node.js environment, you can host it yourself. At the same time, Modern.js officially supports deployment on the Netlify platform.
|
8
|
+
|
9
|
+
:::info
|
10
|
+
Currently Modern.js only supports running in node.js environments, support for other runtime environments will be provided in a later version.
|
11
|
+
:::
|
12
|
+
|
13
|
+
|
14
|
+
## Commands to build products
|
15
|
+
|
16
|
+
Running the `modern deploy` command will automatically build the output file for the production environment. This process includes optimizing the output file and its dependencies, and detecting the current deployment platform and automatically generating a product that will run on that platform.
|
17
|
+
|
18
|
+
If you want to generate and test the output locally for a specific deployment platform, you can specify the platform by setting the environment variable: `modern deploy`:
|
19
|
+
|
20
|
+
```bash
|
21
|
+
MODERNJS_DEPLOY=netlify npx modern deploy
|
22
|
+
```
|
23
|
+
|
24
|
+
:::info
|
25
|
+
When deploying on the deployment platforms officially supported by Modern.js, there is no need to specify environment variables.
|
26
|
+
:::
|
27
|
+
|
28
|
+
|
29
|
+
## Node.js
|
30
|
+
|
31
|
+
### Single Repo
|
32
|
+
|
33
|
+
By default, Modern.js outputs builds that can be run in a Node.js environment when no Modern.js-supported deployment platform is detected.
|
34
|
+
|
35
|
+
Use the following command to build the project:
|
36
|
+
```bash
|
37
|
+
npx modern deploy
|
38
|
+
```
|
39
|
+
|
40
|
+
When running the `modern deploy` command, Modern.js will generate runnable products and output the following content:
|
41
|
+
|
42
|
+
```bash
|
43
|
+
Static directory: `.output/static`
|
44
|
+
You can preview this build by `node .output/index`
|
45
|
+
```
|
46
|
+
|
47
|
+
At this point, you can run the entire server by `node .output/index`, and the static resources required for the page are in the `.output/static` directory. You can upload these static resources to a CDN yourself:
|
48
|
+
|
49
|
+
:::info
|
50
|
+
By default, when running Modern.js Server, it listens on port 8080. If you want to change the listening port, you can specify the `PORT` environment variable:
|
51
|
+
```
|
52
|
+
PORT=3000 node .output/index
|
53
|
+
```
|
54
|
+
:::
|
55
|
+
|
56
|
+
|
57
|
+
### Monorepo
|
58
|
+
|
59
|
+
For the Monorepo project, in addition to building our current project, we also need to build other repositories that the current project depends on.
|
60
|
+
|
61
|
+
We assume that the name in the `package.json` of the current project is `app`. Taking pnpm as an example of a monorepo management tool, you can add the following command to the `package.json` of the current project to build products for the current project:
|
62
|
+
|
63
|
+
```json title="app/package.json"
|
64
|
+
{
|
65
|
+
"scripts": {
|
66
|
+
"deploy": "modern deploy",
|
67
|
+
"deploy:app": "pnpm --filter 'app^...' run build && pnpm --filter=app run deploy",
|
68
|
+
}
|
69
|
+
}
|
70
|
+
```
|
71
|
+
|
72
|
+
If you use rush to manage repositories, you can add the following command in `package.json`:
|
73
|
+
|
74
|
+
```json
|
75
|
+
{
|
76
|
+
"scripts": {
|
77
|
+
"deploy": "modern deploy",
|
78
|
+
"deploy:app": "rush rebuild --to-except app && rushx deploy",
|
79
|
+
}
|
80
|
+
}
|
81
|
+
```
|
82
|
+
|
83
|
+
After the build is completed, Modern.js will generate all dependencies in the `.output/node_modules` directory of the project. Similarly, you can run the entire server using `node .output/index`.
|
84
|
+
|
85
|
+
## Netlify
|
86
|
+
|
87
|
+
Netlify is a popular web development platform designed for building, deploying, and maintaining modern web projects. Deploying on Netlify mainly requires configuring the `netlify.toml` file.
|
88
|
+
|
89
|
+
Depending on the complexity of your project, you can configure it incrementally by this doc.
|
90
|
+
|
91
|
+
### Pure Front-end Project
|
92
|
+
|
93
|
+
Add the `netlify.toml` file to the root directory of the current project:
|
94
|
+
|
95
|
+
```bash
|
96
|
+
./
|
97
|
+
├── src/
|
98
|
+
├── modern.config.ts
|
99
|
+
├── netlify.toml
|
100
|
+
├── package.json
|
101
|
+
```
|
102
|
+
|
103
|
+
Add the following content to `netlify.toml`:
|
104
|
+
```toml
|
105
|
+
[build]
|
106
|
+
publish = "dist"
|
107
|
+
command = "npm run deploy"
|
108
|
+
```
|
109
|
+
|
110
|
+
Add a project to the Netlify platform and deploy it!
|
111
|
+
|
112
|
+
### Full Stack Project
|
113
|
+
|
114
|
+
Full-stack projects refer to projects that use custom servers, SSR, and BFF. These projects need to be deployed on Netlify Functions. Based on the `netlify.toml` file mentioned above,
|
115
|
+
add the following configuration:
|
116
|
+
|
117
|
+
```toml title="netlify.toml"
|
118
|
+
[build]
|
119
|
+
publish = "dist"
|
120
|
+
command = "npm run deploy"
|
121
|
+
|
122
|
+
[functions]
|
123
|
+
directory = ".netlify/functions"
|
124
|
+
node_bundler = "none"
|
125
|
+
included_files = [".netlify/functions/**"]
|
126
|
+
|
127
|
+
```
|
128
|
+
|
129
|
+
:::info
|
130
|
+
Currently, Modern.js does not support deployment on Netlify Edge Functions. We will support it in future versions.
|
131
|
+
:::
|
132
|
+
|
133
|
+
|
134
|
+
### Monorepo
|
135
|
+
|
136
|
+
For Monorepo projects, in addition to building our current project, we also need to build the dependencies of the current project from other repositories.
|
137
|
+
We take a pnpm monorepo repository as an example and deploy the Monorepo project on Netlify.
|
138
|
+
|
139
|
+
Suppose we have the following Monorepo repository:
|
140
|
+
|
141
|
+
```
|
142
|
+
./
|
143
|
+
├── packages/
|
144
|
+
│ ├── app/
|
145
|
+
│ └── app-dep1
|
146
|
+
├── package.json
|
147
|
+
├── pnpm-lock.yaml
|
148
|
+
└── pnpm-workspace.yaml
|
149
|
+
```
|
150
|
+
|
151
|
+
We need to configure Base directory on the netlify platform as `packages/app`:
|
152
|
+
|
153
|
+
<img src="https://sf16-sg.tiktokcdn.com/obj/eden-sg/lmeh7nuptpfnuhd/netlify-monorepo-basedir.png?x-resource-account=public" />
|
154
|
+
|
155
|
+
Add the following script in `packages/app/package.json`, before executing the deployment command of the `app` repository, first execute the build of other repositories in the workspace:
|
156
|
+
|
157
|
+
```json
|
158
|
+
"scripts": {
|
159
|
+
"deploy:app": "pnpm --filter 'app^...' run build && pnpm --filter=app run deploy",
|
160
|
+
}
|
161
|
+
```
|
162
|
+
|
163
|
+
Configure the build command in `netlify.toml`:
|
164
|
+
|
165
|
+
```toml
|
166
|
+
[build]
|
167
|
+
publish = "dist"
|
168
|
+
command = "npm run deploy:app"
|
169
|
+
|
170
|
+
[functions]
|
171
|
+
directory = ".netlify/functions"
|
172
|
+
node_bundler = "none"
|
173
|
+
included_files = [".netlify/functions/**"]
|
174
|
+
```
|
175
|
+
|
176
|
+
Just submit your code and deploy it using the Netlify platform.
|
@@ -1,10 +1,17 @@
|
|
1
1
|
---
|
2
2
|
title: Middleware
|
3
3
|
---
|
4
|
+
|
4
5
|
# Middleware
|
5
6
|
|
6
7
|
用于拓展 Modern.js 内置的 Web Server,与 [Hook](/apis/app/runtime/web-server/hook) 不同的是,Middleware 可以直接操作 Node 原生的请求、响应对象,并且可以使用框架拓展。
|
7
8
|
|
9
|
+
:::note
|
10
|
+
在下一个大版本,Modern.js 将会使用新 Middleware 来替代该写法。
|
11
|
+
|
12
|
+
推荐使用 [UnstableMiddleware](/apis/app/runtime/web-server/unstable_middleware) 处理页面请求。
|
13
|
+
:::
|
14
|
+
|
8
15
|
:::note
|
9
16
|
更多内容可以查看[自定义 Web Server](/guides/advanced-features/web-server)。
|
10
17
|
:::
|
@@ -0,0 +1,133 @@
|
|
1
|
+
---
|
2
|
+
title: Unstable Middleware
|
3
|
+
---
|
4
|
+
|
5
|
+
# Unstable Middleware
|
6
|
+
|
7
|
+
用于拓展 Modern.js 内置的 Web Server。 未来 UnstableMiddleware 将替代 [Middleware](/apis/app/runtime/web-server/middleware)
|
8
|
+
|
9
|
+
## 使用
|
10
|
+
|
11
|
+
```ts title="server/index.ts"
|
12
|
+
import { UnstableMiddleware } from '@modern-js/runtime/server';
|
13
|
+
|
14
|
+
export const unstableMiddlewares: UnstableMiddleware = [];
|
15
|
+
```
|
16
|
+
|
17
|
+
## 类型
|
18
|
+
|
19
|
+
**UnstableMiddleware**
|
20
|
+
|
21
|
+
```ts
|
22
|
+
type UnstableMiddleware<
|
23
|
+
V extends Record<string, unknown> = Record<string, unknown>,
|
24
|
+
> = (
|
25
|
+
c: UnstableMiddlewareContext<V>,
|
26
|
+
next: UnstableNext,
|
27
|
+
) => Promise<void | Response>;
|
28
|
+
```
|
29
|
+
|
30
|
+
**UnstableMiddlewareContext**
|
31
|
+
|
32
|
+
```ts
|
33
|
+
type Body = ReadableStream | ArrayBuffer | string | null;
|
34
|
+
|
35
|
+
type UnstableMiddlewareContext<
|
36
|
+
V extends Record<string, unknown> = Record<string, unknown>,
|
37
|
+
> = {
|
38
|
+
request: Request;
|
39
|
+
response: Response;
|
40
|
+
get: Get<V>;
|
41
|
+
set: Set<V>;
|
42
|
+
header: (name: string, value: string, options?: { append?: boolean }) => void;
|
43
|
+
status: (code: number) => void;
|
44
|
+
redirect: (location: string, status?: number) => Response;
|
45
|
+
body: (data: Body, init?: ResponseInit) => Response;
|
46
|
+
html: (
|
47
|
+
data: string | Promise<string>,
|
48
|
+
init?: ResponseInit,
|
49
|
+
) => Response | Promise<Response>;
|
50
|
+
};
|
51
|
+
```
|
52
|
+
|
53
|
+
**UnstableNext**
|
54
|
+
|
55
|
+
```ts
|
56
|
+
type UnstableNext = () => Promise<void>;
|
57
|
+
```
|
58
|
+
|
59
|
+
## 用例
|
60
|
+
|
61
|
+
### web server 耗时打点
|
62
|
+
|
63
|
+
```ts
|
64
|
+
import { UnstableMiddleware } from '@modern-js/runtime/server';
|
65
|
+
|
66
|
+
const time: UnstableMiddleware = async (c, next) => {
|
67
|
+
const start = Date.now();
|
68
|
+
|
69
|
+
await next();
|
70
|
+
|
71
|
+
const end = Date.now();
|
72
|
+
|
73
|
+
console.log(`${end - start}`);
|
74
|
+
};
|
75
|
+
|
76
|
+
export const unstableMiddlewares: UnstableMiddleware = [time];
|
77
|
+
```
|
78
|
+
|
79
|
+
### 注入服务端数据,供页面 dataLoader 消费
|
80
|
+
|
81
|
+
```ts title="shared/index.ts"
|
82
|
+
export type Vars = {
|
83
|
+
message: string;
|
84
|
+
};
|
85
|
+
```
|
86
|
+
|
87
|
+
```ts title="server/index.ts"
|
88
|
+
import {
|
89
|
+
UnstableMiddleware,
|
90
|
+
UnstableMiddlewareContext,
|
91
|
+
} from '@modern-js/runtime/server';
|
92
|
+
import type { Vars } from '../shared/index';
|
93
|
+
|
94
|
+
const setPayload: UnstableMiddleware = async (
|
95
|
+
c: UnstableMiddlewareContext<Vars>,
|
96
|
+
next,
|
97
|
+
) => {
|
98
|
+
c.set('message', 'facker');
|
99
|
+
|
100
|
+
await next();
|
101
|
+
};
|
102
|
+
|
103
|
+
export const unstableMiddlewares: UnstableMiddleware = [setPayload];
|
104
|
+
```
|
105
|
+
|
106
|
+
```ts title="src/routes/page.data.ts"
|
107
|
+
import type { Payload } from '../../shared/index';
|
108
|
+
import { LoaderFunctionArgs } from '@modern-js/runtime/router';
|
109
|
+
|
110
|
+
export const loader = async ({ context }: LoaderFunctionArgs<Vars>) => {
|
111
|
+
const message = context?.get('message');
|
112
|
+
|
113
|
+
// ...
|
114
|
+
};
|
115
|
+
```
|
116
|
+
|
117
|
+
### 重定向
|
118
|
+
|
119
|
+
```ts
|
120
|
+
import { UnstableMiddleware } from '@modern-js/runtime/server';
|
121
|
+
|
122
|
+
const auth: UnstableMiddleware = async (c, next) => {
|
123
|
+
const user = getUser(c.request);
|
124
|
+
|
125
|
+
if (!user) {
|
126
|
+
return c.redirect('/login');
|
127
|
+
}
|
128
|
+
|
129
|
+
await next();
|
130
|
+
};
|
131
|
+
|
132
|
+
export const unstableMiddlewares: UnstableMiddleware = [auth];
|
133
|
+
```
|
@@ -76,12 +76,18 @@ export const afterRender: AfterRenderHook = (ctx, next) => {
|
|
76
76
|
|
77
77
|
对于某些项目,可能在服务端有更多的需求,Modern.js 提供了 Middleware 为 Web Server 添加前置中间件。它只能运行在 Node 环境下,因此如果项目被部署到其他环境中,如 Worker 环境,则不可以使用 Middleware。
|
78
78
|
|
79
|
+
:::note
|
80
|
+
下一个大版本,Modern.js 将会使用新 Middleware 来替代该写法。
|
81
|
+
|
82
|
+
推荐使用 [UnstableMiddleware](/guides/advanced-features/web-server.html#unstablemiddleware) 处理页面请求。
|
83
|
+
:::
|
84
|
+
|
79
85
|
Modern.js 默认提供了一套 API 供项目使用:
|
80
86
|
|
81
87
|
```ts
|
82
|
-
import {
|
88
|
+
import { Middleware } from '@modern-js/runtime/server';
|
83
89
|
|
84
|
-
export const middleware:
|
90
|
+
export const middleware: Middleware = (context, next) => {
|
85
91
|
const {
|
86
92
|
source: { req, res },
|
87
93
|
} = context;
|
@@ -102,6 +108,33 @@ export const middleware: Middlewre = (context, next) => {
|
|
102
108
|
|
103
109
|
**总的来说,CSR 项目中,使用 Hook 基本能满足简单场景的所有需求。SSR 项目中,可以使用 Middleware 做更复杂的 Node 扩展。**
|
104
110
|
|
111
|
+
### UnstableMiddleware
|
112
|
+
|
113
|
+
Modern.js 将提供新 Middleware 为 Web Server 添加前置中间件,支持在处理页面的前后执行自定义逻辑。
|
114
|
+
|
115
|
+
```ts title="server/index.ts"
|
116
|
+
import {
|
117
|
+
UnstableMiddleware,
|
118
|
+
UnstableMiddlewareContext,
|
119
|
+
} from '@modern-js/runtime/server';
|
120
|
+
|
121
|
+
const time: UnstableMiddleware = async (c: UnstableMiddlewareContext, next) => {
|
122
|
+
const start = Date.now();
|
123
|
+
|
124
|
+
await next();
|
125
|
+
|
126
|
+
const end = Date.now();
|
127
|
+
|
128
|
+
console.log(`dur=${end - start}`);
|
129
|
+
};
|
130
|
+
|
131
|
+
export const unstableMiddleware: UnstableMiddleware[] = [time];
|
132
|
+
```
|
133
|
+
|
134
|
+
:::note
|
135
|
+
详细 API 和更多用法查看 [UnstableMiddleware](/apis/app/runtime/web-server/unstable_middleware)
|
136
|
+
:::
|
137
|
+
|
105
138
|
## 通过 BFF 托管页面请求
|
106
139
|
|
107
140
|
第二种方式,是利用 BFF 来托管页面渲染,这种方式下,所有的请求都会先打到 BFF 的服务。
|
@@ -0,0 +1,177 @@
|
|
1
|
+
---
|
2
|
+
sidebar_position: 15
|
3
|
+
---
|
4
|
+
|
5
|
+
# 部署
|
6
|
+
|
7
|
+
目前 Modern.js 支持在 node.js 环境下运行,你可以自行托管,同时,Modern.js 官方支持在 Netlify 平台上部署。
|
8
|
+
|
9
|
+
:::info
|
10
|
+
当前仅支持在 node.js 环境运行,对其他运行时环境的支持将在后续版本中提供。
|
11
|
+
:::
|
12
|
+
|
13
|
+
|
14
|
+
## 构建产物的命令
|
15
|
+
|
16
|
+
执行 `modern deploy` 命令将自动构建适用于生产环境的输出文件。此过程包括优化输出文件及其依赖,并检测当前部署平台,自动生成可以在该平台运行的产物。
|
17
|
+
如果你希望在本地生成并测试特定部署平台的产物,可以通过设置环境变量来指定平台:
|
18
|
+
|
19
|
+
```bash
|
20
|
+
MODERNJS_DEPLOY=netlify npx modern deploy
|
21
|
+
```
|
22
|
+
|
23
|
+
:::info
|
24
|
+
在 Modern.js 官方支持的部署平台中部署时,无需指定环境变量。
|
25
|
+
:::
|
26
|
+
|
27
|
+
|
28
|
+
## Node.js
|
29
|
+
|
30
|
+
### 单仓库项目
|
31
|
+
|
32
|
+
默认情况下,当未检测到 Modern.js 支持的部署平台时,Modern.js 会输出可以在 Node.js 环境下运行的构建产物。
|
33
|
+
|
34
|
+
使用以下命令构建项目:
|
35
|
+
```bash
|
36
|
+
npx modern deploy
|
37
|
+
```
|
38
|
+
|
39
|
+
当执行 `modern deploy` 命令时,Modern.js 会产出可运行的生产环境产物,并输出以下内容:
|
40
|
+
|
41
|
+
```bash
|
42
|
+
Static directory: `.output/static`
|
43
|
+
You can preview this build by `node .output/index`
|
44
|
+
```
|
45
|
+
|
46
|
+
此时,你可以通过 `node .output/index` 运行整个 server,在 `.output/static` 目录下是页面所需的静态资源,你可以将这些静态资源自行上传至 CDN。
|
47
|
+
|
48
|
+
:::info
|
49
|
+
默认情况下,运行 Modern.js Server 时会监听 8080 端口,如果你想修改监听的端口,可以指定 `PORT` 环境变量:
|
50
|
+
```
|
51
|
+
PORT=3000 node .output/index
|
52
|
+
```
|
53
|
+
:::
|
54
|
+
|
55
|
+
|
56
|
+
### Monorepo
|
57
|
+
|
58
|
+
对于 Monorepo 项目,除了需要构建我们当前的项目外,还需要构建当前项目的依赖的其他仓库。
|
59
|
+
|
60
|
+
假设当前项目的 `package.json` 中的 name 为 `app`,以 pnpm 作为 monorepo 管理工具为例,你可以在当前项目的 `package.json` 添加以下命令用于构建当前项目的产物:
|
61
|
+
|
62
|
+
```json title="app/package.json"
|
63
|
+
{
|
64
|
+
"scripts": {
|
65
|
+
"deploy": "modern deploy",
|
66
|
+
"deploy:app": "pnpm --filter 'app^...' run build && pnpm --filter=app run deploy",
|
67
|
+
}
|
68
|
+
}
|
69
|
+
```
|
70
|
+
|
71
|
+
如果你使用 rush 管理仓库,可以在 `package.json` 中添加以下命令:
|
72
|
+
|
73
|
+
```json
|
74
|
+
{
|
75
|
+
"scripts": {
|
76
|
+
"deploy": "modern deploy",
|
77
|
+
"deploy:app": "rush rebuild --to-except app && rushx deploy",
|
78
|
+
}
|
79
|
+
}
|
80
|
+
```
|
81
|
+
|
82
|
+
当构建完成后,Modern.js 会将项目中所有的依赖生成在 `.output/node_modules` 目录下。同样的,你可以使用 `node .output/index` 运行整个 Server。
|
83
|
+
|
84
|
+
## Netlify
|
85
|
+
|
86
|
+
Netlify 是一个流行的 web 开发平台,专为构建、发布和维护现代 web 项目而设计,在 Netlify 上部署,主要需要配置 `netlify.toml` 文件,
|
87
|
+
根据你的项目复杂度,可以渐进配置。
|
88
|
+
|
89
|
+
### 纯前端项目
|
90
|
+
|
91
|
+
在当前项目的根目录添加 `netlify.toml` 文件:
|
92
|
+
|
93
|
+
```bash
|
94
|
+
./
|
95
|
+
├── src/
|
96
|
+
├── modern.config.ts
|
97
|
+
├── netlify.toml
|
98
|
+
├── package.json
|
99
|
+
```
|
100
|
+
|
101
|
+
在 `netlify.toml` 中添加以下内容:
|
102
|
+
```toml
|
103
|
+
[build]
|
104
|
+
publish = "dist"
|
105
|
+
command = "npm run deploy"
|
106
|
+
```
|
107
|
+
|
108
|
+
在 Netlify 平台上添加项目,部署即可。
|
109
|
+
|
110
|
+
### 全栈项目
|
111
|
+
|
112
|
+
全栈项目是指使用了 自定义 Server,SSR,BFF 的项目,这些项目需要部署在 Netlify Functions 上。基于上述的 `netlify.toml` 文件,
|
113
|
+
添加以下配置:
|
114
|
+
|
115
|
+
```toml title="netlify.toml"
|
116
|
+
[build]
|
117
|
+
publish = "dist"
|
118
|
+
command = "npm run deploy"
|
119
|
+
|
120
|
+
[functions]
|
121
|
+
directory = ".netlify/functions"
|
122
|
+
node_bundler = "none"
|
123
|
+
included_files = [".netlify/functions/**"]
|
124
|
+
|
125
|
+
```
|
126
|
+
|
127
|
+
:::info
|
128
|
+
目前 Modern.js 还不支持在 Netlify Edge Functions 进行部署,我们将在后续的版本中支持。
|
129
|
+
:::
|
130
|
+
|
131
|
+
|
132
|
+
### Monorepo 项目
|
133
|
+
|
134
|
+
对于 Monorepo 项目,除了需要构建我们当前的项目外,还需要构建当前项目的依赖的其他仓库。我们以一个 pnpm monorepo 仓库为例,
|
135
|
+
在 Netlify 上对 Monorepo 项目进行部署。
|
136
|
+
|
137
|
+
假设我们有以下 Monorepo 仓库:
|
138
|
+
|
139
|
+
```
|
140
|
+
./
|
141
|
+
├── packages/
|
142
|
+
│ ├── app/
|
143
|
+
│ └── app-dep1
|
144
|
+
├── package.json
|
145
|
+
├── pnpm-lock.yaml
|
146
|
+
└── pnpm-workspace.yaml
|
147
|
+
```
|
148
|
+
|
149
|
+
我们需要在 netlify 平台上配置 Base directory 为 `packages/app`:
|
150
|
+
|
151
|
+
<img src="https://sf16-sg.tiktokcdn.com/obj/eden-sg/lmeh7nuptpfnuhd/netlify-monorepo-basedir.png?x-resource-account=public" />
|
152
|
+
|
153
|
+
在 `packages/app/package.json` 中添加以下 script,在执行 `app` 仓库的部署命令之前,先执行 workspace 中其他仓库的构建:
|
154
|
+
|
155
|
+
```json
|
156
|
+
"scripts": {
|
157
|
+
"deploy:app": "pnpm --filter 'app^...' run build && pnpm --filter=app run deploy",
|
158
|
+
}
|
159
|
+
```
|
160
|
+
|
161
|
+
在 `netlify.toml` 配置构建命令:
|
162
|
+
|
163
|
+
```toml
|
164
|
+
[build]
|
165
|
+
publish = "dist"
|
166
|
+
command = "npm run deploy:app"
|
167
|
+
|
168
|
+
[functions]
|
169
|
+
directory = ".netlify/functions"
|
170
|
+
node_bundler = "none"
|
171
|
+
included_files = [".netlify/functions/**"]
|
172
|
+
```
|
173
|
+
|
174
|
+
提交你的代码,使用 Netlify 平台部署即可。
|
175
|
+
|
176
|
+
|
177
|
+
|
package/package.json
CHANGED
@@ -15,17 +15,17 @@
|
|
15
15
|
"modern",
|
16
16
|
"modern.js"
|
17
17
|
],
|
18
|
-
"version": "2.
|
18
|
+
"version": "2.51.0",
|
19
19
|
"publishConfig": {
|
20
20
|
"registry": "https://registry.npmjs.org/",
|
21
21
|
"access": "public",
|
22
22
|
"provenance": true
|
23
23
|
},
|
24
24
|
"dependencies": {
|
25
|
-
"@modern-js/sandpack-react": "2.
|
25
|
+
"@modern-js/sandpack-react": "2.51.0"
|
26
26
|
},
|
27
27
|
"peerDependencies": {
|
28
|
-
"@modern-js/builder-doc": "^2.
|
28
|
+
"@modern-js/builder-doc": "^2.51.0"
|
29
29
|
},
|
30
30
|
"devDependencies": {
|
31
31
|
"classnames": "^2",
|
@@ -39,8 +39,8 @@
|
|
39
39
|
"@rspress/shared": "1.18.2",
|
40
40
|
"@types/node": "^16",
|
41
41
|
"@types/fs-extra": "9.0.13",
|
42
|
-
"@modern-js/doc
|
43
|
-
"@modern-js/
|
42
|
+
"@modern-js/builder-doc": "2.51.0",
|
43
|
+
"@modern-js/doc-plugin-auto-sidebar": "2.51.0"
|
44
44
|
},
|
45
45
|
"scripts": {
|
46
46
|
"dev": "rspress dev",
|