@qlover/create-app 0.6.1 → 0.6.3

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/templates/react-app/README.en.md +257 -0
  5. package/dist/templates/react-app/README.md +29 -231
  6. package/dist/templates/react-app/config/IOCIdentifier.ts +13 -0
  7. package/dist/templates/react-app/docs/en/bootstrap.md +562 -0
  8. package/dist/templates/react-app/docs/en/development-guide.md +523 -0
  9. package/dist/templates/react-app/docs/en/env.md +482 -0
  10. package/dist/templates/react-app/docs/en/global.md +509 -0
  11. package/dist/templates/react-app/docs/en/i18n.md +268 -0
  12. package/dist/templates/react-app/docs/en/index.md +173 -0
  13. package/dist/templates/react-app/docs/en/ioc.md +424 -0
  14. package/dist/templates/react-app/docs/en/project-structure.md +434 -0
  15. package/dist/templates/react-app/docs/en/request.md +425 -0
  16. package/dist/templates/react-app/docs/en/router.md +404 -0
  17. package/dist/templates/react-app/docs/en/store.md +321 -0
  18. package/dist/templates/react-app/docs/en/theme.md +424 -0
  19. package/dist/templates/react-app/docs/en/typescript-guide.md +473 -0
  20. package/dist/templates/react-app/docs/zh/bootstrap.md +562 -0
  21. package/dist/templates/react-app/docs/zh/development-guide.md +523 -0
  22. package/dist/templates/react-app/docs/zh/env.md +479 -0
  23. package/dist/templates/react-app/docs/zh/global.md +511 -0
  24. package/dist/templates/react-app/docs/zh/i18n.md +268 -0
  25. package/dist/templates/react-app/docs/zh/index.md +173 -0
  26. package/dist/templates/react-app/docs/zh/ioc.md +422 -0
  27. package/dist/templates/react-app/docs/zh/project-structure.md +434 -0
  28. package/dist/templates/react-app/docs/zh/request.md +429 -0
  29. package/dist/templates/react-app/docs/zh/router.md +408 -0
  30. package/dist/templates/react-app/docs/zh/store.md +321 -0
  31. package/dist/templates/react-app/docs/zh/theme.md +424 -0
  32. package/dist/templates/react-app/docs/zh/typescript-guide.md +473 -0
  33. package/dist/templates/react-app/package.json +2 -2
  34. package/dist/templates/react-app/src/base/apis/AiApi.ts +10 -5
  35. package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +1 -1
  36. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +1 -1
  37. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +10 -17
  38. package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +1 -1
  39. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +2 -1
  40. package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +7 -5
  41. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +3 -2
  42. package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +33 -0
  43. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +1 -1
  44. package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
  45. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +1 -1
  46. package/dist/templates/react-app/src/base/services/RouteService.ts +5 -2
  47. package/dist/templates/react-app/src/base/services/UserService.ts +8 -10
  48. package/dist/templates/react-app/src/core/IOC.ts +73 -83
  49. package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +52 -4
  50. package/dist/templates/react-app/src/core/bootstraps/{index.ts → BootstrapsRegistry.ts} +2 -3
  51. package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +25 -0
  52. package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +11 -17
  53. package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +10 -4
  54. package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +6 -15
  55. package/dist/templates/react-app/src/main.tsx +2 -5
  56. package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +3 -1
  57. package/dist/templates/react-app/src/styles/css/antd-themes/index.css +1 -1
  58. package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +6 -1
  59. package/dist/templates/react-app/src/styles/css/page.css +1 -1
  60. package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +1 -1
  61. package/dist/templates/react-app/tsconfig.app.json +2 -1
  62. package/dist/templates/react-app/tsconfig.node.json +2 -1
  63. package/package.json +2 -2
  64. package/dist/templates/react-app/src/base/port/ApiTransactionInterface.ts +0 -7
  65. package/dist/templates/react-app/src/base/port/RequestCatcherInterface.ts +0 -12
  66. package/dist/templates/react-app/src/core/bootstrap.ts +0 -58
  67. package/dist/templates/react-app/src/core/registers/RegisterApi.ts +0 -5
  68. package/dist/templates/react-app/src/core/registers/index.ts +0 -32
@@ -0,0 +1,562 @@
1
+ ## 项目启动指南
2
+
3
+ ### 什么是 Bootstrap?
4
+
5
+ Bootstrap 是一个应用启动器,它帮助我们在应用启动时统一管理各种初始化逻辑。
6
+
7
+ **简单来说**:就像电脑开机时需要启动各种服务一样,我们的应用也需要在启动时做一些准备工作,比如:
8
+
9
+ - 检查用户是否登录
10
+ - 加载用户信息
11
+ - 初始化 API 配置
12
+ - 设置主题、语言等
13
+
14
+ 文件路径: src/core/bootstraps
15
+
16
+ ### 项目中的实现
17
+
18
+ 该项目基于 `@qlover/fe-corekit` 的 AsyncExecutor 异步执行器,`corekit-bridge` 在此基础上实现了 Bootstrap。
19
+
20
+ **文件入口**:`src/core/bootstraps/BootstrapApp.ts`
21
+
22
+ **主要组成部分**:
23
+
24
+ 1. [IOC 容器](./ioc.md) - 依赖注入管理
25
+ 2. [环境变量的注入](./env.md) - 配置管理
26
+ 3. [浏览器全局变量的注入](./global.md) - 浏览器全局属性
27
+
28
+ ### 什么时候需要使用 Bootstrap?
29
+
30
+ 当你遇到以下情况时,Bootstrap 就能派上用场:
31
+
32
+ ### 为什么需要"启动器"
33
+
34
+ **核心目标**:让应用启动更简洁,业务逻辑更清晰。
35
+
36
+ **解决的问题**:当页面打开时,你需要鉴权,或者请求某个 API,数据才能进入页面,这个时候你可能会这样做
37
+
38
+ ```tsx
39
+ export function App() {
40
+ const [loading, setLoading] = useState(false);
41
+
42
+ useEffect(() => {
43
+ setLoading(true);
44
+
45
+ fetchUserInfo()
46
+ .then(() => {
47
+ setLoading(false);
48
+ })
49
+ .catch(() => {
50
+ setLoading(false);
51
+ });
52
+ }, []);
53
+
54
+ if (loading) {
55
+ return <div>loading ...</div>;
56
+ }
57
+
58
+ return <Router></Router>;
59
+ }
60
+ ```
61
+
62
+ 这段代码执行起来没有什么问题,关键的问题在于,他会和组件强耦合在一起!也就是说当 fetchUserInfo 成功后更新局部状态,然后渲染 Router
63
+
64
+ 但是如果,进入 Router 的逻辑变得复杂,依赖各种情况的时候,组件会变成非常臃肿且难以维护
65
+
66
+ 就比如下面情况:
67
+
68
+ 当路由是 /home 时请求用户信息,成功后,如果用户信息 roles 有权限则进入,否则跳转到 /login
69
+
70
+ ```tsx
71
+ export function App() {
72
+ const [loading, setLoading] = useState(false);
73
+ const [userInfo, setUserInfo] = useState(null);
74
+ const [hasPermission, setHasPermission] = useState(false);
75
+ const location = useLocation();
76
+
77
+ useEffect(() => {
78
+ setLoading(true);
79
+
80
+ // 检查当前路由
81
+ if (location.pathname === '/home') {
82
+ fetchUserInfo()
83
+ .then((user) => {
84
+ setUserInfo(user);
85
+
86
+ // 检查用户权限
87
+ if (user.roles && user.roles.includes('admin')) {
88
+ setHasPermission(true);
89
+ setLoading(false);
90
+ } else {
91
+ // 没有权限,跳转到登录页
92
+ window.location.href = '/login';
93
+ }
94
+ })
95
+ .catch((error) => {
96
+ console.error('Failed to fetch user info:', error);
97
+ // 请求失败也跳转到登录页
98
+ window.location.href = '/login';
99
+ });
100
+ } else {
101
+ setLoading(false);
102
+ }
103
+ }, [location.pathname]);
104
+
105
+ // 如果正在加载,显示加载状态
106
+ if (loading) {
107
+ return <div>Loading...</div>;
108
+ }
109
+
110
+ // 如果是 home 页面但没有权限,显示错误信息
111
+ if (location.pathname === '/home' && !hasPermission) {
112
+ return <div>Access denied</div>;
113
+ }
114
+
115
+ return <Router />;
116
+ }
117
+ ```
118
+
119
+ 这个示例展示了几个问题:
120
+
121
+ 1. **组件职责过重**:App 组件不仅要处理路由,还要处理用户认证、权限检查、错误处理等
122
+ 2. **状态管理复杂**:需要管理 loading、userInfo、hasPermission 等多个状态
123
+ 3. **逻辑耦合**:认证逻辑与组件渲染逻辑混在一起
124
+ 4. **难以测试**:组件包含了太多业务逻辑,难以进行单元测试
125
+ 5. **难以扩展**:如果后续需要添加更多权限检查或认证逻辑,组件会变得更加臃肿
126
+
127
+ 这些问题会再项目迭代后一步一步将问题放大,直到你开始重构代码!
128
+
129
+ ### 启动器是什么?
130
+
131
+ 启动器(Bootstrap)是一个在 UI 层运行的前置逻辑处理器,它的核心作用是:
132
+
133
+ 1. **前置逻辑处理**:在应用渲染之前,执行必要的初始化逻辑
134
+ 2. **状态管理**:通过 store 来管理应用状态,实现 UI 的响应式更新
135
+ 3. **关注点分离**:将业务逻辑从 UI 组件中分离出来
136
+
137
+ #### 核心特性
138
+
139
+ - **异步执行**:基于 AsyncExecutor 实现异步逻辑处理
140
+ - **状态驱动**:通过 store 状态变化来触发 UI 更新
141
+ - **模块化**:支持 IOC 容器、环境变量注入、全局变量注入等模块
142
+
143
+ #### 工作流程
144
+
145
+ ```
146
+ 应用启动 → Bootstrap 初始化 → 执行前置逻辑 → 更新 Store → UI 响应更新
147
+ ```
148
+
149
+ #### 与传统方式的对比
150
+
151
+ **传统方式**:
152
+
153
+ ```tsx
154
+ // 组件中混合业务逻辑
155
+ function App() {
156
+ const [loading, setLoading] = useState(true);
157
+ const [data, setData] = useState(null);
158
+
159
+ useEffect(() => {
160
+ // 业务逻辑混在组件中
161
+ fetchData()
162
+ .then(setData)
163
+ .finally(() => setLoading(false));
164
+ }, []);
165
+
166
+ if (loading) return <Loading />;
167
+ return <MainContent data={data} />;
168
+ }
169
+ ```
170
+
171
+ **使用启动器**:
172
+
173
+ ```tsx
174
+ // 组件只关注渲染
175
+ function App() {
176
+ const { loading, data } = useStore(); // 从 store 获取状态
177
+
178
+ if (loading) return <Loading />;
179
+ return <MainContent data={data} />;
180
+ }
181
+
182
+ // 业务逻辑在启动器中处理
183
+ const bootstrap = new Bootstrap({
184
+ root: window,
185
+ logger,
186
+ ioc: {
187
+ manager: IOC,
188
+ register: new IocRegisterImpl({ pathname, appConfig })
189
+ },
190
+ envOptions: {
191
+ target: appConfig,
192
+ source: import.meta.env,
193
+ prefix: 'APP_'
194
+ },
195
+ globalOptions: {
196
+ sources: globals,
197
+ target: 'AppGlobals'
198
+ }
199
+ });
200
+
201
+ // 注册业务逻辑插件
202
+ bootstrap.use([
203
+ IOC(UserService), // 用户认证服务
204
+ new UserApiBootstarp(), // 用户 API 配置
205
+ new FeApiBootstarp() // 其他 API 配置
206
+ ]);
207
+
208
+ // 启动应用
209
+ await bootstrap.initialize();
210
+ await bootstrap.start();
211
+ ```
212
+
213
+ **对比结果**:
214
+
215
+ - ✅ 组件变得简洁,只负责渲染
216
+ - ✅ 业务逻辑被分离到启动器中
217
+ - ✅ 可以独立测试业务逻辑
218
+ - ✅ 可以复用业务逻辑到其他 UI 框架
219
+
220
+ **完整的用户认证示例**:
221
+
222
+ ```tsx
223
+ // 1. 定义用户 API 插件(配置 API 请求)
224
+ export class UserApiBootstarp implements BootstrapExecutorPlugin {
225
+ readonly pluginName = 'UserApiBootstarp';
226
+
227
+ onBefore({ parameters: { ioc } }: BootstrapContext): void {
228
+ // 配置用户 API 的插件
229
+ ioc
230
+ .get<UserApi>(UserApi)
231
+ .usePlugin(new FetchURLPlugin())
232
+ .usePlugin(IOC.get(IOCIdentifier.ApiMockPlugin))
233
+ .usePlugin(IOC.get(RequestLogger));
234
+ }
235
+ }
236
+
237
+ // 2. 定义用户服务(处理用户认证逻辑)
238
+ @injectable()
239
+ export class UserService
240
+ extends UserAuthService<UserInfo>
241
+ implements ExecutorPlugin
242
+ {
243
+ readonly pluginName = 'UserService';
244
+
245
+ constructor(
246
+ @inject(UserApi) userApi: UserAuthApiInterface<UserInfo>,
247
+ @inject(IOCIdentifier.AppConfig) appConfig: AppConfig
248
+ ) {
249
+ super(userApi, {
250
+ userStorage: {
251
+ key: appConfig.userInfoStorageKey,
252
+ storage: storage
253
+ },
254
+ credentialStorage: {
255
+ key: appConfig.userTokenStorageKey,
256
+ storage: storage
257
+ }
258
+ });
259
+ }
260
+
261
+ // 在启动前检查用户认证状态
262
+ async onBefore(): Promise<void> {
263
+ if (this.isAuthenticated()) {
264
+ return;
265
+ }
266
+
267
+ const userToken = this.getToken();
268
+ if (!userToken) {
269
+ throw new AppError('NO_USER_TOKEN');
270
+ }
271
+
272
+ await this.userInfo();
273
+ this.store.authSuccess();
274
+ }
275
+ }
276
+
277
+ // 3. 在启动器中注册
278
+ const bootstrap = new Bootstrap({
279
+ root: window,
280
+ logger,
281
+ ioc: { manager: IOC, register: new IocRegisterImpl({ pathname, appConfig }) },
282
+ envOptions: { target: appConfig, source: import.meta.env, prefix: 'APP_' },
283
+ globalOptions: { sources: globals, target: 'AppGlobals' }
284
+ });
285
+
286
+ // 注册用户认证相关插件
287
+ bootstrap.use([
288
+ IOC(UserService), // 用户认证服务
289
+ new UserApiBootstarp(), // 用户 API 配置
290
+ IOC(I18nService) // 国际化服务
291
+ ]);
292
+
293
+ // 4. 启动应用
294
+ await bootstrap.initialize();
295
+ await bootstrap.start();
296
+ ```
297
+
298
+ **关键点**:
299
+
300
+ - `UserApiBootstarp`:负责配置 API 请求
301
+ - `UserService`:负责处理用户认证逻辑
302
+ - `Bootstrap`:统一管理所有插件
303
+ - 组件:只负责 UI 渲染
304
+
305
+ 并且最关键的是,ui 和 逻辑可以独立存在,也就是说你可以根据这个逻辑实现多个不同的 UI
306
+
307
+ **可能你觉得使用class,对象来处理多此一举,但论软件设计,项目长远考虑,过去几十年发展时间已经告诉我们,这样是最容易让开发者理解和多人协作的模式**
308
+
309
+ ### 启动器的优势
310
+
311
+ #### 1. **可测试性**
312
+
313
+ ```tsx
314
+ // 可以独立测试业务逻辑
315
+ describe('UserService', () => {
316
+ it('should authenticate user successfully', async () => {
317
+ const userService = new UserService(mockUserApi, mockAppConfig);
318
+ const result = await userService.onBefore();
319
+ expect(result).toBeDefined();
320
+ });
321
+ });
322
+ ```
323
+
324
+ #### 2. **可复用性**
325
+
326
+ ```tsx
327
+ // 同一个业务逻辑可以在不同 UI 框架中使用
328
+ // React 版本
329
+ const bootstrap = new Bootstrap({...});
330
+ bootstrap.use([IOC(UserService)]);
331
+
332
+ // Vue 版本
333
+ const bootstrap = new Bootstrap({...});
334
+ bootstrap.use([IOC(UserService)]); // 相同的业务逻辑
335
+
336
+ // 原生 JS 版本
337
+ const bootstrap = new Bootstrap({...});
338
+ bootstrap.use([IOC(UserService)]); // 相同的业务逻辑
339
+ ```
340
+
341
+ #### 3. **可扩展性**
342
+
343
+ ```tsx
344
+ // 轻松添加新的业务逻辑
345
+ bootstrap.use([
346
+ IOC(UserService),
347
+ IOC(PermissionService), // 新增权限服务
348
+ IOC(NotificationService), // 新增通知服务
349
+ IOC(AnalyticsService) // 新增统计服务
350
+ ]);
351
+ ```
352
+
353
+ #### 4. **团队协作**
354
+
355
+ - **前端开发者**:专注于 UI 组件和用户体验
356
+ - **后端开发者**:专注于 API 接口和数据处理
357
+ - **架构师**:专注于业务逻辑设计和系统架构
358
+ - **测试工程师**:可以独立测试各个模块
359
+
360
+ ### 快速开始
361
+
362
+ 如果你想要快速体验 Bootstrap,可以按照以下步骤:
363
+
364
+ #### 步骤 1:创建简单的插件
365
+
366
+ ```tsx
367
+ // 创建一个简单的插件
368
+ export class SimplePlugin implements BootstrapExecutorPlugin {
369
+ readonly pluginName = 'SimplePlugin';
370
+
371
+ onBefore({ parameters: { logger } }: BootstrapContext): void {
372
+ logger.info('SimplePlugin 启动成功!');
373
+ }
374
+ }
375
+ ```
376
+
377
+ #### 步骤 2:在启动器中注册
378
+
379
+ ```tsx
380
+ const bootstrap = new Bootstrap({
381
+ root: window,
382
+ logger,
383
+ ioc: { manager: IOC, register: new IocRegisterImpl({ pathname, appConfig }) }
384
+ });
385
+
386
+ // 注册插件
387
+ bootstrap.use([new SimplePlugin()]);
388
+
389
+ // 启动
390
+ await bootstrap.initialize();
391
+ await bootstrap.start();
392
+ ```
393
+
394
+ #### 步骤 3:查看效果
395
+
396
+ 打开浏览器控制台,你会看到 "SimplePlugin 启动成功!" 的日志。
397
+
398
+ **提示**:这个简单的例子展示了 Bootstrap 的基本用法。随着你对项目的了解,可以逐步添加更复杂的业务逻辑。
399
+
400
+ ### 实际项目中的应用场景
401
+
402
+ #### 场景一:多端应用
403
+
404
+ ```tsx
405
+ // Web 端
406
+ const webBootstrap = new Bootstrap({
407
+ root: window
408
+ // Web 特定配置
409
+ });
410
+ webBootstrap.use([IOC(UserService), IOC(WebSpecificService)]);
411
+
412
+ // 移动端 H5
413
+ const mobileBootstrap = new Bootstrap({
414
+ root: window
415
+ // 移动端特定配置
416
+ });
417
+ mobileBootstrap.use([IOC(UserService), IOC(MobileSpecificService)]);
418
+
419
+ // 小程序
420
+ const miniprogramBootstrap = new Bootstrap({
421
+ root: globalThis
422
+ // 小程序特定配置
423
+ });
424
+ miniprogramBootstrap.use([IOC(UserService), IOC(MiniprogramSpecificService)]);
425
+ ```
426
+
427
+ #### 场景二:微前端架构
428
+
429
+ ```tsx
430
+ // 主应用
431
+ const mainBootstrap = new Bootstrap({
432
+ root: window
433
+ // 主应用配置
434
+ });
435
+ mainBootstrap.use([IOC(GlobalUserService), IOC(RouterService)]);
436
+
437
+ // 子应用 A
438
+ const appABootstrap = new Bootstrap({
439
+ root: window
440
+ // 子应用 A 配置
441
+ });
442
+ appABootstrap.use([IOC(UserService), IOC(AppASpecificService)]);
443
+
444
+ // 子应用 B
445
+ const appBBootstrap = new Bootstrap({
446
+ root: window
447
+ // 子应用 B 配置
448
+ });
449
+ appBBootstrap.use([IOC(UserService), IOC(AppBSpecificService)]);
450
+ ```
451
+
452
+ #### 场景三:渐进式升级
453
+
454
+ ```tsx
455
+ // 旧版本:直接在组件中处理业务逻辑
456
+ function OldApp() {
457
+ const [user, setUser] = useState(null);
458
+ useEffect(() => {
459
+ fetchUser().then(setUser);
460
+ }, []);
461
+ return <div>{user?.name}</div>;
462
+ }
463
+
464
+ // 新版本:使用启动器分离关注点
465
+ function NewApp() {
466
+ const { user } = useStore(); // 从启动器管理的 store 获取
467
+ return <div>{user?.name}</div>;
468
+ }
469
+
470
+ // 可以同时存在,逐步迁移
471
+ const bootstrap = new Bootstrap({...});
472
+ bootstrap.use([IOC(UserService)]); // 新逻辑
473
+ // 旧逻辑仍然可以继续使用
474
+ ```
475
+
476
+ ### 最佳实践
477
+
478
+ #### 1. **插件设计原则**
479
+
480
+ ```tsx
481
+ // ✅ 好的插件设计
482
+ export class GoodPlugin implements BootstrapExecutorPlugin {
483
+ readonly pluginName = 'GoodPlugin';
484
+
485
+ // 单一职责
486
+ onBefore({ parameters: { ioc } }: BootstrapContext): void {
487
+ // 只做一件事:配置 API
488
+ ioc.get<UserApi>(UserApi).usePlugin(new FetchURLPlugin());
489
+ }
490
+ }
491
+
492
+ // ❌ 不好的插件设计
493
+ export class BadPlugin implements BootstrapExecutorPlugin {
494
+ readonly pluginName = 'BadPlugin';
495
+
496
+ // 做了太多事情
497
+ onBefore({ parameters: { ioc } }: BootstrapContext): void {
498
+ // 配置 API
499
+ ioc.get<UserApi>(UserApi).usePlugin(new FetchURLPlugin());
500
+ // 处理路由
501
+ ioc.get<RouterService>(RouterService).configure();
502
+ // 处理主题
503
+ ioc.get<ThemeService>(ThemeService).init();
504
+ // 处理国际化
505
+ ioc.get<I18nService>(I18nService).load();
506
+ }
507
+ }
508
+ ```
509
+
510
+ #### 2. **错误处理**
511
+
512
+ ```tsx
513
+ export class UserService implements ExecutorPlugin {
514
+ readonly pluginName = 'UserService';
515
+
516
+ async onBefore(): Promise<void> {
517
+ try {
518
+ if (this.isAuthenticated()) {
519
+ return;
520
+ }
521
+
522
+ const userToken = this.getToken();
523
+ if (!userToken) {
524
+ throw new AppError('NO_USER_TOKEN');
525
+ }
526
+
527
+ await this.userInfo();
528
+ this.store.authSuccess();
529
+ } catch (error) {
530
+ // 优雅的错误处理
531
+ this.store.authFailed(error);
532
+ this.routerService.gotoLogin();
533
+ }
534
+ }
535
+ }
536
+ ```
537
+
538
+ #### 3. **性能优化**
539
+
540
+ ```tsx
541
+ // 条件加载插件
542
+ if (process.env.NODE_ENV === 'development') {
543
+ bootstrap.use([IOC(DevToolsService)]);
544
+ }
545
+
546
+ // 按需加载插件
547
+ if (appConfig.features.analytics) {
548
+ bootstrap.use([IOC(AnalyticsService)]);
549
+ }
550
+ ```
551
+
552
+ ### 总结
553
+
554
+ Bootstrap 启动器不仅仅是一个技术实现,更是一种架构思想。它帮助我们:
555
+
556
+ 1. **分离关注点**:UI 和业务逻辑分离
557
+ 2. **提高可维护性**:模块化设计,易于理解和修改
558
+ 3. **增强可测试性**:每个模块都可以独立测试
559
+ 4. **支持团队协作**:不同角色可以专注于自己的领域
560
+ 5. **适应变化**:业务逻辑变化不影响 UI,UI 变化不影响业务逻辑
561
+
562
+ 这种设计模式在现代前端开发中变得越来越重要,特别是在大型项目和团队协作中。