Skip to content

前端工程化面试题

1. 工程化概述

问题:什么是前端工程化?为什么要进行前端工程化?

答案

前端工程化定义: 前端工程化是指使用软件工程的技术和方法来进行前端项目的开发、维护和管理,以提高开发效率、代码质量和项目可维护性。

工程化的核心目标

javascript
// 1. 规范化
// - 代码规范:ESLint、Prettier
// - 提交规范:Commitizen、Husky
// - 目录规范:统一的目录结构

// 2. 自动化
// - 自动化构建:Webpack、Vite、Rollup
// - 自动化测试:Jest、Cypress
// - 自动化部署:CI/CD

// 3. 模块化
// - 代码模块化:ES Modules、CommonJS
// - 组件模块化:Vue、React 组件
// - 样式模块化:CSS Modules、Styled Components

// 4. 组件化
// - UI 组件库:Element UI、Ant Design
// - 业务组件:可复用的业务逻辑
// - 工具组件:通用的工具函数

// 5. 性能优化
// - 代码压缩、Tree Shaking
// - 懒加载、预加载
// - 缓存策略

工程化的好处

  • 提高开发效率
  • 保证代码质量
  • 降低维护成本
  • 提升团队协作
  • 优化用户体验

2. 构建工具

问题:常用的前端构建工具有哪些?它们有什么区别?

答案

主流构建工具对比

工具特点适用场景
Webpack功能强大、生态丰富、配置复杂大型项目、复杂应用
Vite快速冷启动、HMR、配置简单现代项目、快速开发
Rollup输出优化、Tree Shaking 好库开发、工具库
Parcel零配置、开箱即用小型项目、原型开发
esbuild极速编译、Go 编写大型项目、性能敏感
SWCRust 编写、极速编译替代 Babel、大型项目

Webpack 配置

javascript
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // 入口
  entry: './src/index.js',
  
  // 输出
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash:8].js',
    clean: true
  },
  
  // 模块处理
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource'
      }
    ]
  },
  
  // 插件
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:8].css'
    })
  ],
  
  // 开发服务器
  devServer: {
    static: './dist',
    hot: true,
    port: 3000
  },
  
  // 优化
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
};

Vite 配置

javascript
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';

export default defineConfig({
  plugins: [vue()],
  
  // 路径别名
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    }
  },
  
  // 开发服务器
  server: {
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true
      }
    }
  },
  
  // 构建
  build: {
    outDir: 'dist',
    assetsDir: 'assets',
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['vue', 'vue-router']
        }
      }
    }
  },
  
  // CSS
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "./src/styles/vars.scss";`
      }
    }
  }
});

构建工具选择建议

javascript
// 1. 新项目推荐 Vite
// - 开发体验好
// - 构建速度快
// - 配置简单

// 2. 大型项目考虑 Webpack
// - 生态成熟
// - 配置灵活
// - 社区支持好

// 3. 库开发推荐 Rollup
// - 输出优化
// - Tree Shaking 好
// - 配置简洁

// 4. 性能敏感项目考虑 esbuild/SWC
// - 编译速度极快
// - 适合大型项目

3. 模块化

问题:前端模块化有哪些规范?如何使用?

答案

模块化规范

javascript
// 1. CommonJS (Node.js)
// math.js
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;

module.exports = { add, subtract };

// main.js
const { add, subtract } = require('./math');
console.log(add(1, 2));

// 2. ES Modules (ES6+)
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

export default function multiply(a, b) {
  return a * b;
}

// main.js
import multiply, { add, subtract } from './math.js';
import * as math from './math.js';

// 3. AMD (RequireJS)
define(['dependency'], function(dependency) {
  return {
    method: function() {}
  };
});

// 4. UMD (Universal Module Definition)
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(['b'], factory);
  } else if (typeof module === 'object' && module.exports) {
    module.exports = factory(require('b'));
  } else {
    root.returnExports = factory(root.b);
  }
}(typeof self !== 'undefined' ? self : this, function (b) {
  return {};
}));

模块加载原理

javascript
// ES Modules 加载过程
// 1. 构建阶段:解析模块依赖,创建模块映射
// 2. 实例化阶段:为模块分配内存,建立导入导出连接
// 3. 执行阶段:执行模块代码,填充内存

// 循环依赖处理
// a.js
import { bar } from './b.js';
export function foo() {
  console.log('foo');
  bar();
}

// b.js
import { foo } from './a.js';
export function bar() {
  console.log('bar');
  // foo(); // 可能导致无限循环
}

// 解决方案:使用函数延迟执行
// a.js
import { bar } from './b.js';
export function foo() {
  console.log('foo');
}

// b.js
import { foo } from './a.js';
export function bar() {
  console.log('bar');
  foo(); // 安全调用
}

Tree Shaking

javascript
// Tree Shaking 原理
// 1. 基于 ES Modules 的静态分析
// 2. 只打包使用到的代码
// 3. 需要 sideEffects 配置

// utils.js
export function used() {
  return 'used';
}

export function unused() {
  return 'unused';
}

// main.js
import { used } from './utils.js';
console.log(used());

// package.json
{
  "sideEffects": false,
  "sideEffects": [
    "*.css",
    "*.scss"
  ]
}

4. 代码规范

问题:如何保证代码规范?常用的工具有哪些?

答案

ESLint 配置

javascript
// .eslintrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
    es2021: true
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended'
  ],
  parserOptions: {
    ecmaVersion: 2021,
    sourceType: 'module',
    parser: '@typescript-eslint/parser'
  },
  plugins: ['vue', '@typescript-eslint'],
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'vue/multi-word-component-names': 'off',
    '@typescript-eslint/no-explicit-any': 'off'
  },
  overrides: [
    {
      files: ['*.vue'],
      rules: {
        'vue/no-multiple-template-root': 'off'
      }
    }
  ]
};

// .eslintignore
node_modules
dist
build
*.min.js

Prettier 配置

javascript
// .prettierrc
{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5",
  "printWidth": 100,
  "bracketSpacing": true,
  "arrowParens": "avoid",
  "endOfLine": "lf"
}

// .prettierignore
node_modules
dist
build
*.min.js

Husky + lint-staged

javascript
// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "lint-staged": {
    "*.{js,jsx,vue,ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{css,scss,less}": [
      "stylelint --fix",
      "prettier --write"
    ]
  }
}

// commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'feat', 'fix', 'docs', 'style', 'refactor',
      'perf', 'test', 'chore', 'revert'
    ]],
    'subject-full-stop': [0, 'never'],
    'subject-case': [0, 'never']
  }
};

// 提交格式
// feat: 添加新功能
// fix: 修复 bug
// docs: 更新文档
// style: 代码格式调整
// refactor: 重构代码
// perf: 性能优化
// test: 添加测试
// chore: 构建过程或辅助工具的变动

Stylelint 配置

javascript
// .stylelintrc.js
module.exports = {
  extends: [
    'stylelint-config-standard',
    'stylelint-config-standard-scss',
    'stylelint-config-recommended-vue'
  ],
  rules: {
    'selector-class-pattern': null,
    'scss/at-import-partial-extension': null
  }
};

5. 包管理工具

问题:npm、yarn、pnpm 有什么区别?

答案

包管理工具对比

特性npmyarnpnpm
安装速度一般最快
磁盘占用
依赖管理嵌套/扁平扁平内容可寻址
锁文件package-lock.jsonyarn.lockpnpm-lock.yaml
工作区支持支持支持
离线模式支持支持支持

pnpm 优势

bash
# 1. 安装速度快
pnpm install

# 2. 磁盘占用小(硬链接)
# 所有项目共享同一份依赖

# 3. 严格依赖管理
# 不会访问未声明的依赖

# 4. 支持 monorepo
pnpm-workspace.yaml

package.json 配置

json
{
  "name": "my-project",
  "version": "1.0.0",
  "description": "项目描述",
  "main": "index.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint": "eslint . --ext .vue,.js,.jsx,.ts,.tsx",
    "lint:fix": "eslint . --ext .vue,.js,.jsx,.ts,.tsx --fix",
    "format": "prettier --write ."
  },
  "dependencies": {
    "vue": "^3.3.0"
  },
  "devDependencies": {
    "vite": "^4.4.0",
    "eslint": "^8.0.0"
  },
  "engines": {
    "node": ">=16.0.0",
    "pnpm": ">=8.0.0"
  },
  "packageManager": "pnpm@8.6.0"
}

版本管理

javascript
// 版本号规则:主版本.次版本.修订号
// ^1.2.3 - 兼容 1.x.x,不低于 1.2.3
// ~1.2.3 - 兼容 1.2.x,不低于 1.2.3
// 1.2.3 - 精确版本

// 锁定版本
// package-lock.json / yarn.lock / pnpm-lock.yaml

// 更新依赖
npm update          // 更新到最新兼容版本
npm outdated        // 查看可更新依赖
npm audit           // 安全检查
npm audit fix       // 自动修复安全问题

6. CI/CD

问题:什么是 CI/CD?如何配置前端项目的 CI/CD?

答案

CI/CD 概念

  • CI (Continuous Integration):持续集成,频繁地将代码集成到主干
  • CD (Continuous Delivery/Deployment):持续交付/部署,自动将代码部署到生产环境

GitHub Actions 配置

yaml
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  lint-and-test:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'pnpm'
      
      - name: Install pnpm
        uses: pnpm/action-setup@v2
        with:
          version: 8
      
      - name: Install dependencies
        run: pnpm install
      
      - name: Run linter
        run: pnpm lint
      
      - name: Run tests
        run: pnpm test
      
      - name: Build project
        run: pnpm build

  deploy:
    needs: lint-and-test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
      - name: Deploy to production
        run: |
          echo "Deploying to production..."
          # 部署脚本

GitLab CI 配置

yaml
# .gitlab-ci.yml
stages:
  - install
  - lint
  - test
  - build
  - deploy

variables:
  NODE_VERSION: "18"
  PNPM_VERSION: "8"

install:
  stage: install
  image: node:18
  script:
    - npm install -g pnpm@${PNPM_VERSION}
    - pnpm install
  cache:
    paths:
      - node_modules/
      - .pnpm-store/

lint:
  stage: lint
  image: node:18
  script:
    - pnpm lint
  dependencies:
    - install

test:
  stage: test
  image: node:18
  script:
    - pnpm test
  dependencies:
    - install

build:
  stage: build
  image: node:18
  script:
    - pnpm build
  artifacts:
    paths:
      - dist/
  dependencies:
    - install

deploy:
  stage: deploy
  image: node:18
  script:
    - echo "Deploying..."
  only:
    - main

Docker 部署

dockerfile
# Dockerfile
# 构建阶段
FROM node:18-alpine AS builder

WORKDIR /app

# 安装 pnpm
RUN npm install -g pnpm

# 复制依赖文件
COPY package.json pnpm-lock.yaml ./

# 安装依赖
RUN pnpm install --frozen-lockfile

# 复制源代码
COPY . .

# 构建
RUN pnpm build

# 生产阶段
FROM nginx:alpine

# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html

# 复制 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
nginx
# nginx.conf
server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;

    # 缓存静态资源
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 前端路由支持
    location / {
        try_files $uri $uri/ /index.html;
    }
}

7. Monorepo

问题:什么是 Monorepo?如何管理 Monorepo 项目?

答案

Monorepo vs Polyrepo

特性MonorepoPolyrepo
代码共享容易困难
版本管理统一分散
构建优化可以优化难以优化
团队协作紧密松散
权限管理复杂简单

Monorepo 工具

javascript
// 1. pnpm workspace
// pnpm-workspace.yaml
packages:
  - 'packages/*'
  - 'apps/*'

// 2. Turborepo
// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**"]
    },
    "lint": {
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

// 3. Nx
// nx.json
{
  "extends": "nx/presets/npm.json",
  "tasksRunnerOptions": {
    "default": {
      "runner": "nx/tasks-runners/default",
      "options": {
        "cacheableOperations": ["build", "lint", "test"]
      }
    }
  }
}

// 4. Lerna
// lerna.json
{
  "version": "independent",
  "npmClient": "pnpm",
  "command": {
    "publish": {
      "conventionalCommits": true
    }
  }
}

Monorepo 目录结构

my-monorepo/
├── apps/
│   ├── web/              # Web 应用
│   ├── admin/            # 管理后台
│   └── mobile/           # 移动端应用
├── packages/
│   ├── ui/               # UI 组件库
│   ├── utils/            # 工具函数
│   ├── hooks/            # 通用 Hooks
│   └── config/           # 共享配置
├── package.json
├── pnpm-workspace.yaml
└── turbo.json

包间依赖管理

json
// packages/ui/package.json
{
  "name": "@myorg/ui",
  "version": "1.0.0",
  "main": "dist/index.js",
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w"
  },
  "dependencies": {
    "@myorg/utils": "workspace:*"
  }
}

// apps/web/package.json
{
  "name": "@myorg/web",
  "dependencies": {
    "@myorg/ui": "workspace:*",
    "@myorg/utils": "workspace:*"
  }
}

8. 测试

问题:前端测试有哪些类型?如何配置测试环境?

答案

测试类型

javascript
// 1. 单元测试
// 测试单个函数或组件
import { add } from './math';

test('adds 1 + 2 to equal 3', () => {
  expect(add(1, 2)).toBe(3);
});

// 2. 集成测试
// 测试多个模块的协作
import { createApp } from './app';

test('app initializes correctly', async () => {
  const app = await createApp();
  expect(app.isReady()).toBe(true);
});

// 3. E2E 测试
// 测试完整用户流程
describe('User Login', () => {
  it('should login successfully', () => {
    cy.visit('/login');
    cy.get('[data-testid="username"]').type('user');
    cy.get('[data-testid="password"]').type('password');
    cy.get('[data-testid="submit"]').click();
    cy.url().should('include', '/dashboard');
  });
});

// 4. 快照测试
// 测试 UI 是否发生变化
test('Button renders correctly', () => {
  const { container } = render(<Button>Click me</Button>);
  expect(container).toMatchSnapshot();
});

// 5. 视觉回归测试
// 测试 UI 视觉效果

Jest 配置

javascript
// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json'],
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest'
  },
  moduleNameMapping: {
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  collectCoverageFrom: [
    'src/**/*.{js,jsx,ts,tsx}',
    '!src/**/*.d.ts'
  ],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    }
  }
};

// jest.setup.js
import '@testing-library/jest-dom';

// 测试示例
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

test('Button click handler is called', () => {
  const handleClick = jest.fn();
  render(<Button onClick={handleClick}>Click me</Button>);
  
  fireEvent.click(screen.getByText('Click me'));
  expect(handleClick).toHaveBeenCalledTimes(1);
});

Cypress E2E 测试

javascript
// cypress/e2e/login.cy.js
describe('Login', () => {
  beforeEach(() => {
    cy.visit('/login');
  });

  it('displays login form', () => {
    cy.get('[data-testid="login-form"]').should('be.visible');
    cy.get('[data-testid="username"]').should('exist');
    cy.get('[data-testid="password"]').should('exist');
  });

  it('logs in successfully', () => {
    cy.get('[data-testid="username"]').type('testuser');
    cy.get('[data-testid="password"]').type('password123');
    cy.get('[data-testid="submit"]').click();
    
    cy.url().should('include', '/dashboard');
    cy.get('[data-testid="welcome"]').should('contain', 'Welcome');
  });

  it('shows error for invalid credentials', () => {
    cy.get('[data-testid="username"]').type('wronguser');
    cy.get('[data-testid="password"]').type('wrongpassword');
    cy.get('[data-testid="submit"]').click();
    
    cy.get('[data-testid="error"]').should('be.visible');
  });
});

// cypress.config.js
const { defineConfig } = require('cypress');

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    viewportWidth: 1280,
    viewportHeight: 720,
    video: false,
    screenshotOnRunFailure: true
  }
});

9. 性能监控

问题:如何监控前端性能?

答案

性能指标监控

javascript
// 1. Web Vitals
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

function sendToAnalytics(metric) {
  const body = JSON.stringify(metric);
  
  // 使用 sendBeacon 发送数据
  if (navigator.sendBeacon) {
    navigator.sendBeacon('/analytics', body);
  } else {
    fetch('/analytics', {
      body,
      method: 'POST',
      keepalive: true
    });
  }
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);

// 2. 自定义性能监控
class PerformanceMonitor {
  constructor() {
    this.metrics = {};
    this.init();
  }

  init() {
    // 页面加载时间
    window.addEventListener('load', () => {
      setTimeout(() => {
        this.collectNavigationTiming();
        this.collectResourceTiming();
      }, 0);
    });

    // 长任务监控
    if ('PerformanceObserver' in window) {
      const observer = new PerformanceObserver((list) => {
        for (const entry of list.getEntries()) {
          this.reportLongTask(entry);
        }
      });
      observer.observe({ entryTypes: ['longtask'] });
    }

    // 错误监控
    window.addEventListener('error', (event) => {
      this.reportError(event.error);
    });

    window.addEventListener('unhandledrejection', (event) => {
      this.reportError(event.reason);
    });
  }

  collectNavigationTiming() {
    const navigation = performance.getEntriesByType('navigation')[0];
    
    this.metrics.navigation = {
      dns: navigation.domainLookupEnd - navigation.domainLookupStart,
      tcp: navigation.connectEnd - navigation.connectStart,
      ttfb: navigation.responseStart - navigation.requestStart,
      download: navigation.responseEnd - navigation.responseStart,
      dom: navigation.domComplete - navigation.domInteractive,
      load: navigation.loadEventEnd - navigation.fetchStart
    };
  }

  collectResourceTiming() {
    const resources = performance.getEntriesByType('resource');
    
    this.metrics.resources = resources.map(r => ({
      name: r.name,
      duration: r.duration,
      size: r.transferSize
    }));
  }

  reportLongTask(entry) {
    console.warn('Long task detected:', entry.duration);
    // 上报长任务数据
  }

  reportError(error) {
    console.error('Error:', error);
    // 上报错误数据
  }
}

// 使用
const monitor = new PerformanceMonitor();

错误监控

javascript
// Sentry 集成
import * as Sentry from '@sentry/vue';

Sentry.init({
  app,
  dsn: 'your-dsn-url',
  integrations: [
    new Sentry.BrowserTracing({
      routingInstrumentation: Sentry.vueRouterInstrumentation(router)
    }),
    new Sentry.Replay()
  ],
  tracesSampleRate: 1.0,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0
});

// 自定义错误上报
function captureError(error, context) {
  Sentry.captureException(error, {
    extra: context
  });
}

10. 微前端

问题:什么是微前端?如何实现微前端架构?

答案

微前端概念: 微前端是一种架构风格,将前端应用拆分为多个独立的、可单独部署的子应用,每个子应用可以由不同的团队使用不同的技术栈开发。

微前端方案

javascript
// 1. qiankun(阿里)
// 主应用
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'app1',
    entry: '//localhost:8081',
    container: '#container',
    activeRule: '/app1'
  },
  {
    name: 'app2',
    entry: '//localhost:8082',
    container: '#container',
    activeRule: '/app2'
  }
]);

start();

// 子应用
export async function bootstrap() {
  console.log('app bootstraped');
}

export async function mount(props) {
  ReactDOM.render(<App />, props.container);
}

export async function unmount(props) {
  ReactDOM.unmountComponentAtNode(props.container);
}

// 2. Module Federation(Webpack 5)
// 主应用
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'shell',
      remotes: {
        app1: 'app1@http://localhost:3001/remoteEntry.js',
        app2: 'app1@http://localhost:3002/remoteEntry.js'
      },
      shared: ['react', 'react-dom']
    })
  ]
};

// 使用远程组件
import('app1/Button').then((Button) => {
  // 使用 Button
});

// 3. single-spa
import { registerApplication, start } from 'single-spa';

registerApplication({
  name: 'app1',
  app: () => import('./app1/app1.js'),
  activeWhen: '/app1'
});

start();

微前端通信

javascript
// 1. 通过 props 传递
// 主应用
<MicroApp 
  name="app1" 
  props={{ user, theme, onEvent: handleEvent }}
/>

// 2. 全局事件总线
class EventBus {
  constructor() {
    this.events = {};
  }

  on(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }

  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => callback(data));
    }
  }

  off(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback);
    }
  }
}

const eventBus = new EventBus();
window.eventBus = eventBus;

// 3. 共享状态(Redux、Vuex)
// 创建全局 store
const globalStore = createStore(reducer);
window.globalStore = globalStore;

微前端优缺点

javascript
// 优点:
// 1. 技术栈无关
// 2. 独立开发、部署
// 3. 团队自治
// 4. 渐进式升级

// 缺点:
// 1. 复杂度增加
// 2. 性能开销
// 3. 样式隔离问题
// 4. 公共依赖重复

// 解决方案:
// 1. 样式隔离:CSS Modules、Shadow DOM
// 2. JS 隔离:Proxy、快照
// 3. 依赖共享:Module Federation、externals