@qlover/create-app 0.6.0 → 0.6.2
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/CHANGELOG.md +37 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/react-app/config/IOCIdentifier.ts +13 -0
- package/dist/templates/react-app/docs/zh/bootstrap.md +555 -0
- package/dist/templates/react-app/docs/zh/env.md +480 -0
- package/dist/templates/react-app/docs/zh/global.md +510 -0
- package/dist/templates/react-app/docs/zh/ioc.md +410 -0
- package/dist/templates/react-app/package.json +1 -1
- package/dist/templates/react-app/src/base/apis/AiApi.ts +10 -5
- package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +1 -1
- package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +1 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +10 -17
- package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +1 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +2 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +7 -5
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +3 -2
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +33 -0
- package/dist/templates/react-app/src/base/cases/RequestLogger.ts +1 -1
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
- package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +1 -1
- package/dist/templates/react-app/src/base/services/RouteService.ts +5 -2
- package/dist/templates/react-app/src/base/services/UserService.ts +8 -10
- package/dist/templates/react-app/src/core/IOC.ts +73 -83
- package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +52 -4
- package/dist/templates/react-app/src/core/bootstraps/{index.ts → BootstrapsRegistry.ts} +2 -3
- package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +25 -0
- package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +11 -17
- package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +10 -4
- package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +6 -15
- package/dist/templates/react-app/src/main.tsx +2 -5
- package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +1 -1
- package/dist/templates/react-app/tsconfig.app.json +2 -1
- package/dist/templates/react-app/tsconfig.node.json +2 -1
- package/dist/templates/react-app/vite.config.ts +1 -1
- package/package.json +2 -2
- package/dist/templates/react-app/src/base/port/ApiTransactionInterface.ts +0 -7
- package/dist/templates/react-app/src/base/port/RequestCatcherInterface.ts +0 -12
- package/dist/templates/react-app/src/core/bootstrap.ts +0 -58
- package/dist/templates/react-app/src/core/registers/RegisterApi.ts +0 -5
- package/dist/templates/react-app/src/core/registers/index.ts +0 -32
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
# 浏览器全局变量注入
|
|
2
|
+
|
|
3
|
+
## 什么是全局变量注入?
|
|
4
|
+
|
|
5
|
+
全局变量注入是 Bootstrap 的一个重要功能,它允许我们将应用的核心服务和工具注入到浏览器的全局环境中,方便在任何地方访问。
|
|
6
|
+
|
|
7
|
+
**简单来说**:就像把常用的工具放在工具箱里一样,我们把应用的核心功能(日志、存储、配置等)放到浏览器的全局环境中,这样在任何地方都能方便地使用。
|
|
8
|
+
|
|
9
|
+
## 工作原理
|
|
10
|
+
|
|
11
|
+
### 1. 全局变量注入流程
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
应用启动 → Bootstrap 初始化 → InjectGlobal 插件 → 注入到 window 对象 → 全局可访问
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### 2. 核心技术栈
|
|
18
|
+
|
|
19
|
+
- **@qlover/corekit-bridge**:提供 InjectGlobal 插件
|
|
20
|
+
- **TypeScript**:提供类型安全
|
|
21
|
+
- **浏览器全局对象**:window 或 globalThis
|
|
22
|
+
|
|
23
|
+
### 3. 文件结构
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
src/
|
|
27
|
+
├── core/
|
|
28
|
+
│ ├── globals.ts # 全局变量定义
|
|
29
|
+
│ └── bootstraps/
|
|
30
|
+
│ └── BootstrapApp.ts # Bootstrap 配置
|
|
31
|
+
├── base/
|
|
32
|
+
│ └── types/
|
|
33
|
+
│ └── global.d.ts # 全局类型声明
|
|
34
|
+
└── config/
|
|
35
|
+
└── common.ts # 全局变量名称配置
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 项目中的实现
|
|
39
|
+
|
|
40
|
+
### 1. 全局变量定义
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
// src/core/globals.ts
|
|
44
|
+
import { Logger, ConsoleHandler, ColorFormatter } from '@qlover/corekit-bridge';
|
|
45
|
+
import { AppConfig } from '@/base/cases/AppConfig';
|
|
46
|
+
import { DialogHandler } from '@/base/cases/DialogHandler';
|
|
47
|
+
|
|
48
|
+
// 应用配置
|
|
49
|
+
export const appConfig = new AppConfig();
|
|
50
|
+
|
|
51
|
+
// 对话框处理器
|
|
52
|
+
export const dialogHandler = new DialogHandler();
|
|
53
|
+
|
|
54
|
+
// 全局日志器
|
|
55
|
+
export const logger = new Logger({
|
|
56
|
+
handlers: new ConsoleHandler(new ColorFormatter(loggerStyles)),
|
|
57
|
+
silent: isProduction,
|
|
58
|
+
level: 'debug'
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// JSON 序列化器
|
|
62
|
+
export const JSON = new JSONSerializer();
|
|
63
|
+
|
|
64
|
+
// 本地存储
|
|
65
|
+
export const localStorage = new SyncStorage(new ObjectStorage(), [
|
|
66
|
+
JSON,
|
|
67
|
+
new Base64Serializer(),
|
|
68
|
+
window.localStorage
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
// 加密存储
|
|
72
|
+
export const localStorageEncrypt = localStorage;
|
|
73
|
+
|
|
74
|
+
// Cookie 存储
|
|
75
|
+
export const cookieStorage = new CookieStorage();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. 全局类型声明
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
// src/base/types/global.d.ts
|
|
82
|
+
import * as feGlobals from '@/core/globals';
|
|
83
|
+
import type { browserGlobalsName } from '@config/common';
|
|
84
|
+
|
|
85
|
+
declare global {
|
|
86
|
+
interface Window {
|
|
87
|
+
[browserGlobalsName]: Readonly<typeof feGlobals>;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 3. Bootstrap 中的注入配置
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
// src/core/bootstraps/BootstrapApp.ts
|
|
96
|
+
import { Bootstrap } from '@qlover/corekit-bridge';
|
|
97
|
+
import { browserGlobalsName } from '@config/common';
|
|
98
|
+
import * as globals from '../globals';
|
|
99
|
+
|
|
100
|
+
const bootstrap = new Bootstrap({
|
|
101
|
+
root: window,
|
|
102
|
+
logger,
|
|
103
|
+
ioc: {
|
|
104
|
+
manager: IOC,
|
|
105
|
+
register: new IocRegisterImpl({ pathname, appConfig })
|
|
106
|
+
},
|
|
107
|
+
globalOptions: {
|
|
108
|
+
sources: globals, // 全局变量源
|
|
109
|
+
target: browserGlobalsName // 注入目标名称
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 4. 全局变量名称配置
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
// config/common.ts
|
|
118
|
+
export const browserGlobalsName = 'feGlobals';
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## InjectGlobal 插件工作原理
|
|
122
|
+
|
|
123
|
+
### 1. 插件实现
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
// corekit-bridge/src/core/bootstrap/plugins/InjectGlobal.ts
|
|
127
|
+
export class InjectGlobal implements BootstrapExecutorPlugin {
|
|
128
|
+
readonly pluginName = 'InjectGlobal';
|
|
129
|
+
|
|
130
|
+
constructor(protected config: InjectGlobalConfig) {}
|
|
131
|
+
|
|
132
|
+
onBefore(context: BootstrapContext): void {
|
|
133
|
+
const { sources, target } = this.config;
|
|
134
|
+
|
|
135
|
+
// 如果 target 是字符串,注入到 root 对象
|
|
136
|
+
if (typeof target === 'string') {
|
|
137
|
+
Object.assign(context.parameters.root!, {
|
|
138
|
+
[target]: Object.freeze(Object.assign({}, sources))
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 如果 target 是对象,直接注入到目标对象
|
|
144
|
+
const _target = target || context.parameters.root;
|
|
145
|
+
|
|
146
|
+
if (typeof _target !== 'object' || _target === null) {
|
|
147
|
+
throw new Error('target must be an object');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 注入全局变量到目标对象
|
|
151
|
+
for (const key in sources) {
|
|
152
|
+
const element = sources[key];
|
|
153
|
+
Object.assign(_target, { [key]: element });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 2. 注入过程
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
// 注入前
|
|
163
|
+
window = {
|
|
164
|
+
// 浏览器原生属性
|
|
165
|
+
location: {...},
|
|
166
|
+
document: {...},
|
|
167
|
+
// 其他浏览器属性
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 注入后
|
|
171
|
+
window = {
|
|
172
|
+
// 浏览器原生属性
|
|
173
|
+
location: {...},
|
|
174
|
+
document: {...},
|
|
175
|
+
// 注入的全局变量
|
|
176
|
+
feGlobals: {
|
|
177
|
+
appConfig: AppConfig,
|
|
178
|
+
logger: Logger,
|
|
179
|
+
localStorage: SyncStorage,
|
|
180
|
+
dialogHandler: DialogHandler,
|
|
181
|
+
// ... 其他全局变量
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## 在代码中使用
|
|
187
|
+
|
|
188
|
+
### 1. 直接访问全局变量
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
// 在任何地方都可以直接访问
|
|
192
|
+
function someFunction() {
|
|
193
|
+
// 访问全局日志器
|
|
194
|
+
window.feGlobals.logger.info('这是一条日志');
|
|
195
|
+
|
|
196
|
+
// 访问应用配置
|
|
197
|
+
const appName = window.feGlobals.appConfig.appName;
|
|
198
|
+
|
|
199
|
+
// 访问本地存储
|
|
200
|
+
window.feGlobals.localStorage.set('key', 'value');
|
|
201
|
+
|
|
202
|
+
// 访问对话框处理器
|
|
203
|
+
window.feGlobals.dialogHandler.showMessage('Hello World');
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 2. 在组件中使用
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
import React from 'react';
|
|
211
|
+
|
|
212
|
+
function MyComponent() {
|
|
213
|
+
const handleClick = () => {
|
|
214
|
+
// 使用全局日志器
|
|
215
|
+
window.feGlobals.logger.info('用户点击了按钮');
|
|
216
|
+
|
|
217
|
+
// 使用全局对话框
|
|
218
|
+
window.feGlobals.dialogHandler.showMessage('操作成功');
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<button onClick={handleClick}>
|
|
223
|
+
点击我
|
|
224
|
+
</button>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 3. 在服务中使用
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
@injectable()
|
|
233
|
+
export class SomeService {
|
|
234
|
+
async doSomething() {
|
|
235
|
+
// 使用全局日志器记录操作
|
|
236
|
+
window.feGlobals.logger.info('开始执行操作');
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
// 业务逻辑
|
|
240
|
+
const result = await this.performOperation();
|
|
241
|
+
|
|
242
|
+
// 使用全局对话框显示结果
|
|
243
|
+
window.feGlobals.dialogHandler.showMessage('操作完成');
|
|
244
|
+
|
|
245
|
+
return result;
|
|
246
|
+
} catch (error) {
|
|
247
|
+
// 使用全局日志器记录错误
|
|
248
|
+
window.feGlobals.logger.error('操作失败:', error);
|
|
249
|
+
throw error;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### 4. 在工具函数中使用
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
// utils/helper.ts
|
|
259
|
+
export function saveUserData(data: any) {
|
|
260
|
+
try {
|
|
261
|
+
// 使用全局存储
|
|
262
|
+
window.feGlobals.localStorage.set('userData', data);
|
|
263
|
+
|
|
264
|
+
// 使用全局日志器
|
|
265
|
+
window.feGlobals.logger.info('用户数据已保存');
|
|
266
|
+
|
|
267
|
+
return true;
|
|
268
|
+
} catch (error) {
|
|
269
|
+
window.feGlobals.logger.error('保存用户数据失败:', error);
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## 实际应用场景
|
|
276
|
+
|
|
277
|
+
### 1. 调试和开发
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
// 在浏览器控制台中调试
|
|
281
|
+
console.log('应用配置:', window.feGlobals.appConfig);
|
|
282
|
+
console.log('当前用户:', window.feGlobals.localStorage.get('userData'));
|
|
283
|
+
|
|
284
|
+
// 手动触发日志
|
|
285
|
+
window.feGlobals.logger.debug('调试信息');
|
|
286
|
+
|
|
287
|
+
// 手动显示对话框
|
|
288
|
+
window.feGlobals.dialogHandler.showMessage('测试消息');
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### 2. 错误处理和监控
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
// 全局错误处理
|
|
295
|
+
window.addEventListener('error', (event) => {
|
|
296
|
+
window.feGlobals.logger.error('全局错误:', event.error);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// 未处理的 Promise 拒绝
|
|
300
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
301
|
+
window.feGlobals.logger.error('未处理的 Promise 拒绝:', event.reason);
|
|
302
|
+
});
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### 3. 第三方库集成
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
// 与第三方库集成
|
|
309
|
+
import thirdPartyLib from 'third-party-lib';
|
|
310
|
+
|
|
311
|
+
// 配置第三方库使用我们的全局服务
|
|
312
|
+
thirdPartyLib.configure({
|
|
313
|
+
logger: window.feGlobals.logger,
|
|
314
|
+
storage: window.feGlobals.localStorage,
|
|
315
|
+
dialog: window.feGlobals.dialogHandler
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### 4. 浏览器扩展开发
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
// 在浏览器扩展中使用
|
|
323
|
+
if (window.feGlobals) {
|
|
324
|
+
// 扩展可以访问应用的全局服务
|
|
325
|
+
const appConfig = window.feGlobals.appConfig;
|
|
326
|
+
const logger = window.feGlobals.logger;
|
|
327
|
+
|
|
328
|
+
// 执行扩展逻辑
|
|
329
|
+
logger.info('浏览器扩展已加载');
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## 最佳实践
|
|
334
|
+
|
|
335
|
+
### 1. 全局变量设计原则
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
// ✅ 好的设计:只暴露核心服务
|
|
339
|
+
export const globals = {
|
|
340
|
+
appConfig, // 应用配置
|
|
341
|
+
logger, // 日志服务
|
|
342
|
+
localStorage, // 存储服务
|
|
343
|
+
dialogHandler, // 对话框服务
|
|
344
|
+
// 其他核心服务...
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// ❌ 不好的设计:暴露太多细节
|
|
348
|
+
export const globals = {
|
|
349
|
+
appConfig,
|
|
350
|
+
logger,
|
|
351
|
+
localStorage,
|
|
352
|
+
dialogHandler,
|
|
353
|
+
// 不应该暴露的实现细节
|
|
354
|
+
internalService,
|
|
355
|
+
privateHelper,
|
|
356
|
+
implementationDetail
|
|
357
|
+
};
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### 2. 类型安全
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
// 确保全局变量有正确的类型
|
|
364
|
+
declare global {
|
|
365
|
+
interface Window {
|
|
366
|
+
feGlobals: {
|
|
367
|
+
appConfig: AppConfig;
|
|
368
|
+
logger: LoggerInterface;
|
|
369
|
+
localStorage: SyncStorageInterface<string, string>;
|
|
370
|
+
dialogHandler: DialogHandler;
|
|
371
|
+
// 其他全局变量的类型...
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### 3. 只读访问
|
|
378
|
+
|
|
379
|
+
```tsx
|
|
380
|
+
// 使用 Object.freeze 确保全局变量不被修改
|
|
381
|
+
Object.assign(context.parameters.root!, {
|
|
382
|
+
[target]: Object.freeze(Object.assign({}, sources))
|
|
383
|
+
});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### 4. 命名空间隔离
|
|
387
|
+
|
|
388
|
+
```tsx
|
|
389
|
+
// 使用命名空间避免冲突
|
|
390
|
+
export const browserGlobalsName = 'feGlobals'; // 而不是 'globals'
|
|
391
|
+
|
|
392
|
+
// 在 window 上创建命名空间
|
|
393
|
+
window.feGlobals = {
|
|
394
|
+
// 我们的全局变量
|
|
395
|
+
};
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## 调试和故障排除
|
|
399
|
+
|
|
400
|
+
### 1. 检查全局变量注入
|
|
401
|
+
|
|
402
|
+
```tsx
|
|
403
|
+
// 在浏览器控制台中检查
|
|
404
|
+
console.log('全局变量:', window.feGlobals);
|
|
405
|
+
console.log('应用配置:', window.feGlobals?.appConfig);
|
|
406
|
+
console.log('日志器:', window.feGlobals?.logger);
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### 2. 常见问题
|
|
410
|
+
|
|
411
|
+
**问题 1:全局变量未注入**
|
|
412
|
+
```tsx
|
|
413
|
+
// 检查 Bootstrap 配置
|
|
414
|
+
const bootstrap = new Bootstrap({
|
|
415
|
+
globalOptions: {
|
|
416
|
+
sources: globals, // 确保 sources 正确
|
|
417
|
+
target: browserGlobalsName // 确保 target 正确
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
**问题 2:类型错误**
|
|
423
|
+
```tsx
|
|
424
|
+
// 检查类型声明
|
|
425
|
+
declare global {
|
|
426
|
+
interface Window {
|
|
427
|
+
[browserGlobalsName]: Readonly<typeof feGlobals>;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**问题 3:全局变量被修改**
|
|
433
|
+
```tsx
|
|
434
|
+
// 确保使用 Object.freeze
|
|
435
|
+
Object.freeze(Object.assign({}, sources));
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### 3. 调试工具
|
|
439
|
+
|
|
440
|
+
```tsx
|
|
441
|
+
// 创建调试工具
|
|
442
|
+
export class GlobalDebugger {
|
|
443
|
+
static logGlobals(): void {
|
|
444
|
+
console.group('Global Variables Debug');
|
|
445
|
+
console.log('feGlobals:', window.feGlobals);
|
|
446
|
+
console.log('AppConfig:', window.feGlobals?.appConfig);
|
|
447
|
+
console.log('Logger:', window.feGlobals?.logger);
|
|
448
|
+
console.log('LocalStorage:', window.feGlobals?.localStorage);
|
|
449
|
+
console.groupEnd();
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// 在开发环境中使用
|
|
454
|
+
if (import.meta.env.DEV) {
|
|
455
|
+
GlobalDebugger.logGlobals();
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
## 安全考虑
|
|
460
|
+
|
|
461
|
+
### 1. 避免敏感信息
|
|
462
|
+
|
|
463
|
+
```tsx
|
|
464
|
+
// ❌ 不要暴露敏感信息
|
|
465
|
+
export const globals = {
|
|
466
|
+
appConfig,
|
|
467
|
+
logger,
|
|
468
|
+
// 不要暴露 API 密钥、密码等敏感信息
|
|
469
|
+
apiKey: 'secret_key', // 危险!
|
|
470
|
+
password: 'password' // 危险!
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
// ✅ 只暴露必要的服务
|
|
474
|
+
export const globals = {
|
|
475
|
+
appConfig,
|
|
476
|
+
logger,
|
|
477
|
+
localStorage,
|
|
478
|
+
dialogHandler
|
|
479
|
+
// 不包含敏感信息
|
|
480
|
+
};
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### 2. 权限控制
|
|
484
|
+
|
|
485
|
+
```tsx
|
|
486
|
+
// 在生产环境中限制某些功能
|
|
487
|
+
if (import.meta.env.PROD) {
|
|
488
|
+
// 禁用调试功能
|
|
489
|
+
window.feGlobals.logger.setLevel('warn');
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### 3. 命名空间隔离
|
|
494
|
+
|
|
495
|
+
```tsx
|
|
496
|
+
// 使用特定的命名空间避免冲突
|
|
497
|
+
export const browserGlobalsName = 'feGlobals'; // 而不是通用的 'globals'
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
## 总结
|
|
501
|
+
|
|
502
|
+
全局变量注入系统提供了:
|
|
503
|
+
|
|
504
|
+
1. **全局访问**:在任何地方都能访问核心服务
|
|
505
|
+
2. **类型安全**:通过 TypeScript 提供类型检查
|
|
506
|
+
3. **调试便利**:在浏览器控制台中直接调试
|
|
507
|
+
4. **第三方集成**:便于与第三方库集成
|
|
508
|
+
5. **开发体验**:提升开发效率和调试体验
|
|
509
|
+
|
|
510
|
+
通过合理使用全局变量注入,可以让应用的核心服务在任何地方都能方便地访问,同时保持代码的整洁和类型安全。
|