【微前端】qiankun基础

【微前端】qiankun 使用指南:从零搭建微前端项目

    • 一、什么是微前端
      • [1.1 概念](#1.1 概念)
      • [1.2 核心价值](#1.2 核心价值)
      • [1.3 为什么不用 iframe?](#1.3 为什么不用 iframe?)
    • [二、qiankun 简介](#二、qiankun 简介)
      • [2.1 什么是 qiankun](#2.1 什么是 qiankun)
      • [2.2 特性](#2.2 特性)
    • 三、快速上手
      • [3.1 项目结构](#3.1 项目结构)
      • [3.2 主应用配置](#3.2 主应用配置)
      • [3.3 微应用配置](#3.3 微应用配置)
    • 跨域问题

技术栈:qiankun + React + Webpack

一、什么是微前端

1.1 概念

微前端就是把一个超大型应用 拆分成多个独立开发、独立部署、独立运行的小应用,再通过主应用把它们整合起来。

1.2 核心价值

特性 说明
技术栈无关 主框架不限制接入应用的技术栈,微应用具备完全自主权
独立开发、独立部署 微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
增量升级 微前端是一种非常好的实施渐进式重构的手段和策略
独立运行时 每个微应用之间状态隔离,运行时状态不共享

1.3 为什么不用 iframe?

iframe 不是也能实现吗?能,但问题不少:

  • url 不同步:刷新后 iframe url 状态丢失
  • UI 不同步:DOM 结构不共享,弹窗只能在 iframe 内部显示
  • 全局上下文完全隔离:内存变量不共享,Cookie、LocalStorage 不互通
  • :每次子应用进入都是一次浏览器上下文重建、资源重新加载

二、qiankun 简介

2.1 什么是 qiankun

qiankun 是蚂蚁基于single-spa封装的微前端库。

2.2 特性

  • 任意前端框架,React/Vue/Angular/JQuery 都能接入
  • 样式隔离,微应用之间样式不会互相污染
  • JS 沙箱,全局变量/事件隔离,不怕冲突
  • 资源预加载,浏览器空闲时提前加载,切换更快

三、快速上手

3.1 项目结构

bash 复制代码
micro-frontend/
├── main-app/          # 主应用(基座)
└── micro-react/       # 微应用 - React

3.2 主应用配置

安装 qiankun

bash 复制代码
yarn add qiankun

注册微应用

在主应用入口文件中配置:

javascript 复制代码
// main-app/src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import { registerMicroApps, start } from 'qiankun'
import './index.css'

// 注册微应用
registerMicroApps([
  {
    name: 'm-app',
    entry: 'http://localhost:8001',
    container: '#subapp-container',
    activeRule: '/',
  }
])

// 启动 qiankun
start()

// 渲染容器
ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <div id="subapp-container"></div>
  </React.StrictMode>
)

主应用 HTML 结构

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>微前端主应用</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

3.3 微应用配置

修改入口文件

javascript 复制代码
// micro-react/src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'

let root: ReactDOM.Root | null = null

// 渲染函数
function render(props: any = {}) {
  const { container } = props
  const rootElement = container 
    ? container.querySelector('#root') 
    : document.getElementById('root')
  
  if (rootElement) {
    root = ReactDOM.createRoot(rootElement)
    root.render(
      <React.StrictMode>
        <App {...props} />
      </React.StrictMode>
    )
  }
}

// 判断是否在 qiankun 环境中运行
if (!(window as any).__POWERED_BY_QIANKUN__) {
  render()
}

// 导出 qiankun 生命周期函数
export async function bootstrap() {
  console.log('[React子应用] bootstrap')
}

export async function mount(props: any) {
  render(props)
}

export async function unmount() {
  root?.unmount()
  root = null
}

修改 webpack 配置

javascript 复制代码
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const packageName = require('./package.json').name;

module.exports = {
  entry: './src/index.tsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.[contenthash].js',
    clean: true,
    // qiankun 子应用必须配置
    library: `${packageName}-[name]`,
    libraryTarget: 'umd',
    chunkLoadingGlobal: `webpackJsonp_${packageName}`,
    globalObject: 'window',
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.jsx'],
  },
  module: {
    rules: [
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              ['@babel/preset-react', { runtime: 'automatic' }],
              '@babel/preset-typescript',
            ],
          },
        },
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
      title: 'React 子应用',
    }),
  ],
  devServer: {
    port: 8001,
    hot: true,
    historyApiFallback: true,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
};

跨域问题

注意:微应用必须开启 CORS,不然主应用加载不了

javascript 复制代码
// webpack devServer 配置
devServer: {
  headers: {
    'Access-Control-Allow-Origin': '*',
  }
}
相关推荐
爱编程的小新☆几秒前
LangGraph4j工作流框架
前端·数据库·ai·langchain·langgraph4j
@PHARAOH16 分钟前
HOW - 构建一个轻量前后端一体服务
前端·微服务·服务端
无限进步_27 分钟前
【C++】C++11的类功能增强与STL变化
java·前端·数据结构·c++·后端·算法
一只小小Java29 分钟前
Echarts单表多图实现
前端·javascript·echarts
dunky38 分钟前
Spring AI 深度解析:把 LLM 抽象成 Spring Bean 的底层逻辑
前端
星栈39 分钟前
Rust WASM 文件上传全链路:从浏览器到 S3,一个字节都不能少
前端·前端框架·开源
濮水大叔39 分钟前
告别 Django Admin!这个 NodeJS 全栈框架让你在 DTO 中直接配置 Table/Form 渲染
前端·typescript·node.js
JarvanMo40 分钟前
Flutter 3.44 & Dart 3.12重磅发布!这些新特性太香了
前端
竹林81840 分钟前
用Viem替换ethers.js:一次合约交互的"减负"实战,我总算把TypeScript类型搞明白了
前端·javascript
To_OC41 分钟前
一个让我懵了半小时的时钟 Bug,注重前端三权分立落地
前端·代码规范