@modern-js/main-doc 2.33.1 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/en/apis/app/hooks/config/public.mdx +2 -2
- package/docs/en/apis/app/hooks/config/upload.mdx +3 -3
- package/docs/en/components/tech-stack-node-framework.mdx +1 -0
- package/docs/en/configure/app/server/ssr.mdx +2 -0
- package/docs/en/configure/app/source/config-dir.mdx +2 -2
- package/docs/en/guides/advanced-features/eslint.mdx +1 -1
- package/docs/en/guides/basic-features/alias.mdx +11 -50
- package/docs/en/guides/basic-features/env-vars.mdx +1 -1
- package/docs/en/guides/basic-features/routes.mdx +4 -4
- package/docs/en/guides/concept/builder.mdx +1 -1
- package/docs/en/guides/get-started/glossary.mdx +1 -1
- package/docs/en/guides/get-started/introduction.mdx +21 -1
- package/docs/en/guides/get-started/tech-stack.mdx +138 -0
- package/docs/en/guides/topic-detail/changesets/add.mdx +1 -1
- package/docs/en/guides/topic-detail/changesets/changelog.mdx +3 -3
- package/docs/en/guides/topic-detail/changesets/commit.mdx +3 -3
- package/docs/en/guides/topic-detail/changesets/release-note.mdx +3 -3
- package/docs/en/guides/topic-detail/changesets/release.mdx +1 -1
- package/docs/en/guides/topic-detail/framework-plugin/implement.mdx +4 -4
- package/docs/en/guides/topic-detail/generator/create/use.mdx +1 -9
- package/docs/en/guides/topic-detail/generator/plugin/context.md +1 -1
- package/docs/en/tutorials/examples/_category_.json +5 -0
- package/docs/en/tutorials/examples/csr-auth.mdx +214 -0
- package/docs/en/tutorials/foundations/introduction.mdx +10 -1
- package/docs/zh/community/blog/2022-0708-updates.md +4 -4
- package/docs/zh/community/blog/overview.md +1 -1
- package/docs/zh/components/tech-stack-node-framework.mdx +1 -0
- package/docs/zh/configure/app/server/ssr.mdx +3 -0
- package/docs/zh/guides/advanced-features/eslint.mdx +1 -1
- package/docs/zh/guides/basic-features/alias.mdx +11 -50
- package/docs/zh/guides/basic-features/routes.mdx +1 -1
- package/docs/zh/guides/get-started/introduction.mdx +20 -0
- package/docs/zh/guides/get-started/tech-stack.mdx +138 -0
- package/docs/zh/guides/topic-detail/changesets/add.mdx +1 -1
- package/docs/zh/guides/topic-detail/changesets/changelog.mdx +3 -3
- package/docs/zh/guides/topic-detail/changesets/commit.mdx +3 -3
- package/docs/zh/guides/topic-detail/changesets/release-note.mdx +3 -3
- package/docs/zh/guides/topic-detail/changesets/release.mdx +1 -1
- package/docs/zh/guides/topic-detail/framework-plugin/implement.mdx +5 -5
- package/docs/zh/guides/topic-detail/generator/create/use.mdx +0 -8
- package/docs/zh/guides/topic-detail/generator/plugin/context.md +1 -1
- package/docs/zh/tutorials/examples/_category_.json +5 -0
- package/docs/zh/tutorials/examples/csr-auth.mdx +214 -0
- package/docs/zh/tutorials/foundations/introduction.mdx +8 -0
- package/package.json +8 -5
- package/src/components/Sandpack/index.css +10 -0
- package/src/components/Sandpack/index.tsx +30 -0
@@ -0,0 +1,214 @@
|
|
1
|
+
---
|
2
|
+
title: Route Authorization
|
3
|
+
---
|
4
|
+
|
5
|
+
# Route Authorization
|
6
|
+
|
7
|
+
Modern.js defaults to the convention-based routing based on React Router 6. For more details, please refer to [Routing](/guides/basic-features/routes.html#routing-scheme).
|
8
|
+
|
9
|
+
In a web application, if there are multiple routes, we may need to authorize access to some of them before accessing them. For example, in the following scenario:
|
10
|
+
|
11
|
+
- Access to the `/` route does not require authorization and can be accessed directly.
|
12
|
+
- Access to the `/protected` route requires authorization. If there is no authorization, it will automatically redirect to the `/login` route. After successful login, it returns to `/protected`.
|
13
|
+
|
14
|
+
import Sandpack from '@site/src/components/Sandpack';
|
15
|
+
|
16
|
+
<Sandpack template="web-app">
|
17
|
+
```tsx title="src/routes/page.tsx"
|
18
|
+
import { Helmet } from '@modern-js/runtime/head';
|
19
|
+
import './index.css';
|
20
|
+
|
21
|
+
const PublicPage = (): JSX.Element => (
|
22
|
+
<div className="container-box">
|
23
|
+
<Helmet>
|
24
|
+
<link
|
25
|
+
rel="icon"
|
26
|
+
type="image/x-icon"
|
27
|
+
href="https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/favicon.ico"
|
28
|
+
/>
|
29
|
+
</Helmet>
|
30
|
+
<h3>Public</h3>
|
31
|
+
</div>
|
32
|
+
);
|
33
|
+
|
34
|
+
export default PublicPage;
|
35
|
+
|
36
|
+
```
|
37
|
+
```tsx title="src/routes/layout.tsx"
|
38
|
+
import { Link, Outlet } from '@modern-js/runtime/router';
|
39
|
+
import { AuthProvider, AuthStatus } from './Auth';
|
40
|
+
|
41
|
+
export default function Layout() {
|
42
|
+
return (
|
43
|
+
<AuthProvider>
|
44
|
+
<AuthStatus />
|
45
|
+
|
46
|
+
<ul>
|
47
|
+
<li>
|
48
|
+
<Link to="/">Public Page</Link>
|
49
|
+
</li>
|
50
|
+
<li>
|
51
|
+
<Link to="/protected">Protected Page</Link>
|
52
|
+
</li>
|
53
|
+
</ul>
|
54
|
+
|
55
|
+
<Outlet />
|
56
|
+
</AuthProvider>
|
57
|
+
);
|
58
|
+
}
|
59
|
+
|
60
|
+
```
|
61
|
+
```ts title="src/routes/fakeAuth.ts"
|
62
|
+
/**
|
63
|
+
* This represents some generic auth provider API, like Firebase.
|
64
|
+
*/
|
65
|
+
const fakeAuthProvider = {
|
66
|
+
isAuthenticated: false,
|
67
|
+
signin(callback: VoidFunction) {
|
68
|
+
fakeAuthProvider.isAuthenticated = true;
|
69
|
+
setTimeout(callback, 100); // fake async
|
70
|
+
},
|
71
|
+
signout(callback: VoidFunction) {
|
72
|
+
fakeAuthProvider.isAuthenticated = false;
|
73
|
+
setTimeout(callback, 100);
|
74
|
+
},
|
75
|
+
};
|
76
|
+
|
77
|
+
export { fakeAuthProvider };
|
78
|
+
|
79
|
+
```
|
80
|
+
```ts title="src/routes/Auth.tsx"
|
81
|
+
import React from 'react';
|
82
|
+
import { useNavigate, Navigate, useLocation } from '@modern-js/runtime/router';
|
83
|
+
import { fakeAuthProvider } from './fakeAuth';
|
84
|
+
|
85
|
+
interface AuthContextType {
|
86
|
+
user: any;
|
87
|
+
signin: (user: string, callback: VoidFunction) => void;
|
88
|
+
signout: (callback: VoidFunction) => void;
|
89
|
+
}
|
90
|
+
|
91
|
+
const AuthContext = React.createContext<AuthContextType>(null!);
|
92
|
+
|
93
|
+
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
94
|
+
const [user, setUser] = React.useState<any>(null);
|
95
|
+
|
96
|
+
const signin = (newUser: string, callback: VoidFunction) =>
|
97
|
+
fakeAuthProvider.signin(() => {
|
98
|
+
setUser(newUser);
|
99
|
+
callback();
|
100
|
+
});
|
101
|
+
|
102
|
+
const signout = (callback: VoidFunction) =>
|
103
|
+
fakeAuthProvider.signout(() => {
|
104
|
+
setUser(null);
|
105
|
+
callback();
|
106
|
+
});
|
107
|
+
|
108
|
+
const value = { user, signin, signout };
|
109
|
+
|
110
|
+
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
111
|
+
}
|
112
|
+
|
113
|
+
export function useAuth() {
|
114
|
+
return React.useContext(AuthContext);
|
115
|
+
}
|
116
|
+
|
117
|
+
export function AuthStatus() {
|
118
|
+
const auth = useAuth();
|
119
|
+
console.log('auth', auth);
|
120
|
+
const navigate = useNavigate();
|
121
|
+
|
122
|
+
if (!auth.user) {
|
123
|
+
return <p>You are not logged in.</p>;
|
124
|
+
}
|
125
|
+
|
126
|
+
return (
|
127
|
+
<p>
|
128
|
+
Welcome {auth.user}!{' '}
|
129
|
+
<button
|
130
|
+
type="button"
|
131
|
+
onClick={() => {
|
132
|
+
auth.signout(() => navigate('/'));
|
133
|
+
}}
|
134
|
+
>
|
135
|
+
Sign out
|
136
|
+
</button>
|
137
|
+
</p>
|
138
|
+
);
|
139
|
+
}
|
140
|
+
|
141
|
+
export function RequireAuth({ children }: { children: JSX.Element }) {
|
142
|
+
const auth = useAuth();
|
143
|
+
const location = useLocation();
|
144
|
+
|
145
|
+
if (!auth.user) {
|
146
|
+
// Redirect them to the /login page, but save the current location they were
|
147
|
+
// trying to go to when they were redirected. This allows us to send them
|
148
|
+
// along to that page after they login, which is a nicer user experience
|
149
|
+
// than dropping them off on the home page.
|
150
|
+
return <Navigate to="/login" state={{ from: location }} replace />;
|
151
|
+
}
|
152
|
+
|
153
|
+
return children;
|
154
|
+
}
|
155
|
+
|
156
|
+
```
|
157
|
+
```ts title="src/routes/protected/page.tsx"
|
158
|
+
import { RequireAuth } from '../Auth';
|
159
|
+
|
160
|
+
export default function ProtectedPage() {
|
161
|
+
return (
|
162
|
+
<div className="container-box">
|
163
|
+
<RequireAuth>
|
164
|
+
<h3>Protected</h3>
|
165
|
+
</RequireAuth>
|
166
|
+
</div>
|
167
|
+
);
|
168
|
+
}
|
169
|
+
|
170
|
+
```
|
171
|
+
```ts title="src/routes/login/page.tsx"
|
172
|
+
import { useLocation, useNavigate } from '@modern-js/runtime/router';
|
173
|
+
import { useAuth } from '../Auth';
|
174
|
+
|
175
|
+
export default function Login() {
|
176
|
+
const navigate = useNavigate();
|
177
|
+
const location = useLocation();
|
178
|
+
const auth = useAuth();
|
179
|
+
|
180
|
+
const from = location.state?.from?.pathname || '/';
|
181
|
+
|
182
|
+
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
|
183
|
+
event.preventDefault();
|
184
|
+
|
185
|
+
const formData = new FormData(event.currentTarget);
|
186
|
+
const username = formData.get('username') as string;
|
187
|
+
|
188
|
+
auth.signin(username, () => {
|
189
|
+
// Send them back to the page they tried to visit when they were
|
190
|
+
// redirected to the login page. Use { replace: true } so we don't create
|
191
|
+
// another entry in the history stack for the login page. This means that
|
192
|
+
// when they get to the protected page and click the back button, they
|
193
|
+
// won't end up back on the login page, which is also really nice for the
|
194
|
+
// user experience.
|
195
|
+
navigate(from, { replace: true });
|
196
|
+
});
|
197
|
+
}
|
198
|
+
|
199
|
+
return (
|
200
|
+
<div>
|
201
|
+
<p>You must log in to view the page at {from}</p>
|
202
|
+
|
203
|
+
<form onSubmit={handleSubmit}>
|
204
|
+
<label>
|
205
|
+
Username: <input name="username" type="text" />
|
206
|
+
</label>{' '}
|
207
|
+
<button type="submit">Login</button>
|
208
|
+
</form>
|
209
|
+
</div>
|
210
|
+
);
|
211
|
+
}
|
212
|
+
|
213
|
+
```
|
214
|
+
</Sandpack>
|
@@ -24,5 +24,14 @@ We have prepared a tutorial on creating a "contact list app" that you can follow
|
|
24
24
|
- Data fetching
|
25
25
|
- State Management
|
26
26
|
- Container components
|
27
|
-
- New
|
27
|
+
- New entry
|
28
28
|
- ...
|
29
|
+
|
30
|
+
## Case Studies
|
31
|
+
|
32
|
+
We offer some commonly used case studies for your reference during the development process. Here you can find some usage patterns of the feature combinations provided by Modern.js. We will continue to improve the case studies here.
|
33
|
+
|
34
|
+
- [Route Authorization](/tutorials/examples/csr-auth.html)
|
35
|
+
- ...
|
36
|
+
|
37
|
+
Let's start from [creating a project](tutorials/first-app/c01-start) now!
|
@@ -10,7 +10,7 @@ Modern.js 7 ~ 8 月的最新版本为 v1.17.0,本双月的主要更新有:
|
|
10
10
|
|
11
11
|
- **支持 React 18**:完成框架和插件对 React 18 的适配。
|
12
12
|
- **包版本统一**:Modern.js 所有组成包的版本号进行统一,提供升级命令。
|
13
|
-
-
|
13
|
+
- **Modern.js Module 支持 bundle 构建**:Modern.js Module 项目,支持对产物做 bundle 构建。
|
14
14
|
- **Reduck v1.1**:发布 Reduck v1.1,使用文档全面更新。
|
15
15
|
|
16
16
|
## 支持 React 18
|
@@ -33,11 +33,11 @@ Modern.js 框架和相关插件完成对 React 18 的适配。现在,只需要
|
|
33
33
|
npx @modern-js/upgrade
|
34
34
|
```
|
35
35
|
|
36
|
-
##
|
36
|
+
## Modern.js Module 支持 bundle 构建
|
37
37
|
|
38
|
-
|
38
|
+
Modern.js Module 对底层实现进行重构,新增 [`output.buildConfig`](https://modernjs.dev/v1/docs/apis/module/config/output/build-config/) 配置,用于提供更加丰富的构建功能。
|
39
39
|
|
40
|
-
|
40
|
+
新的 Modern.js Module 项目,不仅支持对产物做 bundless 构建,也支持 bundle 构建。通过配置 `buildConfig` 下的 [`buildType`](https://modernjs.dev/v1/docs/apis/module/config/output/build-config/build-type) ,即可进行 bundle 构建:
|
41
41
|
|
42
42
|
```ts title="modern.config.ts"
|
43
43
|
import { defineConfig } from '@modern-js/module-tools';
|
@@ -80,7 +80,7 @@ Modern.js 7 ~ 8 月的最新版本为 v1.17.0,本双月的主要更新有:
|
|
80
80
|
|
81
81
|
- **支持 React 18**:完成框架和插件对 React 18 的适配。
|
82
82
|
- **包版本统一**:Modern.js 所有组成包的版本号进行统一,提供升级命令。
|
83
|
-
-
|
83
|
+
- **Modern.js Module 支持 bundle 构建**:Modern.js Module 项目,支持对产物做 bundle 构建。
|
84
84
|
- **Reduck v1.1**:发布 [Reduck v1.1](https://github.com/web-infra-dev/reduck),使用文档全面更新。
|
85
85
|
|
86
86
|
[了解更多 →](/community/blog/2022-0708-updates)
|
@@ -0,0 +1 @@
|
|
1
|
+
Modern.js 支持 [Express.js](https://expressjs.com/) 和 [Koa.js](https://koajs.com/) 作为可选的 BFF 运行时框架,请参考[「BFF - 运行时框架」](/guides/advanced-features/bff/frameworks.html)。
|
@@ -28,6 +28,8 @@ export default defineConfig({
|
|
28
28
|
- `mode`:`string = 'string'`,默认为使用 `renderToString` 渲染。配置为 `stream` 开启流式渲染。
|
29
29
|
- `forceCSR`:`boolean = false`,默认关闭强制 CSR 渲染。配置为 `true` 后,在页面访问时添加 `?csr=true` 或添加请求头 `x-modern-ssr-fallback` 即可强制 CSR。
|
30
30
|
- `inlineScript`:`boolean = true`,默认情况下,SSR 的数据会以内联脚本的方式注入到 HTML 中,并且直接赋值给全局变量。配置为 `false` 后,会下发 JSON,而不是赋值给全局变量。
|
31
|
+
- `disablePrerender`: `boolean = fasle`, 为了兼容旧数据请求方式 - `useLoader`, 默认情况下 Modern.js 会对组件进行一次预渲染即有两次渲染。
|
32
|
+
开发者在保证项目中没有使用 useLoader Api 情况下, 可通过配置 `disablePrerender=true`来减少一次渲染。
|
31
33
|
|
32
34
|
```ts title="modern.config.ts"
|
33
35
|
export default defineConfig({
|
@@ -36,6 +38,7 @@ export default defineConfig({
|
|
36
38
|
forceCSR: true,
|
37
39
|
mode: 'stream',
|
38
40
|
inlineScript: false,
|
41
|
+
disablePrerender: true,
|
39
42
|
},
|
40
43
|
},
|
41
44
|
});
|
@@ -4,64 +4,25 @@ sidebar_position: 3
|
|
4
4
|
|
5
5
|
# 路径别名
|
6
6
|
|
7
|
-
|
7
|
+
import Alias from '@modern-js/builder-doc/docs/zh/shared/alias';
|
8
8
|
|
9
|
-
|
10
|
-
{
|
11
|
-
'@': '<appDirectory>/src',
|
12
|
-
'@shared': '<appDirectory>/shared',
|
13
|
-
}
|
14
|
-
```
|
15
|
-
|
16
|
-
:::info
|
17
|
-
在开启可选功能时,new 命令也会动态的添加内置别名,例如启用 BFF 时默认会添加 `@api` 别名。
|
9
|
+
<Alias />
|
18
10
|
|
19
|
-
|
11
|
+
## 默认别名
|
20
12
|
|
21
|
-
|
22
|
-
|
23
|
-
```bash
|
24
|
-
.
|
25
|
-
├── common
|
26
|
-
│ ├── styles
|
27
|
-
│ │ └── base.css
|
28
|
-
│ └── utils
|
29
|
-
│ └── index.ts
|
30
|
-
└── App.tsx
|
31
|
-
```
|
32
|
-
|
33
|
-
`src/App.tsx` 中写法如下:
|
34
|
-
|
35
|
-
```ts
|
36
|
-
import utils from '@/src/common/utils';
|
37
|
-
import '@/src/common/styles/base.css';
|
38
|
-
```
|
39
|
-
|
40
|
-
Modern.js 也提供了自定义别名的方式,以添加 `@common` 别名为例:
|
41
|
-
|
42
|
-
对于 TypeScript 项目,只需要在项目根目录 `tsconfig.json` 下配置 `compilerOptions.paths`:
|
13
|
+
Modern.js 框架内置了以下别名:
|
43
14
|
|
44
15
|
```json
|
45
16
|
{
|
46
|
-
"
|
47
|
-
|
48
|
-
"@/*": ["./src/*"],
|
49
|
-
"@/common/*": ["./src/common/*"]
|
50
|
-
}
|
51
|
-
}
|
17
|
+
"@": "./src",
|
18
|
+
"@shared": "./shared"
|
52
19
|
}
|
53
20
|
```
|
54
21
|
|
55
|
-
|
22
|
+
此外,在启用框架的 BFF 插件时,默认会添加 `@api` 别名。
|
56
23
|
|
57
|
-
```
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
'@common': './src/common',
|
62
|
-
},
|
63
|
-
},
|
64
|
-
});
|
24
|
+
```json
|
25
|
+
{
|
26
|
+
"@api": "./api"
|
27
|
+
}
|
65
28
|
```
|
66
|
-
|
67
|
-
对于别名配置的具体用法,请参考 [source.alias 文档](/configure/app/source/alias)。
|
@@ -207,7 +207,7 @@ export default () => {
|
|
207
207
|
└── page.tsx
|
208
208
|
```
|
209
209
|
|
210
|
-
`routes/user/[id$]/page.tsx` 文件会转为 `/user/:id?` 路由。`/user` 下的所有路由都会匹配到该路由,并且 `id`
|
210
|
+
`routes/user/[id$]/page.tsx` 文件会转为 `/user/:id?` 路由。`/user` 下的所有路由都会匹配到该路由,并且 `id` 参数可选存在。通常在区分**创建**与**编辑**时,可以使用该路由。
|
211
211
|
|
212
212
|
在组件中,可以通过 [useParams](/apis/app/runtime/router/router#useparams) 获取对应命名的参数。
|
213
213
|
|
@@ -66,6 +66,26 @@ Modern.js 能为开发者提供极致的**开发体验(Development Experience
|
|
66
66
|
- 🌏 **周边生态**:自研状态管理、微前端、模块打包、Monorepo 方案等周边需求。
|
67
67
|
- 🕸 **多种路由模式**:包含自控路由、基于文件约定的路由(嵌套路由)等。
|
68
68
|
|
69
|
+
## 和其他框架的对比
|
70
|
+
|
71
|
+
### Next.js
|
72
|
+
|
73
|
+
Next.js 是社区中最流行的 React 框架之一,由 Vercel 开发。
|
74
|
+
|
75
|
+
Next.js 默认使用了 React Server Components,这意味着**你需要在服务端渲染你的 Web 应用,并为服务器产生的开销付费**;并且 Server Components 目前不是一项稳定的技术,社区中很多流行的 React 库尚未完成对 RSC 的适配。在目前阶段,你可能需要使用 Next.js 旧版的 Pages Router 来避免 Server Components 带来的问题。
|
76
|
+
|
77
|
+
当你想构建一个单页面应用(SPA),并通过客户端渲染时,Next.js 可能不是一个好的选择,因为它的很多功能都是围绕 Server 优先来设计的。如果你需要使用客户端渲染,只能通过 Next.js 提供的 "static exports" 来使用有限的功能。
|
78
|
+
|
79
|
+
而 Modern.js 将客户端渲染(CSR)和服务端渲染(SSR)视为同样重要的场景。当你创建一个 Modern.js 应用时,它默认是在客户端渲染的,你不需要了解 Server Components 的用法和局限性。你也可以在任何有需要的时候开启 SSR,甚至可以为一部分页面开启 SSR,整个过程是完全渐进式的。请注意,Modern.js 目前不支持 Server Components,我们会持续观察它的潜力,并在合适的时候支持它。
|
80
|
+
|
81
|
+
### Umi
|
82
|
+
|
83
|
+
Umi 是中文社区中非常流行的 React 框架,也是蚂蚁集团的底层前端框架。Modern.js 和 Umi 有许多相似之处,比如都支持插件系统、约定式路由、微生成器等。
|
84
|
+
|
85
|
+
**Modern.js 和 Umi 的主要区别在于构建优化方式不同**。Umi 采用了 MFSU 技术来提升构建速度,而 Modern.js 则使用 Rspack 来提升 5 ~ 10 倍构建速度。在我们看来,类似 Rspack 这样的 Rust 工具更符合前端工具链的长期发展趋势,它可以在性能、稳定性和生态兼容性之间取得较好的平衡。
|
86
|
+
|
87
|
+
此外,Modern.js 的服务端能力更加丰富,包括完备的 SSR 能力、一体化 BFF 开发能力和自定义 Web Server 支持。这些能力经过了字节跳动大量线上应用的验证,可以直接用于生产环境。
|
88
|
+
|
69
89
|
## 下一步
|
70
90
|
|
71
91
|
如果你希望了解如何使用 Modern.js 框架,可以尝试 [创建第一个应用](/tutorials/first-app/c01-start),或是阅读 [快速上手](/guides/get-started/quick-start)。
|
@@ -0,0 +1,138 @@
|
|
1
|
+
---
|
2
|
+
sidebar_position: 4
|
3
|
+
---
|
4
|
+
|
5
|
+
# 技术栈
|
6
|
+
|
7
|
+
Modern.js 框架默认集成了一些社区中流行的库和开发工具。
|
8
|
+
|
9
|
+
在这篇文档中,你可以了解到 Modern.js 框架涉及的主要技术栈,以及一些可选的库和工具。
|
10
|
+
|
11
|
+
---
|
12
|
+
|
13
|
+
## UI 库
|
14
|
+
|
15
|
+
Modern.js 使用 [React 18](https://react.dev/) 来构建用户界面,同时也兼容 React 17。
|
16
|
+
|
17
|
+
Modern.js 底层的 Builder 也支持构建 Vue 应用,如果你需要使用 Vue,可以参考[「构建 Vue 应用」](https://modernjs.dev/builder/guide/framework/vue3.html)。
|
18
|
+
|
19
|
+
---
|
20
|
+
|
21
|
+
## 路由
|
22
|
+
|
23
|
+
Modern.js 的路由基于 [React Router 6](https://reactrouter.com/en/main),同时也兼容 React Router 5。
|
24
|
+
|
25
|
+
Modern.js 支持约定式路由、自控式路由或其他路由方案,请参考[「路由方案」](/guides/basic-features/routes) 进行选择。
|
26
|
+
|
27
|
+
---
|
28
|
+
|
29
|
+
## 微前端
|
30
|
+
|
31
|
+
Modern.js 提供对 [Garfish](https://www.garfishjs.org/) 微前端框架开箱即用的支持。
|
32
|
+
|
33
|
+
同时,我们也正在与 [Module Federation](https://webpack.js.org/concepts/module-federation/) 的作者 Zack Jackson 合作,以提供更完整的解决方案。
|
34
|
+
|
35
|
+
---
|
36
|
+
|
37
|
+
## 状态管理
|
38
|
+
|
39
|
+
Modern.js 可以与社区中任意的状态管理库搭配使用,比如 [Redux](https://redux.js.org/)、[Jotai](https://jotai.org/)、[Zustand](https://docs.pmnd.rs/zustand)、[Valtio](https://valtio.pmnd.rs/) 等。
|
40
|
+
|
41
|
+
Modern.js 也基于 Redux 封装了 Reduck 状态管理库,你可以参考 [「Reduck 状态管理」](/guides/topic-detail/model/quick-start)来使用。
|
42
|
+
|
43
|
+
---
|
44
|
+
|
45
|
+
## 包管理器
|
46
|
+
|
47
|
+
Modern.js 可以与社区中任意的包管理器搭配使用,比如 [npm](https://www.npmjs.com/package/npm)、[yarn](https://classic.yarnpkg.com/lang/en/)、[pnpm](https://pnpm.io/) 或 [Bun](https://bun.sh/)。
|
48
|
+
|
49
|
+
我们推荐使用 pnpm 来获得更快的安装速度。
|
50
|
+
|
51
|
+
---
|
52
|
+
|
53
|
+
## 打包工具
|
54
|
+
|
55
|
+
Modern.js 使用 [Webpack 5](https://webpack.js.org/) 或 [Rspack](https://www.rspack.dev/) 来打包你的 Web 应用。
|
56
|
+
|
57
|
+
默认使用的打包工具为 Webpack 5,你可以参考[「使用 Rspack」](/guides/advanced-features/rspack-start) 来切换到更快的 Rspack。
|
58
|
+
|
59
|
+
---
|
60
|
+
|
61
|
+
## 转译工具
|
62
|
+
|
63
|
+
Modern.js 使用 [Babel](https://babeljs.io/)、[SWC](https://swc.rs/) 或 [esbuild](https://esbuild.github.io/) 作为 JS 转译工具,将 TypeScript 或 JSX 转义为可以在浏览器上运行的 JavaScript 代码,并进行语法降级。
|
64
|
+
|
65
|
+
- 使用 Webpack 打包时,默认为 Babel,支持切换到 SWC 或 esbuild。
|
66
|
+
- 使用 Rspack 打包时,默认为 SWC,支持切换到 Babel。
|
67
|
+
|
68
|
+
---
|
69
|
+
|
70
|
+
## 压缩工具
|
71
|
+
|
72
|
+
在生产环境构建时,Modern.js 使用 [Terser](https://github.com/terser/terser)、[SWC](https://swc.rs/) 或 [esbuild](https://esbuild.github.io/) 来压缩 JavaScript 代码,使用 [cssnano](https://cssnano.co/) 来压缩 CSS 代码。
|
73
|
+
|
74
|
+
- 使用 Webpack 打包时,默认使用 Terser 压缩 JS 代码,支持切换到 SWC 或 esbuild。
|
75
|
+
- 使用 Rspack 打包时,默认使用 SWC 压缩 JS 代码,暂不支持切换到其他工具。
|
76
|
+
|
77
|
+
---
|
78
|
+
|
79
|
+
## CSS 转换
|
80
|
+
|
81
|
+
Modern.js 使用 [PostCSS](https://postcss.org/) 来转换 CSS 代码,并默认开启 [autoprefixer](https://github.com/postcss/autoprefixer) 来补全 CSS 前缀。
|
82
|
+
|
83
|
+
Modern.js 支持[「启用 Tailwind CSS」](/guides/basic-features/css.html#使用-tailwind-css),并同时兼容 Tailwind CSS v2 和 v3 版本。
|
84
|
+
|
85
|
+
---
|
86
|
+
|
87
|
+
## CSS 预处理器
|
88
|
+
|
89
|
+
Modern.js 支持 [Sass](https://sass-lang.com/)、[Less](https://lesscss.org/) 和 [Stylus](https://stylus-lang.com/) 三种 CSS 预处理器:
|
90
|
+
|
91
|
+
- 默认支持 Sass 和 Less,开箱即用。
|
92
|
+
- 可选支持 Stylus,请参考[「Stylus 插件」](https://modernjs.dev/builder/plugins/plugin-stylus.html) 来使用。
|
93
|
+
|
94
|
+
---
|
95
|
+
|
96
|
+
## CSS Modules
|
97
|
+
|
98
|
+
Modern.js 对 [CSS Modules](https://github.com/css-modules/css-modules) 提供了开箱即用的支持,内部基于 [css-loader](https://www.npmjs.com/package/css-loader) 实现。
|
99
|
+
|
100
|
+
请参考[「使用 CSS Modules」](https://modernjs.dev/builder/guide/basic/css-modules.html) 来使用。
|
101
|
+
|
102
|
+
---
|
103
|
+
|
104
|
+
## CSS-in-JS
|
105
|
+
|
106
|
+
Modern.js 支持使用 [styled-components](https://styled-components.com/),请参考[「使用 CSS-in-JS」](/guides/basic-features/css.html#使用-css-in-js) 来使用。
|
107
|
+
|
108
|
+
如果你需要使用其他 CSS-in-JS 方案,可以自行集成到你的项目中。
|
109
|
+
|
110
|
+
---
|
111
|
+
|
112
|
+
## 测试框架
|
113
|
+
|
114
|
+
Modern.js 支持使用 [Jest](https://jestjs.io/) 进行单元测试或集成测试。该功能为可选功能,请参考[「使用 Jest 测试」](/guides/advanced-features/testing) 启用。
|
115
|
+
|
116
|
+
如果你需要使用 [Vitest](https://vitest.dev/) 或其他测试框架,可以自行集成到你的项目中。
|
117
|
+
|
118
|
+
---
|
119
|
+
|
120
|
+
## 组件库
|
121
|
+
|
122
|
+
Modern.js 可以与社区中任意的 React 组件库搭配使用,比如 [MUI](https://mui.com/)、[Ant Design](https://ant.design/)、[Arco Design](https://github.com/arco-design/arco-design)、[Semi Design](https://semi.design/)、[Radix UI](https://www.radix-ui.com/) 等。
|
123
|
+
|
124
|
+
同时,Modern.js 内置了对 Ant Design 和 Arco Design 的 [按需引入](/configure/app/source/transform-import) 支持。
|
125
|
+
|
126
|
+
---
|
127
|
+
|
128
|
+
## 组件开发
|
129
|
+
|
130
|
+
Modern.js 支持使用 [Storybook](https://storybook.js.org/) 来开发 UI 组件。该功能为可选功能,请参考[「使用 Storybook」](/guides/advanced-features/using-storybook) 启用。
|
131
|
+
|
132
|
+
---
|
133
|
+
|
134
|
+
## Node.js 框架
|
135
|
+
|
136
|
+
import TechStackNodeFramework from '@site-docs/components/tech-stack-node-framework';
|
137
|
+
|
138
|
+
<TechStackNodeFramework />
|
@@ -160,11 +160,11 @@ module.exports = {
|
|
160
160
|
}
|
161
161
|
```
|
162
162
|
|
163
|
-
###
|
163
|
+
### 使用 Modern.js Module
|
164
164
|
|
165
|
-
自定义 changelog
|
165
|
+
自定义 changelog 还可以使用 Modern.js Module 方案进行管理,提供通用方案。
|
166
166
|
|
167
|
-
#### 使用 `npx @modern-js/create@latest`
|
167
|
+
#### 使用 `npx @modern-js/create@latest` 创建 Modern.js Module
|
168
168
|
|
169
169
|
```md
|
170
170
|
? 请选择你想创建的工程类型:Npm 模块
|
@@ -191,11 +191,11 @@ commit 配置为 ./my-commit-config.js 即可:
|
|
191
191
|
}
|
192
192
|
```
|
193
193
|
|
194
|
-
###
|
194
|
+
### 使用 Modern.js Module
|
195
195
|
|
196
|
-
自定义 commit
|
196
|
+
自定义 commit 还可以使用 Modern.js Module 进行管理,提供通用方案。
|
197
197
|
|
198
|
-
#### 使用 `npx @modern-js/create@latest`
|
198
|
+
#### 使用 `npx @modern-js/create@latest` 创建 Modern.js Module
|
199
199
|
|
200
200
|
```md
|
201
201
|
? 请选择你想创建的工程类型:Npm 模块
|
@@ -204,11 +204,11 @@ pnpm run gen-release-note --custom ./scripts/my-release-note-config.js
|
|
204
204
|
|
205
205
|
直接执行命令 `pnpm run gen-release-note` 即可。
|
206
206
|
|
207
|
-
###
|
207
|
+
### 使用 Modern.js Module
|
208
208
|
|
209
|
-
custom
|
209
|
+
custom 参数值还可以使用 Modern.js Module 进行管理,提供通用方案。
|
210
210
|
|
211
|
-
#### 使用 `npx @modern-js/create@latest`
|
211
|
+
#### 使用 `npx @modern-js/create@latest` 创建 Modern.js Module
|
212
212
|
|
213
213
|
```md
|
214
214
|
? 请选择你想创建的工程类型:Npm 模块
|
@@ -36,13 +36,13 @@ const myPlugin = {
|
|
36
36
|
|
37
37
|
### 插件类型
|
38
38
|
|
39
|
-
Modern
|
39
|
+
Modern.js 支持多种工程开发,如应用开发(Modern.js Framework), 模块开发(Modern.js Module)等。
|
40
40
|
|
41
|
-
为了兼顾不同工程开发的差异和通性,Modern
|
41
|
+
为了兼顾不同工程开发的差异和通性,Modern.js 将插件如下图进行组织:
|
42
42
|
|
43
43
|

|
44
44
|
|
45
|
-
从图可以看出,Modern
|
45
|
+
从图可以看出,Modern.js 将插件大致分为两类:
|
46
46
|
|
47
47
|
1. 通用插件: 插件只会包含一些基础的 Hooks
|
48
48
|
|
@@ -210,9 +210,9 @@ export default defineConfig({
|
|
210
210
|
|
211
211
|
### 在 npm 上发布插件
|
212
212
|
|
213
|
-
|
213
|
+
如果你需要将 Modern.js 插件发布到 npm,推荐使用 [Modern.js Module](https://modernjs.dev/module-tools) 来管理和构建。
|
214
214
|
|
215
|
-
|
215
|
+
首先创建一个空的 Modern.js Module 项目,调整 npm 包名称:
|
216
216
|
|
217
217
|
```json
|
218
218
|
{
|