@modern-js/main-doc 2.33.1 → 2.35.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. package/docs/en/apis/app/hooks/config/public.mdx +2 -2
  2. package/docs/en/apis/app/hooks/config/upload.mdx +3 -3
  3. package/docs/en/components/tech-stack-node-framework.mdx +1 -0
  4. package/docs/en/configure/app/server/ssr.mdx +2 -0
  5. package/docs/en/configure/app/source/config-dir.mdx +2 -2
  6. package/docs/en/guides/advanced-features/eslint.mdx +1 -1
  7. package/docs/en/guides/basic-features/alias.mdx +11 -50
  8. package/docs/en/guides/basic-features/env-vars.mdx +1 -1
  9. package/docs/en/guides/basic-features/routes.mdx +4 -4
  10. package/docs/en/guides/concept/builder.mdx +1 -1
  11. package/docs/en/guides/get-started/glossary.mdx +1 -1
  12. package/docs/en/guides/get-started/introduction.mdx +21 -1
  13. package/docs/en/guides/get-started/tech-stack.mdx +138 -0
  14. package/docs/en/guides/topic-detail/changesets/add.mdx +1 -1
  15. package/docs/en/guides/topic-detail/changesets/changelog.mdx +3 -3
  16. package/docs/en/guides/topic-detail/changesets/commit.mdx +3 -3
  17. package/docs/en/guides/topic-detail/changesets/release-note.mdx +3 -3
  18. package/docs/en/guides/topic-detail/changesets/release.mdx +1 -1
  19. package/docs/en/guides/topic-detail/framework-plugin/implement.mdx +4 -4
  20. package/docs/en/guides/topic-detail/generator/create/use.mdx +1 -9
  21. package/docs/en/guides/topic-detail/generator/plugin/context.md +1 -1
  22. package/docs/en/tutorials/examples/_category_.json +5 -0
  23. package/docs/en/tutorials/examples/csr-auth.mdx +214 -0
  24. package/docs/en/tutorials/foundations/introduction.mdx +10 -1
  25. package/docs/zh/community/blog/2022-0708-updates.md +4 -4
  26. package/docs/zh/community/blog/overview.md +1 -1
  27. package/docs/zh/components/tech-stack-node-framework.mdx +1 -0
  28. package/docs/zh/configure/app/server/ssr.mdx +3 -0
  29. package/docs/zh/guides/advanced-features/eslint.mdx +1 -1
  30. package/docs/zh/guides/basic-features/alias.mdx +11 -50
  31. package/docs/zh/guides/basic-features/routes.mdx +1 -1
  32. package/docs/zh/guides/get-started/introduction.mdx +20 -0
  33. package/docs/zh/guides/get-started/tech-stack.mdx +138 -0
  34. package/docs/zh/guides/topic-detail/changesets/add.mdx +1 -1
  35. package/docs/zh/guides/topic-detail/changesets/changelog.mdx +3 -3
  36. package/docs/zh/guides/topic-detail/changesets/commit.mdx +3 -3
  37. package/docs/zh/guides/topic-detail/changesets/release-note.mdx +3 -3
  38. package/docs/zh/guides/topic-detail/changesets/release.mdx +1 -1
  39. package/docs/zh/guides/topic-detail/framework-plugin/implement.mdx +5 -5
  40. package/docs/zh/guides/topic-detail/generator/create/use.mdx +0 -8
  41. package/docs/zh/guides/topic-detail/generator/plugin/context.md +1 -1
  42. package/docs/zh/tutorials/examples/_category_.json +5 -0
  43. package/docs/zh/tutorials/examples/csr-auth.mdx +214 -0
  44. package/docs/zh/tutorials/foundations/introduction.mdx +8 -0
  45. package/package.json +8 -5
  46. package/src/components/Sandpack/index.css +10 -0
  47. package/src/components/Sandpack/index.tsx +30 -0
@@ -26,7 +26,7 @@ export default function (context: IPluginContext) {
26
26
 
27
27
  ## 自定义 Input
28
28
 
29
- Modern.js Web 应用和 Npm 模块工程方案都存在一些默认的 Input 交互,使用这里的 API 可以对这些 Input 进行添加、修改、隐藏、提供默认值等操作。
29
+ Modern.js Framework Modern.js Module 都存在一些默认的 Input 交互,使用这里的 API 可以对这些 Input 进行添加、修改、隐藏、提供默认值等操作。
30
30
 
31
31
  例如:
32
32
 
@@ -0,0 +1,5 @@
1
+ {
2
+ "label": "案例",
3
+ "position": 3,
4
+ "collapsed": false
5
+ }
@@ -0,0 +1,214 @@
1
+ ---
2
+ title: 路由鉴权
3
+ ---
4
+
5
+ # 路由鉴权
6
+
7
+ Modern.js 默认提供的路由方式是基于 React Router 6 的约定式路由,具体可查看[路由方案](/guides/basic-features/routes.html#路由方案)。
8
+
9
+ 在一个 Web 应用中如果存在多个路由,我们可能需要对部分路由进行鉴权后才能访问。例如下面这个案例:
10
+
11
+ - 访问 `/` 路由,无需鉴权,可直接访问。
12
+ - 访问 `/protected` 路由,需要鉴权,如果无,自动跳转到 `/login` 路由,登录成功后返回 `/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>
@@ -27,4 +27,12 @@ sidebar_position: 1
27
27
  - 新建入口
28
28
  - ...
29
29
 
30
+ ## 案例
31
+
32
+ 我们提供了一些在开发过程中常用的案例供你参考,可以在这里找到 Modern.js 提供的一些功能组合的使用方式,我们将持续完善这里的案例。
33
+
34
+ - [路由鉴权](/tutorials/examples/csr-auth.html)
35
+ - ...
36
+
30
37
  下面就让我们从 [创建项目](tutorials/first-app/c01-start) 开始吧!
38
+
package/package.json CHANGED
@@ -15,14 +15,17 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.33.1",
18
+ "version": "2.35.0",
19
19
  "publishConfig": {
20
20
  "registry": "https://registry.npmjs.org/",
21
21
  "access": "public",
22
22
  "provenance": true
23
23
  },
24
+ "dependencies": {
25
+ "@modern-js/sandpack-react": "2.35.0"
26
+ },
24
27
  "peerDependencies": {
25
- "@modern-js/builder-doc": "^2.33.1"
28
+ "@modern-js/builder-doc": "^2.35.0"
26
29
  },
27
30
  "devDependencies": {
28
31
  "classnames": "^2",
@@ -32,12 +35,12 @@
32
35
  "ts-node": "^10.9.1",
33
36
  "typescript": "^5",
34
37
  "fs-extra": "^10",
35
- "rspress": "0.0.6",
38
+ "rspress": "0.0.10",
36
39
  "@rspress/shared": "0.0.6",
37
40
  "@types/node": "^16",
38
41
  "@types/fs-extra": "^9",
39
- "@modern-js/builder-doc": "2.33.1",
40
- "@modern-js/doc-plugin-auto-sidebar": "2.33.1"
42
+ "@modern-js/builder-doc": "2.35.0",
43
+ "@modern-js/doc-plugin-auto-sidebar": "2.35.0"
41
44
  },
42
45
  "scripts": {
43
46
  "dev": "rspress dev",
@@ -0,0 +1,10 @@
1
+ .light {
2
+ --sp-layout-height: 500px !important;
3
+ }
4
+
5
+ .dark {
6
+ --sp-layout-height: 500px !important;
7
+ }
8
+ .sp-read-only {
9
+ display: none;
10
+ }
@@ -0,0 +1,30 @@
1
+ import ModernSandpack, { ModernSandpackProps } from '@modern-js/sandpack-react';
2
+ import React, { PropsWithChildren } from 'react';
3
+ import { useDark, NoSSR } from 'rspress/runtime';
4
+
5
+ import './index.css';
6
+
7
+ const Sandpack = (props: PropsWithChildren<ModernSandpackProps>) => {
8
+ const dark = useDark();
9
+ const { children, ...otherProps } = props;
10
+ const files: Record<string, string> = {};
11
+ React.Children.forEach(children, (child: any) => {
12
+ if (child) {
13
+ const { meta, children } = child.props.children.props;
14
+ const matches = meta.match(/title="(.*)"/);
15
+ if (matches.length > 1) {
16
+ files[matches[1]] = children;
17
+ }
18
+ }
19
+ });
20
+ return (
21
+ <NoSSR>
22
+ <ModernSandpack
23
+ files={files}
24
+ theme={dark ? 'dark' : 'light'}
25
+ {...otherProps}
26
+ />
27
+ </NoSSR>
28
+ );
29
+ };
30
+ export default Sandpack;