qiankun微前端使用指南-从开发到部署
qiankun 使用指南(基座 Vue2 + 子应用 Vue2 / Vue3 / React / jQuery)
本文为通用实践文档,不依赖任何现有项目代码,可作为你的微前端接入手册与实施清单。
阅读指南与结构
- 顺序建议:
- 快速上手(基座注册与启动)
- 子应用通用改造(publicPath 与生命周期)
- 本地开发跨域(CORS / 代理)
- 跨应用通信(props / 全局状态 / 动态 update)
- 路由与激活规则(Hash/History)
- 部署与 Nginx 配置(同域/子域)
- 进阶能力(loadMicroApp 等)
- 常见问题排查
- 实施 Checklist(自检)
目录
- 适用场景与核心概念
- 快速上手
- 子应用通用改造
- 子应用示例(Vue2 / Vue3 / React / jQuery)
- 跨应用通信(含基座向子应用传递数据)
- 路由与激活规则
- 本地开发跨域(Webpack DevServer)
- 部署与 Nginx 配置
- 构建与部署要点清单
- 进阶能力
- 常见问题排查
- 实施 Checklist
最佳实践总览
- 使用同域子路径部署,entry 指向同源
/app-*,省去跨域复杂度 - 子应用入口首行引入
public-path.js,打包为 UMD,根节点统一#app - 路由优先 Hash;History 必配
try_files回退 - 通信优先全局状态(
initGlobalState),props 承载初始化与函数引用,频繁更新用loadMicroApp().update - 本地联调优先“基座代理同源”,次选子应用 CORS;携带凭证需精确 Origin+Credentials
- 缓存策略:HTML no-cache,静态资源长缓存(带 hash)
适用场景与核心概念
- 适用场景:多团队/多技术栈共存、垂直拆分大型前端、独立部署与灰度、渐进式改造老系统。
- 核心概念:
- 基座(主应用):承载导航、布局、权限与微应用加载调度。
- 子应用(微应用):独立构建与部署,通过 UMD 生命周期接入基座。
- 激活规则 activeRule:根据 URL(建议 Hash 或 History 前缀)决定子应用何时装载/卸载。
- 运行时 publicPath 注入:解决生产静态资源路径问题。
快速上手
1) 安装
npm i qiankun --save
2) 基座(Vue2)最小可用集成
- 在你的基座页面中预留容器:
<!-- App.vue 或基座布局中 -->
<div id="micro-app-container">
<div id="subapp-root"></div>
</div>
- 基座注册与启动:
// main.js(或专门的 micro-frontend.ts)
import { registerMicroApps, start, initGlobalState } from 'qiankun';
const getActiveRule = (hashOrList) => (location) => {
const list = Array.isArray(hashOrList) ? hashOrList : [hashOrList];
return list.some((prefix) => new RegExp(`^${prefix}($|[/?#].*)`).test(location.hash || location.pathname));
};
registerMicroApps([
{
name: 'app-vue2',
entry: process.env.NODE_ENV === 'production' ? '/app-vue2/' : '//localhost:8081',
container: '#subapp-root',
activeRule: getActiveRule('#/app-vue2'),
props: { fromBase: 'hello' },
},
{
name: 'app-vue3',
entry: process.env.NODE_ENV === 'production' ? '/app-vue3/' : '//localhost:8082',
container: '#subapp-root',
activeRule: getActiveRule('#/app-vue3'),
},
{
name: 'app-react',
entry: process.env.NODE_ENV === 'production' ? '/app-react/' : '//localhost:8083',
container: '#subapp-root',
activeRule: getActiveRule('#/app-react'),
},
{
name: 'app-jquery',
entry: process.env.NODE_ENV === 'production' ? '/app-jquery/' : '//localhost:8084',
container: '#subapp-root',
activeRule: getActiveRule('#/app-jquery'),
},
], {
beforeLoad: [() => {/* 显示加载中 */}],
beforeMount: [() => {/* 切换布局/隐藏基座区域 */}],
afterUnmount: [() => {/* 恢复布局 */}],
});
// 全局状态(可选)
const actions = initGlobalState({ user: null, token: null });
actions.onGlobalStateChange((state, prev) => {
console.log('global state change:', state, prev);
});
start({
prefetch: 'all', // 预加载策略:'all' | true | false | [appName]
sandbox: { strictStyleIsolation: false },
singular: false, // 是否同一时刻只渲染一个微应用
});
3) 子应用通用改造
- 运行时 publicPath 注入:
// src/public-path.js
if (window.__POWERED_BY_QIANKUN__) {
/* eslint-disable */
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
- 入口生命周期(通用约定):
bootstrap(props):初始化仅需执行一次的逻辑。mount(props):挂载渲染,读取props.container与自定义props。unmount(props):解绑事件、卸载实例、清理 DOM。
- 独立/qiankun 双态运行:在入口末尾检测
window.__POWERED_BY_QIANKUN__,不在 qiankun 环境时直接render()。
子应用示例
A. Vue2 子应用(Webpack)
// src/public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
// src/main.js
import './public-path';
import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
let instance = null;
let router = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({ mode: 'hash', routes: [] });
instance = new Vue({ router, render: (h) => h(App) })
.$mount(container ? container.querySelector('#app') : '#app');
}
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {}
export async function mount(props) { render(props); }
export async function unmount() {
instance && instance.$destroy();
instance && (instance.$el.innerHTML = '');
instance = null;
router = null;
}
// webpack.config.js 关键配置
module.exports = {
output: {
library: 'app-vue2-[name]',
libraryTarget: 'umd',
publicPath: 'auto',
},
devServer: {
port: 8081,
headers: { 'Access-Control-Allow-Origin': '*' },
},
};
B. Vue3 子应用(Vite)
// src/public-path.js(仍可沿用同样写法)
if ((window as any).__POWERED_BY_QIANKUN__) {
// @ts-ignore
__webpack_public_path__ = (window as any).__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
// src/main.ts
import './public-path';
import { createApp } from 'vue';
import App from './App.vue';
import { createRouter, createWebHashHistory } from 'vue-router';
let app: any = null;
let router: any = null;
function render(props: any = {}) {
const { container } = props;
router = createRouter({ history: createWebHashHistory(), routes: [] });
app = createApp(App);
app.use(router);
app.mount(container ? container.querySelector('#app')! : '#app');
}
if (!(window as any).__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {}
export async function mount(props: any) { render(props); }
export async function unmount() {
app?.unmount();
app = null;
router = null;
}
// vite.config.ts(推荐 vite-plugin-qiankun)
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import qiankun from 'vite-plugin-qiankun';
export default defineConfig({
plugins: [vue(), qiankun('app-vue3', { useDevMode: true })],
server: { port: 8082, cors: true },
base: '/',
});
C. React 18 子应用(Webpack 或 Vite)
// src/public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
// src/main.jsx
import './public-path';
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
let root = null;
function render(props = {}) {
const { container } = props;
const dom = container ? container.querySelector('#app') : document.getElementById('app');
if (!dom) return;
root = createRoot(dom);
root.render(<App />);
}
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {}
export async function mount(props) { render(props); }
export async function unmount() { root?.unmount(); root = null; }
// webpack.config.js 关键配置
module.exports = {
output: {
library: 'app-react-[name]',
libraryTarget: 'umd',
publicPath: 'auto',
},
devServer: { port: 8083, headers: { 'Access-Control-Allow-Origin': '*' } },
};
// vite.config.ts(可选)
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import qiankun from 'vite-plugin-qiankun';
export default defineConfig({
plugins: [react(), qiankun('app-react', { useDevMode: true })],
server: { port: 8083, cors: true },
base: '/',
});
D. jQuery / 原生 子应用(UMD)
// src/public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
// src/main.js
import './public-path';
import $ from 'jquery';
let containerEl = null;
function render(props = {}) {
const { container } = props;
containerEl = container ? container.querySelector('#app') : document.getElementById('app');
if (!containerEl) return;
$(containerEl).html(
'<div class="jq-app">\n' +
' <h3>jQuery Micro App</h3>\n' +
' <button id="jq-btn">Click</button>\n' +
'</div>'
);
$(containerEl).on('click', '#jq-btn', () => alert('Hello from jQuery app'));
}
if (!window.__POWERED_BY_QIANKUN__) { render(); }
export async function bootstrap() {}
export async function mount(props) { render(props); }
export async function unmount() {
if (containerEl) {
$(containerEl).off('click', '#jq-btn');
$(containerEl).empty();
containerEl = null;
}
}
// webpack.config.js 关键配置
module.exports = {
output: {
library: 'app-jquery-[name]',
libraryTarget: 'umd',
publicPath: 'auto',
},
devServer: { port: 8084, headers: { 'Access-Control-Allow-Origin': '*' } },
};
路由与激活规则
- 推荐 Hash 前缀:简单可靠,基座
activeRule('#/app-react')与子应用内部使用 Hash 路由一致。 - History 模式:需要服务端 rewrite,否则刷新 404。
location /app-react/ {
root /your/dist/root;
try_files $uri $uri/ /app-react/index.html;
}
- activeRule 编写:支持字符串或数组;可根据
location.pathname与location.hash组合匹配。
跨应用通信
- props 传参(简单直观):基座在
registerMicroApps的props字段传入;子应用在bootstrap/mount中读取。 - 全局状态(推荐):
initGlobalState返回的actions可在基座与所有子应用间同步状态。
// 基座
const actions = initGlobalState({ user: null });
actions.setGlobalState({ user: { id: 1 } });
// 子应用
export async function mount(props) {
props.onGlobalStateChange((state) => console.log(state), true);
props.setGlobalState && props.setGlobalState({ user: { id: 2 } });
}
- 其他:事件总线、URL 查询参数、LocalStorage(需注意隔离与一致性)。
构建与部署要点清单
- 子应用打包必须为 UMD,且入口导出生命周期。
- 生产环境必须启用 运行时 publicPath 注入,避免静态资源 404。
- 开发环境建议为每个子应用配置 独立端口 且允许 CORS。
- 基座
container与子应用根节点选择器(如#app)需一致。 - 多子应用并行时,合理设置
singular与prefetch,避免性能瓶颈。
常见问题排查
- 刷新 404(History 模式):服务端缺少 rewrite;改用 Hash 或配置 Nginx
try_files。 - 样式污染/丢失:开启
sandbox.strictStyleIsolation或使用 CSS Modules/BEM;确保子应用unmount清理干净。 - 静态资源路径错误:缺少
public-path.js注入或构建publicPath写死。 - 白屏:容器选择器不匹配;入口未导出生命周期;网络错误导致 entry 加载失败。
- 内存泄漏:
unmount未解绑事件/未销毁实例。
进阶能力
- 手动加载微应用:
import { loadMicroApp } from 'qiankun';
const app = loadMicroApp({ name: 'x', entry: '//localhost:9000', container: '#subapp-root' });
// app.unmount() 可在任意时机卸载
- 保活与 KeepAlive:自行在基座维护缓存容器(注意与 qiankun 沙箱冲突)。
- HTML Entry 子应用:直接使用完整 HTML 作为 entry(默认行为),无需额外配置。
实施 Checklist(落地自检)
基座向子应用传递数据(详解)
方案一:通过 props 直传(简单直观)
- 基座在注册时通过
props字段传入任意可序列化对象或函数引用(同上下文,非跨进程,函数可直接传递)。
// 基座
import { registerMicroApps } from 'qiankun';
const api = {
fetchUser: async (id) => ({ id, name: 'Alice' }),
openModal: (payload) => console.log('open modal', payload),
};
registerMicroApps([
{
name: 'app-react',
entry: '//localhost:8083',
container: '#subapp-root',
activeRule: '#/app-react',
props: {
user: { id: 1, name: 'admin' },
permissions: ['read', 'write'],
api,
featureFlags: { newUI: true },
},
},
]);
// 子应用(以 React 为例)
export async function mount(props) {
const { user, permissions, api, featureFlags } = props;
console.log('from base:', user, permissions, featureFlags);
api.openModal({ title: 'Hello' });
}
- 要点:
- props 仅在
mount初次传入,之后若需“实时更新”,更推荐使用全局状态;或使用loadMicroApp + update机制(见方案三)。 - 大对象请仅传递标识(如 id),数据在子应用自行拉取,以降低耦合与传输体积。
- props 仅在
方案二:全局状态(推荐,支持订阅与推送)
- 基座初始化全局状态后,子应用可通过
props.onGlobalStateChange订阅、props.setGlobalState推送。
// 基座
import { initGlobalState, registerMicroApps, start } from 'qiankun';
const actions = initGlobalState({ user: { id: 1, name: 'admin' }, theme: 'light' });
actions.onGlobalStateChange((state, prev) => {
console.log('base observe:', state, prev);
});
registerMicroApps([
{ name: 'app-vue2', entry: '//localhost:8081', container: '#subapp-root', activeRule: '#/app-vue2' },
]);
start();
// 在任意时机更新:
actions.setGlobalState({ theme: 'dark' });
// 子应用(任意技术栈通用)
export async function mount(props) {
// 订阅(fireImmediately=true 首次立即触发一次)
props.onGlobalStateChange && props.onGlobalStateChange((state, prev) => {
console.log('sub observe:', state, prev);
// TODO: 根据 state 更新自身 UI/状态
}, true);
// 推送
props.setGlobalState && props.setGlobalState({ theme: 'dark' });
}
- 要点:
- 不需要手动在
props中传入 actions,初始化后 qiankun 会把onGlobalStateChange、setGlobalState、offGlobalStateChange注入到每个子应用的props。 - 状态必须为可序列化对象;更新是浅合并(保留未覆盖的字段)。
- 不需要手动在
方案三:动态更新 props(loadMicroApp + update)
- 如需在运行中多次下发不同 props,可使用手动加载 API 并在子应用导出
update生命周期。
// 基座(手动加载)
import { loadMicroApp } from 'qiankun';
const app = loadMicroApp({
name: 'app-react',
entry: '//localhost:8083',
container: '#subapp-root',
props: { filters: { keyword: '' } },
});
// 运行时更新 props
app.update({ filters: { keyword: 'hello' } });
// 子应用(增加 update 生命周期)
export async function update(props) {
// 从 props 中读取最新数据并应用到 UI
console.log('updated props', props);
}
- 要点:
registerMicroApps场景下没有直接的 props 更新 API;若需要频繁更新,请优先用“全局状态”,或切换到loadMicroApp。
类型定义(可选,TS)
// 子应用可约束接收的 props 类型
export interface MicroAppProps {
container?: HTMLElement;
name?: string;
onGlobalStateChange?: (cb: (state: any, prev: any) => void, fireImmediately?: boolean) => void;
setGlobalState?: (state: Record<string, any>) => void;
offGlobalStateChange?: () => void;
// 自定义字段
user?: { id: number; name: string } | null;
permissions?: string[];
featureFlags?: Record<string, boolean>;
api?: { fetchUser?: (id: number) => Promise<any>; openModal?: (payload: any) => void };
}
最佳实践
- 使用全局状态广播通用上下文(如
user、theme、语言等),props 仅承载初始化必要参数和函数引用。 - 避免下发大型对象;以 ID + 子应用内聚的数据获取为主。
- 明确卸载时机:在
unmount内清理订阅(offGlobalStateChange)、事件监听与定时器,避免内存泄漏。 - 如需强约束,使用 TypeScript 定义
MicroAppProps并在各子应用落地校验。
本地开发跨域(Webpack DevServer)
qiankun 在开发环境通常通过不同端口加载子应用 HTML Entry(跨源)。需为每个子应用的 Webpack DevServer 开启 CORS,或者通过“基座代理”将子应用映射到同源路径以规避 CORS。
子应用开启 CORS(最简单)
// 子应用 webpack.config.js(或 vue-cli 的 vue.config.js -> devServer)
module.exports = {
// ...
devServer: {
port: 8083, // 每个子应用使用独立端口
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
},
allowedHosts: 'all', // webpack-dev-server v4
hot: true,
},
output: {
publicPath: 'auto', // 搭配运行时 publicPath 注入
library: 'app-react-[name]',
libraryTarget: 'umd',
},
};
- 适用于不携带 Cookie/凭证的加载场景(纯资源加载)。
- 基座的
entry可直接指向//localhost:8083。
携带凭证(Cookie/Authorization)场景
若子应用资源或接口需要 Cookie,会触发“凭证跨域”规则:
- 响应头必须为精确的
Access-Control-Allow-Origin: http://localhost:8080(不能使用*)。 - 且需包含
Access-Control-Allow-Credentials: true。 - 前端请求需开启凭证(如 axios
withCredentials: true)。
// 子应用 webpack.config.js
const BASE_ORIGIN = 'http://localhost:8080'; // 基座地址
module.exports = {
devServer: {
port: 8083,
headers: {
'Access-Control-Allow-Origin': BASE_ORIGIN,
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
},
},
};
// axios 示例(基座或子应用内都需与后端约定好)
import axios from 'axios';
axios.defaults.withCredentials = true;
注意:若仅是“加载子应用入口 HTML 与脚本”,大多数场景无需凭证;仅当你的静态资源服务依赖 Cookie 鉴权时才需此配置。
通过基座代理规避跨域(同源映射,推荐)
将子应用开发服务代理到基座同源路径(如 http://localhost:8080/app-react/),此时无需子应用开放 CORS:
// 基座(Vue CLI)vue.config.js -> devServer.proxy
module.exports = {
devServer: {
port: 8080,
proxy: {
'/app-react': {
target: 'http://localhost:8083',
changeOrigin: true,
pathRewrite: { '^/app-react': '/' },
// ws: false // 如需
},
'/app-vue2': {
target: 'http://localhost:8081',
changeOrigin: true,
pathRewrite: { '^/app-vue2': '/' },
},
},
},
};
// 基座注册时将 entry 改为同源路径
registerMicroApps([
{
name: 'app-react',
entry: '/app-react/', // 由代理转发到 8083
container: '#subapp-root',
activeRule: '#/app-react',
},
]);
- 优点:彻底避免跨域与 CORS 复杂度;模拟生产同路径部署结构。
- 缺点:需要配置多个代理规则;若子应用也访问其后端接口,可能还需额外代理。
其他注意点
- 协议一致:基座与子应用尽量同为
http或同为https,避免混合内容被浏览器拦截。 - Host 校验:webpack-dev-server v4 默认限制外部访问,开发时可设置
allowedHosts: 'all'。 - CSP 与跨源脚本:如启用严格 CSP,请确保允许加载相应源的脚本与样式。
- Script crossorigin:通常不需要手动设置;若有 SourceMap 收集等需求,可设置
output.crossOriginLoading = 'anonymous'。
常见错误与排查
- 报错 “No 'Access-Control-Allow-Origin' header is present”:
- 子应用未设置
devServer.headers;或使用了凭证但仍设置了*。
- 子应用未设置
- 报错 “The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'”:
- 开启了 Cookie/凭证但响应头仍为
*;改为精确 Origin 并添加Access-Control-Allow-Credentials: true。
- 开启了 Cookie/凭证但响应头仍为
net::ERR_FAILED/加载入口 HTML 失败:- 端口未启动、端口冲突、被系统代理/防火墙拦截;或
entry地址错误。
- 端口未启动、端口冲突、被系统代理/防火墙拦截;或
部署与 Nginx 配置
微前端生产部署的关键点:
- 子应用必须以 UMD 产物对外提供入口(HTML Entry 方式加载),并保证运行时 publicPath 正确;
- 根据路由模式配置回退(Hash 模式无需回退,History 模式需 try_files 到 index.html);
- 统一同源(同域 + 子路径)最省心,也可采用子域名跨域 + CORS;
- 区分 HTML 与静态资源的缓存策略,避免发布后页面不更新。
方案一:同域 + 子路径(推荐)
- 目录结构(示例):
- 基座:
/var/www/base/(包含index.html与静态资源) - Vue2 子应用:
/var/www/app-vue2/ - Vue3 子应用:
/var/www/app-vue3/ - React 子应用:
/var/www/app-react/ - jQuery 子应用:
/var/www/app-jquery/
- 基座:
- 基座在
registerMicroApps中的 entry 指向同域路径:/app-vue2/、/app-react/等。
server {
listen 80;
server_name example.com;
# 基座(History 模式)
root /var/www/base;
index index.html;
# 静态资源强缓存
location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800, immutable";
}
# HTML 不缓存(便于发布后立即生效)
location = /index.html {
add_header Cache-Control "no-cache";
}
# 基座 History 路由回退
location / {
try_files $uri $uri/ /index.html;
}
# 子应用:Vue2(Hash 或 History 均可,History 需要回退)
location /app-vue2/ {
alias /var/www/app-vue2/;
index index.html;
try_files $uri $uri/ /app-vue2/index.html;
}
# 子应用:Vue3
location /app-vue3/ {
alias /var/www/app-vue3/;
index index.html;
try_files $uri $uri/ /app-vue3/index.html;
}
# 子应用:React
location /app-react/ {
alias /var/www/app-react/;
index index.html;
try_files $uri $uri/ /app-react/index.html;
}
# 子应用:jQuery / 原生
location /app-jquery/ {
alias /var/www/app-jquery/;
index index.html;
try_files $uri $uri/ /app-jquery/index.html;
}
# 可选:开启 gzip 压缩
gzip on;
gzip_comp_level 5;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/json image/svg+xml;
# 可选:基础安全头
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
}
注意:使用 alias 映射子路径到对应目录;若使用 root,需确保路径拼接正确。
方案二:子域名(跨域加载)
- 基座:
base.example.com,子应用:vue2.example.com、react.example.com等; - 基座的 entry 使用完整 URL:
https://vue2.example.com/; - 如需跨域携带 Cookie(含鉴权资源),需在子应用服务器添加 CORS 头:
# 子应用服务器(仅当需要跨域凭证时)
server {
listen 443 ssl;
server_name vue2.example.com;
root /var/www/app-vue2;
index index.html;
# 允许基座域名跨域访问(凭证场景不要使用 *)
add_header Access-Control-Allow-Origin https://base.example.com always;
add_header Access-Control-Allow-Credentials true always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
if ($request_method = OPTIONS) {
return 204;
}
location / {
try_files $uri $uri/ /index.html;
}
}
一般只需开放静态资源跨域;接口跨域由后端网关统一处理更稳妥。
Hash vs History 模式部署要点
- Hash 模式:静态托管即可,不需要
try_files回退; - History 模式:所有非文件请求回退到各自
index.html,否则刷新会 404; - 基座与子应用可以混用不同模式,但建议统一以减少心智负担。
资源路径与 publicPath
- 子应用务必使用“运行时 publicPath 注入”(
window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__),避免构建时写死路径; - 若部署到子路径(如
/app-react/),构建工具(Vite 的base或 Webpack 的publicPath)需与运行时注入协同(建议保持auto+ 运行时注入)。
缓存与版本
- 对
*.js/*.css等静态资源开启长期缓存(带 hash 文件名),对 HTML 禁用缓存; - 发布策略:先上传静态资源,再替换
index.html,避免短时间 404; - 可结合
Cache-Control: immutable与版本号管理,确保灰度与回滚安全。
HTTPS 与 HTTP/2
- 建议启用 HTTPS 与 HTTP/2,提升首屏与并发加载性能:
server {
listen 443 ssl http2;
server_name example.com;
# ssl_certificate /path/fullchain.pem;
# ssl_certificate_key /path/privkey.pem;
# 其余与 80 端口配置一致
}
反向代理到应用服务器(可选)
- 若基座/子应用由 Node/Nest/Express 提供静态与 SSR,可用反向代理:
location /app-react/ {
proxy_pass http://127.0.0.1:7003/; # 由后端应用处理 SPA 回退
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
部署检查清单
本文来自博客园,作者:Math点PI,个性签名:“不写bug怎么进步?”,转载请注明原文链接:https://www.cnblogs.com/MrZhous/p/19040000

浙公网安备 33010602011771号