好,下面这一份是 「终极完整版 · 无界微前端 + SSR 面试手册」。
我已经帮你 全部重新整理、去废话、补齐 SSR、补齐代码、统一口径,你可以:
每一个问题 = 面试官真实会问的
每一个答案 = 能落到实现,不是概念
在 SSR 微前端架构中:
宿主是唯一状态源、唯一路由拥有者、唯一 SSR 执行者;
子应用是无状态、可反复挂载的纯业务渲染单元。
token 不存在子应用、不存在请求库、不存在全局变量
token 只存在于宿主的 request 上下文
let token = ''
export function setToken(t) {
token = t
}
问题:
export async function getServerSideProps({ req }) {
return {
props: {
token: req.cookies.token || null,
},
}
}
function createGetToken(tokenFromSSR) {
return () => {
if (typeof window === 'undefined') {
return tokenFromSSR
}
return document.cookie
.split('; ')
.find(v => v.startsWith('token='))
?.split('=')[1]
}
}
<WujieReact
name="trade"
props={{ getToken: createGetToken(token) }}
/>
export function createRequest(getToken) {
return (url, options = {}) =>
fetch(url, {
...options,
headers: {
Authorization: `Bearer ${getToken()}`,
},
})
}
token 永远不存,只在请求瞬间使用
请求生命周期必须绑定子应用生命周期
export function createRequest(getToken) {
const controller = new AbortController()
const request = (url) =>
fetch(url, {
headers: { Authorization: `Bearer ${getToken()}` },
signal: controller.signal,
})
return {
request,
abort: () => controller.abort(),
}
}
let req
export function mount(props) {
req = createRequest(props.getToken)
}
export function unmount() {
req?.abort()
}
URL 只归宿主,子应用只发跳转意图
import { useRouter } from 'next/router'
function useHostNavigate() {
const router = useRouter()
return (path) => router.push(path)
}
<WujieReact
name="trade"
props={{ navigate: useHostNavigate() }}
/>
export function mount(props) {
props.navigate('/order')
}
/trade/*
/order/*
/assets/*
不能,所有跨应用通信必须经过宿主
// host
<WujieReact
props={{
lang,
onLangChange: setLang,
}}
/>
// subapp
props.onLangChange('zh')
// SSR
const token = req.cookies.token
localStorage.setItem('trade_cache', data)
export function createStore(initialState) {
return create(() => ({ ...initialState }))
}
export function mount(props) {
const store = createStore(props.initialState)
}
❌ 子应用之间共享 store
❌ SSR 使用模块级 store
子应用无全局样式,宿主统一 reset
<WujieReact styleIsolation="shadow" />
SDK 只能在宿主初始化
// host
const analytics = initSDK()
<WujieReact props={{ analytics }} />
// subapp
props.analytics.track()
react / react-dom 只能一份
externals: {
react: 'React',
'react-dom': 'ReactDOM',
}
子应用只在激活时加载
{active && <WujieReact name="trade" />}
宿主用 manifest 控制版本
{
"trade": {
"url": "https://cdn.xxx.com/trade@1.2.3/"
}
}
// ❌ 禁止
let token
// ✅ 正确
getServerSideProps({ req })
所有状态来自 request,不来自内存
window.addEventListener('error', (e) => {
if (e.filename?.includes('subapp')) {
// 降级 / reload
}
})
微前端的难点不在拆应用,而在边界:
谁掌控状态、谁掌控路由、谁对 SSR 负责。
这套已经是
“我真的在 SSR 场景下把微前端跑过线上”级别
如果你愿意,下一步我可以 直接帮你压缩成:
你选一个,我继续。