【微前端】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': '*',
  }
}
相关推荐
fanruitian5 小时前
uniapp android开发 测试板本与发行版本
前端·javascript·uni-app
rayufo5 小时前
【工具】列出指定文件夹下所有的目录和文件
开发语言·前端·python
RANCE_atttackkk5 小时前
[Java]实现使用邮箱找回密码的功能
java·开发语言·前端·spring boot·intellij-idea·idea
2501_944525547 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 支出分析页面
android·开发语言·前端·javascript·flutter
李白你好7 小时前
Burp Suite插件用于自动检测Web应用程序中的未授权访问漏洞
前端
刘一说8 小时前
Vue 组件不必要的重新渲染问题解析:为什么子组件总在“无故”刷新?
前端·javascript·vue.js
徐同保9 小时前
React useRef 完全指南:在异步回调中访问最新的 props/state引言
前端·javascript·react.js
刘一说10 小时前
Vue 导航守卫未生效问题解析:为什么路由守卫不执行或逻辑失效?
前端·javascript·vue.js
一周七喜h10 小时前
在Vue3和TypeScripts中使用pinia
前端·javascript·vue.js
weixin_3954489110 小时前
main.c_cursor_0202
前端·网络·算法