Skip to content

Commit

Permalink
feat(1.0.0-rc.6): Improve router system of naitve mode
Browse files Browse the repository at this point in the history
  • Loading branch information
bailicangdu committed Jun 28, 2024
1 parent 5b7ed5f commit 4814b30
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 24 deletions.
1 change: 1 addition & 0 deletions docs/zh-cn/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- 🐞 修复 当官网文档页面内容含有tab时,跳转或刷新后标题锚点定为不准确的问题。
- 🐞 修复 火狐浏览器下子应用`favicon.ico`将主应用图标替换的问题。
- 🐞 修复 循环嵌套时,中间层子应用为iframe沙箱时通过data属性传递初始化数据失败的问题。
- 🐞 修复 native路由模式下vue3按需加载页面在部分场景下点击浏览器前进后退按钮时浏览器地址错误。

- **Update**
- 🚀 优化 沙箱架构设计。
Expand Down
20 changes: 11 additions & 9 deletions docs/zh-cn/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。
开启inline模式后,script元素会被保留,方便查看和调试代码,但会稍微损耗性能,建议只在开发环境中使用。


## destroy
- Desc: `卸载时强制删除缓存资源`
- Default: `false`
- 使用方式: `<micro-app name='xx' url='xx' destroy></micro-app>`

默认情况下,子应用被卸载后不会删除缓存的静态资源和数据,以便在重新渲染时获得更好的性能。

开启destroy,子应用在卸载后会清空缓存资源和数据,当重新渲染时将和初次渲染的行为保持一致。

## clear-data
- Desc: `卸载时清空数据通讯中的缓存数据`
- Default: `false`
Expand All @@ -63,6 +54,17 @@ MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。

[destroy](/zh-cn/configure?id=destroy)也有同样的效果。

## destroy
- Desc: `卸载时删除缓存资源`
- Default: `false`
- 使用方式: `<micro-app name='xx' url='xx' destroy></micro-app>`

默认情况下,子应用被卸载后不会删除缓存的静态资源和沙箱数据,以便在重新渲染时获得更好的性能。

开启destroy,子应用在卸载后会清空缓存的静态资源和沙箱数据。

但destroy只适合一次性渲染的子应用,由于子应用每次初始化都可能会增加一些无法释放的内存,如果频繁渲染和卸载,设置destroy反而会增加内存消耗,请谨慎使用。


## disable-scopecss
- Desc: `关闭样式隔离`
Expand Down
11 changes: 9 additions & 2 deletions src/sandbox/router/core.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
MicroLocation,
MicroState,
MicroRouterInfoState,
LocationQuery,
HandleMicroPathResult,
} from '@micro-app/types'
Expand Down Expand Up @@ -35,14 +36,14 @@ export function setMicroState (
): MicroState {
// TODO: 验证native模式下修改state nextjs路由是否正常
const rawState = globalEnv.rawWindow.history.state
const additionalState: Record<string, any> = {
const additionalState: Record<'__MICRO_APP_STATE__', Record<string, MicroRouterInfoState>> = {
__MICRO_APP_STATE__: assign({}, rawState?.__MICRO_APP_STATE__, {
[appName]: {
fullPath: targetLocation ? targetLocation.pathname + targetLocation.search + targetLocation.hash : null,
state: microState ?? null,
mode: getRouterMode(appName),
}
})
}),
}

// create new state object
Expand All @@ -69,6 +70,12 @@ export function getMicroState (appName: string): MicroState {
return rawState?.__MICRO_APP_STATE__?.[appName]?.state || null
}

// get micro app router info state form origin state
export function getMicroRouterInfoState (appName: string): MicroRouterInfoState | null {
const rawState = globalEnv.rawWindow.history.state
return rawState?.__MICRO_APP_STATE__?.[appName] || null
}

const ENC_AD_RE = /&/g // %M1
const ENC_EQ_RE = /=/g // %M2
const DEC_AD_RE = /%M1/g // &
Expand Down
20 changes: 10 additions & 10 deletions src/sandbox/router/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import {
getMicroPathFromURL,
getMicroState,
getMicroRouterInfoState,
isEffectiveApp,
isRouterModeCustom,
} from './core'
Expand Down Expand Up @@ -51,22 +52,21 @@ export function addHistoryListener (appName: string): CallableFunction {
!e.onlyForBrowser
) {
/**
* main app maybe navigate async when receive popstateEvent, but child may respond to popstateEvent immediately(vue2, react), so when go back throw browser child will not unmount sync, and will respond to popstateEvent before base app, this will cause some problems
*/
/**
* NOTE:
* base app may respond to popstateEvent async(lazy load page & browser back/forward), but child app will respond to popstateEvent immediately(vue2, react), this will cause some problems
* 2 solutions:
* 1. child app respond to popstateEvent async -- router-event-delay
* 2. child app will not respond to popstateEvent in some scenarios (history.state===null || history.state?__MICRO_APP_STATE__[appName])
* NOTE 1:
* 1. browser back/forward
* 2. location.hash/search/pathname = xxx
* 3. <a href="/#/xxx">, <a href="/xxx">
* 4. history.back/go/forward
* 5. history.pushState/replaceState
*
* NOTE2:
* react16 hash mode navigate by location.hash = xxx, history.state is always null, but react16 respond to popstateEvent sync
*/
// 1、其它模式要不要也过滤关键在于history.state存在时__MICRO_APP_STATE__有没有可能不存在
// 如果history.state存在而__MICRO_APP_STATE__不存在在非native模式下存在,那就不能过滤,比如pure模式?
// 不对啊,location.hash=xxx,确实会导致state为null,可以框架接受到popstate事件后就重新写入state了,所以这种方式不准确 -- 误会,框架重写写入state也是靠history.replaceState,所以没事
if (!isRouterModeCustom(appName) || !history.state || getMicroState(appName)) {
// updateMicroLocationWithEvent(appName, getMicroPathFromURL(appName))
// 这里加一个判断,如果是native或者search模式才启用延迟,state、pure不需要这样做
if (!isRouterModeCustom(appName) || !history.state || getMicroRouterInfoState(appName)) {
const container = appInstanceMap.get(appName)?.container
macro(
() => updateMicroLocationWithEvent(appName, getMicroPathFromURL(appName)),
Expand Down
7 changes: 4 additions & 3 deletions src/sandbox/router/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
setMicroPathToURL,
setMicroState,
getMicroState,
getMicroRouterInfoState,
getMicroPathFromURL,
isEffectiveApp,
isRouterModePure,
Expand Down Expand Up @@ -223,12 +224,12 @@ function reWriteHistoryMethod (method: History['pushState' | 'replaceState']): C
const app = appInstanceMap.get(appName)!
attachRouteToBrowserURL(
appName,
setMicroPathToURL(appName, app.sandBox.proxyWindow.location as MicroLocation),
setMicroState(appName, getMicroState(appName), app.sandBox.proxyWindow.location as MicroLocation),
setMicroPathToURL(appName, app.sandBox.proxyWindow.location),
setMicroState(appName, getMicroState(appName), app.sandBox.proxyWindow.location),
)
}

if (isRouterModeCustom(appName) && !rawWindow.history.state?.__MICRO_APP_STATE__?.[appName]) {
if (isRouterModeCustom(appName) && !getMicroRouterInfoState(appName)) {
nativeHistoryNavigate(
appName,
'replaceState',
Expand Down
5 changes: 5 additions & 0 deletions typings/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,11 @@ declare module '@micro-app/types' {

type MicroHistory = ProxyHandler<History>
type MicroState = any
interface MicroRouterInfoState {
fullPath: string | null,
state: MicroState,
mode: string,
}
type HistoryProxyValue =
Pick<
History,
Expand Down

0 comments on commit 4814b30

Please sign in to comment.