当前位置: 首页 > article >正文

JavaScript系列(33)--微前端架构详解

JavaScript微前端架构详解 🏗️

今天,让我们深入了解JavaScript的微前端架构,这是一种用于构建和管理大型前端应用的现代架构模式。

微前端基础概念 🌟

💡 小知识:微前端是一种将前端应用分解成更小、更易管理的独立部分的架构风格。每个部分可以由不同的团队独立开发、测试和部署,最终组合成一个完整的应用。

基本实现方案 📊

// 1. 基础路由分发
class MicroFrontendRouter {
    constructor() {
        this.routes = new Map();
        this.container = null;
    }
    
    setContainer(containerId) {
        this.container = document.getElementById(containerId);
    }
    
    registerApp(route, loadApp) {
        this.routes.set(route, loadApp);
    }
    
    async navigateTo(route) {
        if (!this.routes.has(route)) {
            throw new Error(`Route ${route} not found`);
        }
        
        const loadApp = this.routes.get(route);
        const app = await loadApp();
        
        this.container.innerHTML = '';
        this.container.appendChild(app);
    }
}

// 2. 应用加载器
class AppLoader {
    constructor(baseUrl) {
        this.baseUrl = baseUrl;
        this.loadedScripts = new Set();
        this.loadedStyles = new Set();
    }
    
    async loadScript(url) {
        if (this.loadedScripts.has(url)) {
            return;
        }
        
        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = this.baseUrl + url;
            script.onload = () => {
                this.loadedScripts.add(url);
                resolve();
            };
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }
    
    async loadStyle(url) {
        if (this.loadedStyles.has(url)) {
            return;
        }
        
        return new Promise((resolve, reject) => {
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = this.baseUrl + url;
            link.onload = () => {
                this.loadedStyles.add(url);
                resolve();
            };
            link.onerror = reject;
            document.head.appendChild(link);
        });
    }
}

// 3. 沙箱环境
class MicroAppSandbox {
    constructor(appName) {
        this.appName = appName;
        this.windowSnapshot = {};
        this.modifiedProps = new Set();
    }
    
    activate() {
        // 保存当前window状态
        this.windowSnapshot = this.snapshotWindow();
        
        // 创建代理对象
        return new Proxy(window, {
            set: (target, prop, value) => {
                if (!this.modifiedProps.has(prop)) {
                    this.modifiedProps.add(prop);
                }
                target[prop] = value;
                return true;
            },
            get: (target, prop) => {
                return target[prop];
            }
        });
    }
    
    deactivate() {
        // 恢复window状态
        this.restoreWindow();
        this.modifiedProps.clear();
    }
    
    snapshotWindow() {
        const snapshot = {};
        for (const prop in window) {
            if (window.hasOwnProperty(prop)) {
                snapshot[prop] = window[prop];
            }
        }
        return snapshot;
    }
    
    restoreWindow() {
        this.modifiedProps.forEach(prop => {
            if (prop in this.windowSnapshot) {
                window[prop] = this.windowSnapshot[prop];
            } else {
                delete window[prop];
            }
        });
    }
}

高级实现模式 🚀

// 1. 通信系统
class MessageBus {
    constructor() {
        this.subscribers = new Map();
    }
    
    subscribe(topic, callback, appName) {
        if (!this.subscribers.has(topic)) {
            this.subscribers.set(topic, new Map());
        }
        
        const topicSubscribers = this.subscribers.get(topic);
        if (!topicSubscribers.has(appName)) {
            topicSubscribers.set(appName, new Set());
        }
        
        topicSubscribers.get(appName).add(callback);
        
        return () => {
            const callbacks = topicSubscribers.get(appName);
            callbacks.delete(callback);
            if (callbacks.size === 0) {
                topicSubscribers.delete(appName);
            }
        };
    }
    
    publish(topic, data, sourceApp) {
        if (!this.subscribers.has(topic)) return;
        
        const topicSubscribers = this.subscribers.get(topic);
        for (const [appName, callbacks] of topicSubscribers) {
            if (appName !== sourceApp) {
                callbacks.forEach(callback => callback(data, sourceApp));
            }
        }
    }
}

// 2. 状态管理
class SharedState {
    constructor() {
        this.state = {};
        this.listeners = new Map();
    }
    
    setState(path, value, appName) {
        const oldValue = this.getState(path);
        if (oldValue === value) return;
        
        this.setNestedValue(this.state, path.split('.'), value);
        this.notifyListeners(path, value, oldValue, appName);
    }
    
    getState(path) {
        return this.getNestedValue(this.state, path.split('.'));
    }
    
    subscribe(path, callback, appName) {
        if (!this.listeners.has(path)) {
            this.listeners.set(path, new Map());
        }
        
        const pathListeners = this.listeners.get(path);
        if (!pathListeners.has(appName)) {
            pathListeners.set(appName, new Set());
        }
        
        pathListeners.get(appName).add(callback);
        
        return () => {
            const callbacks = pathListeners.get(appName);
            callbacks.delete(callback);
            if (callbacks.size === 0) {
                pathListeners.delete(appName);
            }
        };
    }
    
    setNestedValue(obj, path, value) {
        const lastKey = path.pop();
        const target = path.reduce((obj, key) => {
            if (!(key in obj)) obj[key] = {};
            return obj[key];
        }, obj);
        target[lastKey] = value;
    }
    
    getNestedValue(obj, path) {
        return path.reduce((obj, key) => obj && obj[key], obj);
    }
    
    notifyListeners(path, newValue, oldValue, sourceApp) {
        if (this.listeners.has(path)) {
            const pathListeners = this.listeners.get(path);
            for (const [appName, callbacks] of pathListeners) {
                if (appName !== sourceApp) {
                    callbacks.forEach(callback => 
                        callback(newValue, oldValue)
                    );
                }
            }
        }
    }
}

// 3. 生命周期管理
class LifecycleManager {
    constructor() {
        this.apps = new Map();
    }
    
    registerApp(appName, lifecycles) {
        this.apps.set(appName, {
            bootstrap: lifecycles.bootstrap || (() => Promise.resolve()),
            mount: lifecycles.mount || (() => Promise.resolve()),
            unmount: lifecycles.unmount || (() => Promise.resolve()),
            update: lifecycles.update || (() => Promise.resolve()),
            status: 'NOT_LOADED'
        });
    }
    
    async bootstrapApp(appName) {
        const app = this.apps.get(appName);
        if (!app) throw new Error(`App ${appName} not found`);
        
        if (app.status !== 'NOT_LOADED') return;
        
        try {
            await app.bootstrap();
            app.status = 'NOT_MOUNTED';
        } catch (error) {
            app.status = 'LOAD_ERROR';
            throw error;
        }
    }
    
    async mountApp(appName) {
        const app = this.apps.get(appName);
        if (!app) throw new Error(`App ${appName} not found`);
        
        if (app.status !== 'NOT_MOUNTED') return;
        
        try {
            await app.mount();
            app.status = 'MOUNTED';
        } catch (error) {
            app.status = 'MOUNT_ERROR';
            throw error;
        }
    }
    
    async unmountApp(appName) {
        const app = this.apps.get(appName);
        if (!app) throw new Error(`App ${appName} not found`);
        
        if (app.status !== 'MOUNTED') return;
        
        try {
            await app.unmount();
            app.status = 'NOT_MOUNTED';
        } catch (error) {
            app.status = 'UNMOUNT_ERROR';
            throw error;
        }
    }
}

实际应用场景 💼

// 1. 微前端容器应用
class MicroFrontendContainer {
    constructor() {
        this.router = new MicroFrontendRouter();
        this.messageBus = new MessageBus();
        this.sharedState = new SharedState();
        this.lifecycleManager = new LifecycleManager();
    }
    
    async registerApp(config) {
        const {
            name,
            route,
            loadApp,
            lifecycles
        } = config;
        
        // 注册路由
        this.router.registerApp(route, async () => {
            const app = await loadApp();
            return app;
        });
        
        // 注册生命周期
        this.lifecycleManager.registerApp(name, lifecycles);
        
        // 创建沙箱环境
        const sandbox = new MicroAppSandbox(name);
        
        // 注册通信接口
        const api = {
            messageBus: this.messageBus,
            sharedState: this.sharedState,
            sandbox
        };
        
        return api;
    }
    
    async start() {
        window.addEventListener('popstate', () => {
            this.handleRouteChange();
        });
        
        await this.handleRouteChange();
    }
    
    async handleRouteChange() {
        const route = window.location.pathname;
        await this.router.navigateTo(route);
    }
}

// 2. 微应用实现
class MicroApp {
    constructor(name, api) {
        this.name = name;
        this.messageBus = api.messageBus;
        this.sharedState = api.sharedState;
        this.sandbox = api.sandbox;
    }
    
    async bootstrap() {
        // 初始化应用
        this.sandbox.activate();
        
        // 订阅消息
        this.unsubscribe = this.messageBus.subscribe(
            'global',
            this.handleMessage.bind(this),
            this.name
        );
        
        // 监听状态变化
        this.unsubscribeState = this.sharedState.subscribe(
            'user',
            this.handleStateChange.bind(this),
            this.name
        );
    }
    
    async mount() {
        // 渲染应用
        this.render();
    }
    
    async unmount() {
        // 清理资源
        this.unsubscribe();
        this.unsubscribeState();
        this.sandbox.deactivate();
    }
    
    handleMessage(data, sourceApp) {
        console.log(`Received message from ${sourceApp}:`, data);
    }
    
    handleStateChange(newValue, oldValue) {
        console.log('State changed:', { newValue, oldValue });
        this.update();
    }
    
    render() {
        // 实现具体的渲染逻辑
    }
    
    update() {
        // 实现更新逻辑
    }
}

// 3. 应用间通信示例
class AppCommunication {
    constructor(messageBus, sharedState) {
        this.messageBus = messageBus;
        this.sharedState = sharedState;
    }
    
    sendMessage(topic, data, sourceApp) {
        this.messageBus.publish(topic, data, sourceApp);
    }
    
    updateState(path, value, sourceApp) {
        this.sharedState.setState(path, value, sourceApp);
    }
}

性能优化技巧 ⚡

// 1. 资源预加载
class ResourcePreloader {
    constructor() {
        this.preloadQueue = new Map();
        this.loading = new Set();
    }
    
    addToQueue(resources) {
        resources.forEach(resource => {
            if (!this.preloadQueue.has(resource.url)) {
                this.preloadQueue.set(resource.url, {
                    type: resource.type,
                    priority: resource.priority || 0
                });
            }
        });
    }
    
    async preload() {
        // 按优先级排序
        const sortedResources = Array.from(this.preloadQueue.entries())
            .sort((a, b) => b[1].priority - a[1].priority);
        
        for (const [url, config] of sortedResources) {
            if (this.loading.has(url)) continue;
            
            this.loading.add(url);
            
            try {
                if (config.type === 'script') {
                    await this.preloadScript(url);
                } else if (config.type === 'style') {
                    await this.preloadStyle(url);
                }
            } finally {
                this.loading.delete(url);
                this.preloadQueue.delete(url);
            }
        }
    }
    
    preloadScript(url) {
        return new Promise((resolve, reject) => {
            const link = document.createElement('link');
            link.rel = 'preload';
            link.as = 'script';
            link.href = url;
            link.onload = resolve;
            link.onerror = reject;
            document.head.appendChild(link);
        });
    }
    
    preloadStyle(url) {
        return new Promise((resolve, reject) => {
            const link = document.createElement('link');
            link.rel = 'preload';
            link.as = 'style';
            link.href = url;
            link.onload = resolve;
            link.onerror = reject;
            document.head.appendChild(link);
        });
    }
}

// 2. 应用缓存
class AppCache {
    constructor(maxSize = 5) {
        this.cache = new Map();
        this.maxSize = maxSize;
    }
    
    set(appName, instance) {
        if (this.cache.size >= this.maxSize) {
            const oldestApp = this.cache.keys().next().value;
            this.delete(oldestApp);
        }
        
        this.cache.set(appName, {
            instance,
            timestamp: Date.now()
        });
    }
    
    get(appName) {
        const entry = this.cache.get(appName);
        if (entry) {
            entry.timestamp = Date.now();
            return entry.instance;
        }
        return null;
    }
    
    delete(appName) {
        const instance = this.cache.get(appName);
        if (instance) {
            // 清理应用资源
            if (instance.unmount) {
                instance.unmount();
            }
            this.cache.delete(appName);
        }
    }
    
    clear() {
        for (const [appName] of this.cache) {
            this.delete(appName);
        }
    }
}

// 3. 性能监控
class PerformanceMonitor {
    constructor() {
        this.metrics = new Map();
    }
    
    startMeasure(appName, phase) {
        const key = `${appName}-${phase}`;
        performance.mark(`${key}-start`);
    }
    
    endMeasure(appName, phase) {
        const key = `${appName}-${phase}`;
        performance.mark(`${key}-end`);
        
        performance.measure(
            key,
            `${key}-start`,
            `${key}-end`
        );
        
        const measures = performance.getEntriesByName(key);
        const duration = measures[measures.length - 1].duration;
        
        if (!this.metrics.has(appName)) {
            this.metrics.set(appName, new Map());
        }
        
        const appMetrics = this.metrics.get(appName);
        if (!appMetrics.has(phase)) {
            appMetrics.set(phase, []);
        }
        
        appMetrics.get(phase).push(duration);
        
        // 清理marks
        performance.clearMarks(`${key}-start`);
        performance.clearMarks(`${key}-end`);
        performance.clearMeasures(key);
    }
    
    getMetrics(appName, phase) {
        const appMetrics = this.metrics.get(appName);
        if (!appMetrics) return null;
        
        const phaseMetrics = appMetrics.get(phase);
        if (!phaseMetrics) return null;
        
        return {
            average: phaseMetrics.reduce((a, b) => a + b, 0) / phaseMetrics.length,
            min: Math.min(...phaseMetrics),
            max: Math.max(...phaseMetrics),
            count: phaseMetrics.length
        };
    }
}

最佳实践建议 💡

  1. 应用隔离
// 1. 样式隔离
class StyleIsolator {
    constructor(appName) {
        this.appName = appName;
    }
    
    wrapStyles(styles) {
        return styles.replace(
            /([^}]*){([^}]*)}/g,
            `[data-app="${this.appName}"] $1{$2}`
        );
    }
    
    injectStyles(styles) {
        const styleElement = document.createElement('style');
        styleElement.setAttribute('data-app', this.appName);
        styleElement.textContent = this.wrapStyles(styles);
        document.head.appendChild(styleElement);
        
        return () => styleElement.remove();
    }
}

// 2. 全局变量隔离
class GlobalVarIsolator {
    constructor() {
        this.originalValues = new Map();
    }
    
    isolate(variables) {
        variables.forEach(varName => {
            if (varName in window) {
                this.originalValues.set(varName, window[varName]);
            }
            window[varName] = undefined;
        });
    }
    
    restore() {
        for (const [varName, value] of this.originalValues) {
            if (value === undefined) {
                delete window[varName];
            } else {
                window[varName] = value;
            }
        }
        this.originalValues.clear();
    }
}

// 3. 错误边界
class ErrorBoundary {
    constructor(appName, onError) {
        this.appName = appName;
        this.onError = onError;
    }
    
    wrap(fn) {
        return async (...args) => {
            try {
                return await fn(...args);
            } catch (error) {
                this.onError(error, this.appName);
                throw error;
            }
        };
    }
}

结语 📝

微前端架构为大型前端应用提供了一种可扩展的解决方案。通过本文,我们学习了:

  1. 微前端的基本概念和实现方案
  2. 高级实现模式和通信机制
  3. 实际应用场景和示例
  4. 性能优化技巧
  5. 最佳实践和注意事项

💡 学习建议:在采用微前端架构时,要注意平衡架构的复杂性和业务需求。不是所有项目都需要微前端架构,要根据实际情况选择合适的解决方案。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻


http://www.kler.cn/a/510761.html

相关文章:

  • 以租赁合同的例子讲清楚 开源协议原理和区别
  • 流量分析复现(第十八届信息安全大赛 第二届长城杯 )
  • 【深度学习】Huber Loss详解
  • Android SystemUI——CarSystemBar视图解析(十一)
  • 【RAG落地利器】向量数据库Qdrant使用教程
  • 头歌答案--爬虫实战
  • C语言之装甲车库车辆动态监控辅助记录系统
  • 第一次在Gitee建仓传码
  • 迈向 “全能管家” 之路:机器人距离终极蜕变还需几步?
  • 多平台下Informatica在医疗数据抽取中的应用
  • SpringCloud -根据服务名获取服务运行实例并进行负载均衡
  • 中型项目中 HTTP 的挑战与解决方案
  • 大型系统中 HTTP 的优化与部署
  • STM32使用DSP库 Keil方式添加
  • 数据可视化大屏设计与实现
  • OpenWrt 中使用 LuCI 界面部署 Docker 镜像
  • 【C++学习篇】哈希表的实现
  • vue+高德API搭建前端3D交通页面
  • flutter 使用google_mlkit_image_labeling做图片识别
  • Spring Boot 整合 log4j2 日志配置教程
  • 洛谷P4868 Preprefix sum
  • 基于ESP32+VUE+JAVA+Ngnix的一个小型固件编译系统
  • Top期刊算法!RIME-CNN-BiLSTM-Attention系列四模型多变量时序预测
  • 最新版Edge浏览器加载ActiveX控件技术——allWebPlugin中间件之awp_CreateActiveXObject接口用法
  • hydra破解密码
  • USB3020任意波形发生器4路16位同步模拟量输出卡1MS/s频率 阿尔泰科技