概述
在企业环境中,Three.js应用需要满足更高的要求:可维护性、可扩展性、性能、安全性和团队协作。本节将深入探讨如何构建面向企业级生产的Three.js应用架构,涵盖从项目结构到部署运维的全流程。

企业级Three.js架构:
企业级Three.js应用 应用架构层 开发工具层 运维部署层 模块化设计 状态管理 服务抽象 开发环境 构建系统 质量保证 持续集成 性能监控 错误追踪 代码可维护性 开发效率 部署可靠性
企业级架构设计原则
核心设计原则
| 原则 | 企业级实现 | 收益 |
|---|---|---|
| 单一职责 | 模块功能专注,职责清晰 | 易于测试和维护 |
| 开闭原则 | 对扩展开放,对修改关闭 | 系统稳定性 |
| 依赖倒置 | 依赖抽象而非具体实现 | 解耦和灵活性 |
| 接口隔离 | 细粒度接口设计 | 减少不必要的依赖 |
| 迪米特法则 | 最小知识原则 | 降低耦合度 |
企业级技术要求
-
可维护性
- 清晰的代码组织结构
- 完善的文档和注释
- 统一的代码规范
-
可扩展性
- 插件化架构
- 配置驱动开发
- 微前端支持
-
性能要求
- 内存泄漏防护
- 渲染性能优化
- 加载策略优化
完整企业级架构实现
1. 项目结构设计
enterprise-threejs-app/
├── public/ # 静态资源
│ ├── models/ # 3D模型文件
│ ├── textures/ # 纹理贴图
│ └── fonts/ # 字体文件
├── src/
│ ├── core/ # 核心架构
│ │ ├── Application.js # 应用主类
│ │ ├── SceneManager.js # 场景管理器
│ │ └── EventSystem.js # 事件系统
│ ├── modules/ # 功能模块
│ │ ├── rendering/ # 渲染模块
│ │ ├── animation/ # 动画模块
│ │ ├── physics/ # 物理模块
│ │ └── ui/ # UI模块
│ ├── services/ # 服务层
│ │ ├── AssetService.js # 资源服务
│ │ ├── ConfigService.js # 配置服务
│ │ └── AnalyticsService.js # 分析服务
│ ├── utils/ # 工具函数
│ │ ├── math/ # 数学工具
│ │ ├── geometry/ # 几何工具
│ │ └── helpers/ # 辅助工具
│ ├── types/ # TypeScript类型定义
│ ├── config/ # 配置文件
│ └── styles/ # 样式文件
├── tests/ # 测试文件
├── docs/ # 项目文档
├── scripts/ # 构建脚本
└── config/ # 工程配置
2. 核心应用架构
javascript
// src/core/Application.js
class EnterpriseThreeJSApplication {
constructor(config = {}) {
this.config = this.mergeConfig(config);
this.modules = new Map();
this.services = new Map();
this.state = new ApplicationState();
this.eventSystem = new EventSystem();
this.isInitialized = false;
this.isRunning = false;
this.init();
}
// 合并配置
mergeConfig(userConfig) {
const defaultConfig = {
container: '#app',
width: window.innerWidth,
height: window.innerHeight,
antialias: true,
alpha: false,
preserveDrawingBuffer: false,
powerPreference: 'high-performance',
autoStart: true,
debug: process.env.NODE_ENV === 'development',
modules: [],
services: []
};
return { ...defaultConfig, ...userConfig };
}
// 初始化应用
async init() {
try {
// 初始化事件系统
await this.eventSystem.init();
// 初始化服务层
await this.initServices();
// 初始化核心模块
await this.initCoreModules();
// 初始化功能模块
await this.initFeatureModules();
// 设置事件监听
this.setupEventListeners();
this.isInitialized = true;
// 触发初始化完成事件
this.eventSystem.emit('application:initialized');
// 自动启动
if (this.config.autoStart) {
this.start();
}
} catch (error) {
console.error('Application initialization failed:', error);
this.eventSystem.emit('application:error', { error });
}
}
// 初始化服务层
async initServices() {
const serviceConfigs = [
{
name: 'AssetService',
class: AssetService,
config: this.config.assets
},
{
name: 'ConfigService',
class: ConfigService,
config: this.config
},
{
name: 'AnalyticsService',
class: AnalyticsService,
config: this.config.analytics
},
{
name: 'PerformanceService',
class: PerformanceService,
config: this.config.performance
},
...this.config.services
];
for (const serviceConfig of serviceConfigs) {
try {
const service = new serviceConfig.class(serviceConfig.config);
await service.init();
this.services.set(serviceConfig.name, service);
this.eventSystem.emit('service:initialized', {
name: serviceConfig.name,
service
});
} catch (error) {
console.error(`Service ${serviceConfig.name} initialization failed:`, error);
throw error;
}
}
}
// 初始化核心模块
async initCoreModules() {
const coreModules = [
{
name: 'SceneManager',
class: SceneManager,
priority: 100
},
{
name: 'RenderManager',
class: RenderManager,
priority: 90
},
{
name: 'CameraManager',
class: CameraManager,
priority: 80
},
{
name: 'InputManager',
class: InputManager,
priority: 70
}
];
await this.initModules(coreModules);
}
// 初始化功能模块
async initFeatureModules() {
await this.initModules(this.config.modules);
}
// 初始化模块
async initModules(moduleConfigs) {
// 按优先级排序
moduleConfigs.sort((a, b) => (b.priority || 0) - (a.priority || 0));
for (const moduleConfig of moduleConfigs) {
try {
const module = new moduleConfig.class({
application: this,
eventSystem: this.eventSystem,
services: this.services,
config: moduleConfig.config
});
await module.init();
this.modules.set(moduleConfig.name, module);
this.eventSystem.emit('module:initialized', {
name: moduleConfig.name,
module
});
} catch (error) {
console.error(`Module ${moduleConfig.name} initialization failed:`, error);
// 根据配置决定是否终止初始化
if (moduleConfig.required !== false) {
throw error;
}
}
}
}
// 启动应用
async start() {
if (!this.isInitialized) {
throw new Error('Application must be initialized before starting');
}
if (this.isRunning) {
console.warn('Application is already running');
return;
}
try {
// 启动所有模块
for (const [name, module] of this.modules) {
await module.start();
this.eventSystem.emit('module:started', { name, module });
}
// 启动所有服务
for (const [name, service] of this.services) {
if (typeof service.start === 'function') {
await service.start();
this.eventSystem.emit('service:started', { name, service });
}
}
this.isRunning = true;
this.eventSystem.emit('application:started');
// 开始渲染循环
this.startRenderLoop();
} catch (error) {
console.error('Application startup failed:', error);
this.eventSystem.emit('application:error', { error });
}
}
// 开始渲染循环
startRenderLoop() {
const render = (timestamp) => {
if (!this.isRunning) return;
try {
// 更新应用状态
this.update(timestamp);
// 渲染场景
this.render(timestamp);
// 继续循环
requestAnimationFrame(render);
} catch (error) {
console.error('Render loop error:', error);
this.eventSystem.emit('render:error', { error });
}
};
requestAnimationFrame(render);
}
// 更新逻辑
update(timestamp) {
const deltaTime = this.calculateDeltaTime(timestamp);
// 更新所有模块
for (const [name, module] of this.modules) {
if (typeof module.update === 'function') {
module.update(deltaTime, timestamp);
}
}
this.eventSystem.emit('application:update', { deltaTime, timestamp });
}
// 渲染逻辑
render(timestamp) {
this.eventSystem.emit('render:before');
// 调用渲染管理器进行渲染
const renderManager = this.modules.get('RenderManager');
if (renderManager) {
renderManager.render(timestamp);
}
this.eventSystem.emit('render:after');
}
// 计算时间差
calculateDeltaTime(timestamp) {
if (!this.lastTimestamp) {
this.lastTimestamp = timestamp;
return 0;
}
const deltaTime = (timestamp - this.lastTimestamp) / 1000;
this.lastTimestamp = timestamp;
// 限制最大deltaTime避免异常情况
return Math.min(deltaTime, 0.1);
}
// 获取服务
getService(name) {
const service = this.services.get(name);
if (!service) {
throw new Error(`Service ${name} not found`);
}
return service;
}
// 获取模块
getModule(name) {
const module = this.modules.get(name);
if (!module) {
throw new Error(`Module ${name} not found`);
}
return module;
}
// 暂停应用
pause() {
this.isRunning = false;
this.eventSystem.emit('application:paused');
}
// 恢复应用
resume() {
if (this.isRunning) return;
this.isRunning = true;
this.lastTimestamp = null;
this.startRenderLoop();
this.eventSystem.emit('application:resumed');
}
// 销毁应用
async destroy() {
this.isRunning = false;
// 销毁所有模块
for (const [name, module] of this.modules) {
try {
await module.destroy();
this.eventSystem.emit('module:destroyed', { name });
} catch (error) {
console.error(`Error destroying module ${name}:`, error);
}
}
// 销毁所有服务
for (const [name, service] of this.services) {
try {
if (typeof service.destroy === 'function') {
await service.destroy();
this.eventSystem.emit('service:destroyed', { name });
}
} catch (error) {
console.error(`Error destroying service ${name}:`, error);
}
}
// 清理事件系统
this.eventSystem.destroy();
this.modules.clear();
this.services.clear();
this.eventSystem.emit('application:destroyed');
}
}
3. 场景管理器
javascript
// src/core/SceneManager.js
class SceneManager {
constructor(dependencies) {
this.application = dependencies.application;
this.eventSystem = dependencies.eventSystem;
this.config = dependencies.config;
this.scenes = new Map();
this.currentScene = null;
this.sceneStack = [];
this.transitionInProgress = false;
}
async init() {
// 创建默认场景
await this.createDefaultScene();
// 设置场景切换监听
this.setupSceneListeners();
}
async createDefaultScene() {
const defaultScene = new THREE.Scene();
defaultScene.name = 'default';
// 设置场景背景
if (this.config.background) {
if (typeof this.config.background === 'string') {
defaultScene.background = new THREE.Color(this.config.background);
} else {
defaultScene.background = this.config.background;
}
}
// 设置雾效
if (this.config.fog) {
defaultScene.fog = new THREE.Fog(
this.config.fog.color,
this.config.fog.near,
this.config.fog.far
);
}
this.addScene('default', defaultScene);
this.switchToScene('default');
}
// 添加场景
addScene(name, scene, options = {}) {
if (this.scenes.has(name)) {
throw new Error(`Scene ${name} already exists`);
}
const sceneInfo = {
name,
scene,
objects: new Map(),
cameras: new Map(),
lights: new Map(),
userData: options.userData || {},
isActive: false
};
this.scenes.set(name, sceneInfo);
this.eventSystem.emit('scene:added', { name, scene, options });
return sceneInfo;
}
// 切换到场景
async switchToScene(name, transitionOptions = {}) {
if (this.transitionInProgress) {
console.warn('Scene transition already in progress');
return false;
}
if (!this.scenes.has(name)) {
throw new Error(`Scene ${name} not found`);
}
const targetScene = this.scenes.get(name);
if (this.currentScene && this.currentScene.name === name) {
console.warn(`Already in scene ${name}`);
return true;
}
this.transitionInProgress = true;
try {
// 触发场景切换前事件
this.eventSystem.emit('scene:beforeSwitch', {
from: this.currentScene?.name,
to: name,
options: transitionOptions
});
// 执行场景切换
await this.performSceneSwitch(targetScene, transitionOptions);
this.transitionInProgress = false;
// 触发场景切换后事件
this.eventSystem.emit('scene:afterSwitch', {
from: this.currentScene?.name,
to: name
});
return true;
} catch (error) {
this.transitionInProgress = false;
console.error(`Scene switch to ${name} failed:`, error);
this.eventSystem.emit('scene:switchError', { error, target: name });
return false;
}
}
// 执行场景切换
async performSceneSwitch(targetScene, transitionOptions) {
const oldScene = this.currentScene;
// 离开旧场景
if (oldScene) {
await this.leaveScene(oldScene, transitionOptions);
}
// 进入新场景
await this.enterScene(targetScene, transitionOptions);
// 更新当前场景
this.currentScene = targetScene;
// 更新渲染管理器
const renderManager = this.application.getModule('RenderManager');
if (renderManager) {
renderManager.setScene(targetScene.scene);
}
}
// 离开场景
async leaveScene(sceneInfo, transitionOptions) {
sceneInfo.isActive = false;
// 触发场景离开事件
this.eventSystem.emit('scene:leaving', {
scene: sceneInfo.name,
options: transitionOptions
});
// 执行离开动画或清理
if (transitionOptions.transitionOut) {
await transitionOptions.transitionOut(sceneInfo.scene);
}
}
// 进入场景
async enterScene(sceneInfo, transitionOptions) {
sceneInfo.isActive = true;
// 触发场景进入事件
this.eventSystem.emit('scene:entering', {
scene: sceneInfo.name,
options: transitionOptions
});
// 执行进入动画
if (transitionOptions.transitionIn) {
await transitionOptions.transitionIn(sceneInfo.scene);
}
}
// 推入场景(保留当前场景)
pushScene(name, transitionOptions = {}) {
if (this.currentScene) {
this.sceneStack.push(this.currentScene.name);
}
return this.switchToScene(name, transitionOptions);
}
// 弹出场景(返回上一个场景)
popScene(transitionOptions = {}) {
if (this.sceneStack.length === 0) {
console.warn('No scenes in stack to pop');
return false;
}
const previousScene = this.sceneStack.pop();
return this.switchToScene(previousScene, transitionOptions);
}
// 获取当前场景
getCurrentScene() {
return this.currentScene ? this.currentScene.scene : null;
}
// 获取场景信息
getSceneInfo(name) {
return this.scenes.get(name);
}
// 添加对象到场景
addObjectToScene(sceneName, object, options = {}) {
const sceneInfo = this.scenes.get(sceneName);
if (!sceneInfo) {
throw new Error(`Scene ${sceneName} not found`);
}
const objectId = options.id || object.uuid;
sceneInfo.objects.set(objectId, {
object,
id: objectId,
type: options.type || 'mesh',
userData: options.userData || {}
});
sceneInfo.scene.add(object);
this.eventSystem.emit('scene:objectAdded', {
scene: sceneName,
object,
objectId,
options
});
return objectId;
}
// 从场景移除对象
removeObjectFromScene(sceneName, objectId) {
const sceneInfo = this.scenes.get(sceneName);
if (!sceneInfo) return false;
const objectInfo = sceneInfo.objects.get(objectId);
if (!objectInfo) return false;
sceneInfo.scene.remove(objectInfo.object);
sceneInfo.objects.delete(objectId);
this.eventSystem.emit('scene:objectRemoved', {
scene: sceneName,
objectId,
object: objectInfo.object
});
return true;
}
// 查找场景中的对象
findObjectInScene(sceneName, predicate) {
const sceneInfo = this.scenes.get(sceneName);
if (!sceneInfo) return null;
for (const [objectId, objectInfo] of sceneInfo.objects) {
if (predicate(objectInfo.object, objectId, objectInfo)) {
return objectInfo;
}
}
return null;
}
// 设置场景监听
setupSceneListeners() {
// 监听窗口大小变化
window.addEventListener('resize', () => {
this.handleResize();
});
}
// 处理窗口大小变化
handleResize() {
if (this.currentScene) {
this.eventSystem.emit('scene:resize', {
scene: this.currentScene.name,
width: window.innerWidth,
height: window.innerHeight
});
}
}
// 更新场景
update(deltaTime) {
if (!this.currentScene) return;
// 更新场景中的动画对象
for (const [objectId, objectInfo] of this.currentScene.objects) {
if (objectInfo.object.userData &&
typeof objectInfo.object.userData.update === 'function') {
objectInfo.object.userData.update(deltaTime);
}
}
}
// 销毁场景管理器
async destroy() {
// 销毁所有场景
for (const [name, sceneInfo] of this.scenes) {
this.destroyScene(sceneInfo);
}
this.scenes.clear();
this.currentScene = null;
this.sceneStack = [];
}
// 销毁单个场景
destroyScene(sceneInfo) {
// 清理所有对象
for (const [objectId, objectInfo] of sceneInfo.objects) {
this.cleanupObject(objectInfo.object);
}
sceneInfo.objects.clear();
sceneInfo.scene.dispose();
this.eventSystem.emit('scene:destroyed', { name: sceneInfo.name });
}
// 清理对象
cleanupObject(object) {
if (object.geometry) {
object.geometry.dispose();
}
if (object.material) {
if (Array.isArray(object.material)) {
object.material.forEach(material => material.dispose());
} else {
object.material.dispose();
}
}
if (object.texture) {
object.texture.dispose();
}
// 递归清理子对象
if (object.children) {
object.children.forEach(child => this.cleanupObject(child));
}
}
}
4. 服务层实现
javascript
// src/services/AssetService.js
class AssetService {
constructor(config) {
this.config = config;
this.loaders = new Map();
this.cache = new Map();
this.queue = new AssetQueue();
this.progressCallbacks = new Set();
this.initLoaders();
}
async init() {
// 预加载关键资源
if (this.config.preload) {
await this.preloadAssets(this.config.preload);
}
}
// 初始化加载器
initLoaders() {
// 注册各种资源加载器
this.loaders.set('texture', new THREE.TextureLoader());
this.loaders.set('gltf', new THREE.GLTFLoader());
this.loaders.set('obj', new THREE.OBJLoader());
this.loaders.set('fbx', new THREE.FBXLoader());
this.loaders.set('font', new THREE.FontLoader());
this.loaders.set('audio', new THREE.AudioLoader());
// 配置加载器
this.configureLoaders();
}
// 配置加载器
configureLoaders() {
// 配置GLTF加载器
const gltfLoader = this.loaders.get('gltf');
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath(this.config.dracoPath || '/draco/');
gltfLoader.setDRACOLoader(dracoLoader);
}
// 加载资源
async load(url, options = {}) {
const cacheKey = this.getCacheKey(url, options);
// 检查缓存
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
// 检查正在加载的资源
if (this.queue.isLoading(url)) {
return this.queue.waitForCompletion(url);
}
// 开始加载
const promise = this.loadAsset(url, options);
this.queue.add(url, promise);
try {
const asset = await promise;
this.cache.set(cacheKey, asset);
this.queue.complete(url);
return asset;
} catch (error) {
this.queue.error(url, error);
throw error;
}
}
// 加载单个资源
async loadAsset(url, options) {
const type = options.type || this.detectAssetType(url);
const loader = this.loaders.get(type);
if (!loader) {
throw new Error(`No loader found for type: ${type}`);
}
return new Promise((resolve, reject) => {
// 进度回调
const onProgress = (event) => {
this.handleProgress(url, event, options);
};
// 加载完成回调
const onLoad = (asset) => {
this.handleLoadComplete(url, asset, options);
resolve(asset);
};
// 错误处理
const onError = (error) => {
this.handleLoadError(url, error, options);
reject(error);
};
// 执行加载
loader.load(url, onLoad, onProgress, onError);
});
}
// 批量加载资源
async loadMultiple(assets) {
const promises = assets.map(asset =>
this.load(asset.url, asset.options)
);
return Promise.all(promises);
}
// 预加载资源
async preloadAssets(assets) {
const total = assets.length;
let loaded = 0;
for (const asset of assets) {
try {
await this.load(asset.url, asset.options);
loaded++;
// 更新进度
this.emitProgress({
type: 'preload',
loaded,
total,
url: asset.url
});
} catch (error) {
console.error(`Preload failed for ${asset.url}:`, error);
}
}
}
// 检测资源类型
detectAssetType(url) {
const extension = url.split('.').pop().toLowerCase();
const typeMap = {
'jpg': 'texture',
'jpeg': 'texture',
'png': 'texture',
'gif': 'texture',
'webp': 'texture',
'gltf': 'gltf',
'glb': 'gltf',
'obj': 'obj',
'fbx': 'fbx',
'json': 'font',
'mp3': 'audio',
'wav': 'audio',
'ogg': 'audio'
};
return typeMap[extension] || 'texture';
}
// 处理加载进度
handleProgress(url, event, options) {
const progress = {
url,
loaded: event.loaded,
total: event.total,
percent: event.total ? (event.loaded / event.total) * 100 : 0,
type: options.type
};
this.emitProgress(progress);
}
// 处理加载完成
handleLoadComplete(url, asset, options) {
// 后处理资源
if (options.postProcess) {
options.postProcess(asset);
}
// 触发加载完成事件
this.emitProgress({
url,
type: 'complete',
asset
});
}
// 处理加载错误
handleLoadError(url, error, options) {
console.error(`Asset load failed: ${url}`, error);
this.emitProgress({
url,
type: 'error',
error
});
}
// 发射进度事件
emitProgress(progress) {
this.progressCallbacks.forEach(callback => {
try {
callback(progress);
} catch (error) {
console.error('Progress callback error:', error);
}
});
}
// 添加进度回调
onProgress(callback) {
this.progressCallbacks.add(callback);
return () => this.progressCallbacks.delete(callback);
}
// 获取缓存键
getCacheKey(url, options) {
return `${url}:${JSON.stringify(options)}`;
}
// 清理缓存
clearCache() {
// 清理资源
for (const asset of this.cache.values()) {
this.disposeAsset(asset);
}
this.cache.clear();
}
// 释放资源
disposeAsset(asset) {
if (asset.dispose) {
asset.dispose();
} else if (asset.geometry) {
asset.geometry.dispose();
} else if (asset.material) {
if (Array.isArray(asset.material)) {
asset.material.forEach(m => m.dispose());
} else {
asset.material.dispose();
}
} else if (asset.texture) {
asset.texture.dispose();
}
}
// 销毁服务
async destroy() {
this.clearCache();
this.progressCallbacks.clear();
this.queue.clear();
}
}
// 资源队列管理
class AssetQueue {
constructor() {
this.loading = new Map();
this.waiting = new Map();
}
add(url, promise) {
this.loading.set(url, {
promise,
startTime: Date.now()
});
}
isLoading(url) {
return this.loading.has(url);
}
waitForCompletion(url) {
if (!this.loading.has(url)) {
return Promise.reject(new Error(`Asset ${url} not in loading queue`));
}
return this.loading.get(url).promise;
}
complete(url) {
this.loading.delete(url);
this.cleanupWaiting(url);
}
error(url, error) {
this.loading.delete(url);
this.cleanupWaiting(url, error);
}
cleanupWaiting(url, error = null) {
if (this.waiting.has(url)) {
const callbacks = this.waiting.get(url);
this.waiting.delete(url);
callbacks.forEach(callback => {
try {
callback(error);
} catch (e) {
console.error('Waiting callback error:', e);
}
});
}
}
clear() {
this.loading.clear();
this.waiting.clear();
}
}
5. 配置管理系统
javascript
// src/services/ConfigService.js
class ConfigService {
constructor(config) {
this.defaultConfig = this.getDefaultConfig();
this.userConfig = config || {};
this.dynamicConfig = {};
this.configListeners = new Map();
this.mergedConfig = this.mergeConfigs();
}
// 获取默认配置
getDefaultConfig() {
return {
rendering: {
antialias: true,
shadowMap: {
enabled: true,
type: THREE.PCFSoftShadowMap
},
toneMapping: THREE.ACESFilmicToneMapping,
toneMappingExposure: 1.0
},
quality: {
level: 'high', // 'low', 'medium', 'high', 'ultra'
textureQuality: 1.0,
geometryQuality: 1.0
},
performance: {
maxFPS: 60,
enableStats: false,
enableMemoryMonitor: false
},
controls: {
sensitivity: 1.0,
invertY: false,
smoothness: 0.1
},
audio: {
enabled: true,
volume: 0.8,
spatialAudio: true
},
accessibility: {
colorBlindMode: 'none',
highContrast: false,
largeText: false
}
};
}
// 合并配置
mergeConfigs() {
const merged = this.deepMerge(
this.defaultConfig,
this.userConfig,
this.dynamicConfig
);
// 应用配置验证
this.validateConfig(merged);
return merged;
}
// 深度合并对象
deepMerge(...objects) {
const result = {};
for (const obj of objects) {
for (const [key, value] of Object.entries(obj)) {
if (value && typeof value === 'object' && !Array.isArray(value)) {
result[key] = this.deepMerge(result[key] || {}, value);
} else {
result[key] = value;
}
}
}
return result;
}
// 验证配置
validateConfig(config) {
const validators = {
quality: (quality) => {
const validLevels = ['low', 'medium', 'high', 'ultra'];
if (!validLevels.includes(quality.level)) {
throw new Error(`Invalid quality level: ${quality.level}`);
}
},
rendering: (rendering) => {
if (rendering.toneMappingExposure < 0) {
throw new Error('Tone mapping exposure cannot be negative');
}
}
};
for (const [section, validator] of Object.entries(validators)) {
if (config[section]) {
validator(config[section]);
}
}
}
// 获取配置
get(path, defaultValue = null) {
const keys = path.split('.');
let value = this.mergedConfig;
for (const key of keys) {
if (value && typeof value === 'object' && key in value) {
value = value[key];
} else {
return defaultValue;
}
}
return value;
}
// 设置配置
set(path, value) {
const keys = path.split('.');
let current = this.dynamicConfig;
// 创建嵌套结构
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (!(key in current)) {
current[key] = {};
}
current = current[key];
}
// 设置最终值
const finalKey = keys[keys.length - 1];
const oldValue = this.get(path);
current[finalKey] = value;
// 重新合并配置
this.mergedConfig = this.mergeConfigs();
// 触发配置变化事件
this.emitConfigChange(path, value, oldValue);
}
// 监听配置变化
onConfigChange(path, callback) {
if (!this.configListeners.has(path)) {
this.configListeners.set(path, new Set());
}
this.configListeners.get(path).add(callback);
// 返回取消监听函数
return () => {
const listeners = this.configListeners.get(path);
if (listeners) {
listeners.delete(callback);
if (listeners.size === 0) {
this.configListeners.delete(path);
}
}
};
}
// 发射配置变化事件
emitConfigChange(path, newValue, oldValue) {
const listeners = this.configListeners.get(path);
if (listeners) {
listeners.forEach(callback => {
try {
callback(newValue, oldValue, path);
} catch (error) {
console.error('Config change callback error:', error);
}
});
}
// 同时触发通配符监听器
const wildcardListeners = this.configListeners.get('*');
if (wildcardListeners) {
wildcardListeners.forEach(callback => {
try {
callback(path, newValue, oldValue);
} catch (error) {
console.error('Wildcard config change callback error:', error);
}
});
}
}
// 保存配置到本地存储
saveToLocalStorage(key = 'threejs-app-config') {
try {
localStorage.setItem(key, JSON.stringify(this.dynamicConfig));
} catch (error) {
console.error('Failed to save config to localStorage:', error);
}
}
// 从本地存储加载配置
loadFromLocalStorage(key = 'threejs-app-config') {
try {
const saved = localStorage.getItem(key);
if (saved) {
this.dynamicConfig = JSON.parse(saved);
this.mergedConfig = this.mergeConfigs();
return true;
}
} catch (error) {
console.error('Failed to load config from localStorage:', error);
}
return false;
}
// 重置配置
reset() {
this.dynamicConfig = {};
this.mergedConfig = this.mergeConfigs();
}
// 获取完整配置
getAll() {
return { ...this.mergedConfig };
}
async init() {
// 尝试加载保存的配置
this.loadFromLocalStorage();
// 应用配置到Three.js
this.applyThreeJSConfig();
}
// 应用配置到Three.js
applyThreeJSConfig() {
const renderingConfig = this.get('rendering');
if (renderingConfig) {
// 这里可以应用全局Three.js设置
THREE.ColorManagement.enabled = renderingConfig.colorManagement !== false;
}
}
async destroy() {
// 保存配置
this.saveToLocalStorage();
this.configListeners.clear();
}
}
企业级开发工具链
Webpack配置优化
javascript
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: process.env.NODE_ENV || 'development',
entry: {
app: './src/index.js',
vendor: ['three', 'dat.gui']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime']
}
}
},
{
test: /\.(glsl|vs|fs|vert|frag)$/,
use: 'raw-loader'
},
{
test: /\.(png|jpg|gif|gltf|bin|mp3|wav)$/,
type: 'asset/resource'
}
]
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
enforce: true
},
three: {
test: /[\\/]node_modules[\\/](three)[\\/]/,
name: 'three',
priority: 20,
enforce: true
}
}
}
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.APP_VERSION': JSON.stringify(process.env.npm_package_version)
})
],
devServer: {
static: {
directory: path.join(__dirname, 'public')
},
compress: true,
port: 3000,
hot: true
}
};
性能监控集成
javascript
// src/services/PerformanceService.js
class PerformanceService {
constructor(config) {
this.config = config;
this.metrics = new Map();
this.reporters = new Set();
this.samplingInterval = null;
}
async init() {
// 初始化性能监控
this.setupPerformanceMonitoring();
// 设置性能采样
this.setupSampling();
// 初始化报告器
this.setupReporters();
}
setupPerformanceMonitoring() {
// 监控帧率
this.monitorFPS();
// 监控内存使用
if (this.config.memoryMonitoring) {
this.monitorMemory();
}
// 监控加载时间
this.monitorLoadTimes();
}
monitorFPS() {
let frameCount = 0;
let lastTime = performance.now();
const checkFPS = () => {
frameCount++;
const currentTime = performance.now();
if (currentTime >= lastTime + 1000) {
const fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
this.recordMetric('fps', fps);
frameCount = 0;
lastTime = currentTime;
}
requestAnimationFrame(checkFPS);
};
checkFPS();
}
monitorMemory() {
if (performance.memory) {
setInterval(() => {
const memory = performance.memory;
this.recordMetric('memory.used', Math.round(memory.usedJSHeapSize / 1048576));
this.recordMetric('memory.total', Math.round(memory.totalJSHeapSize / 1048576));
this.recordMetric('memory.limit', Math.round(memory.jsHeapSizeLimit / 1048576));
}, 5000);
}
}
recordMetric(name, value, tags = {}) {
const timestamp = Date.now();
const metric = { name, value, timestamp, tags };
this.metrics.set(name, metric);
// 触发指标更新事件
this.emitMetricUpdate(metric);
}
emitMetricUpdate(metric) {
this.reporters.forEach(reporter => {
try {
reporter.onMetricUpdate(metric);
} catch (error) {
console.error('Reporter error:', error);
}
});
}
// 添加性能报告器
addReporter(reporter) {
this.reporters.add(reporter);
}
// 获取性能报告
getReport() {
const report = {
timestamp: Date.now(),
metrics: Array.from(this.metrics.values()),
summary: this.generateSummary()
};
return report;
}
generateSummary() {
const fps = this.metrics.get('fps');
const memory = this.metrics.get('memory.used');
return {
fps: fps ? fps.value : 0,
memory: memory ? memory.value : 0,
status: this.getPerformanceStatus()
};
}
getPerformanceStatus() {
const fps = this.metrics.get('fps');
if (!fps) return 'unknown';
if (fps.value < 30) return 'poor';
if (fps.value < 50) return 'fair';
return 'good';
}
async destroy() {
if (this.samplingInterval) {
clearInterval(this.samplingInterval);
}
this.reporters.clear();
this.metrics.clear();
}
}
通过这种企业级架构设计,Three.js应用可以获得更好的可维护性、可扩展性和可靠性,满足大型项目的开发需求。这种架构也为团队协作、持续集成和性能优化提供了坚实的基础。