第57节:Three.js企业级应用架构

概述

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

企业级Three.js架构:
企业级Three.js应用 应用架构层 开发工具层 运维部署层 模块化设计 状态管理 服务抽象 开发环境 构建系统 质量保证 持续集成 性能监控 错误追踪 代码可维护性 开发效率 部署可靠性

企业级架构设计原则

核心设计原则

原则 企业级实现 收益
单一职责 模块功能专注,职责清晰 易于测试和维护
开闭原则 对扩展开放,对修改关闭 系统稳定性
依赖倒置 依赖抽象而非具体实现 解耦和灵活性
接口隔离 细粒度接口设计 减少不必要的依赖
迪米特法则 最小知识原则 降低耦合度

企业级技术要求

  1. 可维护性

    • 清晰的代码组织结构
    • 完善的文档和注释
    • 统一的代码规范
  2. 可扩展性

    • 插件化架构
    • 配置驱动开发
    • 微前端支持
  3. 性能要求

    • 内存泄漏防护
    • 渲染性能优化
    • 加载策略优化

完整企业级架构实现

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应用可以获得更好的可维护性、可扩展性和可靠性,满足大型项目的开发需求。这种架构也为团队协作、持续集成和性能优化提供了坚实的基础。

相关推荐
sali-tec1 小时前
C# 基于halcon的视觉工作流-章62 点云采样
开发语言·图像处理·人工智能·算法·计算机视觉
芳草萋萋鹦鹉洲哦2 小时前
【vue】调用同页面其他组件方法几种新思路
前端·javascript·vue.js
没有bug.的程序员2 小时前
JVM 整体架构:一套虚拟机的心脏与血管
java·jvm·spring boot·spring cloud·架构
巴啦啦臭魔仙2 小时前
uniapp scroll-view自定义下拉刷新的坑
前端·javascript·uni-app
晨枫阳2 小时前
不同语言的元组对比
java·前端·javascript
喝养乐多长不高2 小时前
JAVA微服务脚手架项目详解(上)
微服务·云原生·架构
这人很懒没留下什么2 小时前
SpringBoot2.7.4整合Oauth2
开发语言·lua
ZHOUZAIHUI2 小时前
WSL(Ubuntu24.04) 安装PostgreSQL
开发语言·后端·scala
Y***K4343 小时前
后端缓存策略设计,多级缓存架构实践
缓存·架构