diff --git a/dev/children/vite4/src/main.js b/dev/children/vite4/src/main.js index beef4fae0..56386d99e 100644 --- a/dev/children/vite4/src/main.js +++ b/dev/children/vite4/src/main.js @@ -47,7 +47,6 @@ let router = null let history = null // 将渲染操作放入 mount 函数 window.mount = (data) => { - // console.log(1212121212121212, location.href) history = createWebHistory(window.__MICRO_APP_BASE_ROUTE__ || import.meta.env.BASE_URL) router = createRouter({ history, @@ -283,7 +282,7 @@ setTimeout(() => { /* ---------------------- Image --------------------- */ // const newImg = new Image() -// newImg.src = '/micro-app/vite2/src/assets/logo.png' +// newImg.src = '/micro-app/vite4/src/assets/logo.png' // document.body.appendChild(newImg) // newImg.setAttribute('width', '50px') @@ -296,19 +295,20 @@ setTimeout(() => { /* ---------------------- location 跳转 --------------------- */ // 依次放开每个注释来,尽可能覆盖所有场景 setTimeout(() => { + const baseRoute = (window.__MICRO_APP_BASE_ROUTE__ || import.meta.env.BASE_URL).replace(/\/$/, '') // window.microApp.location.href = 'https://www.baidu.com/' // origin不同,直接跳转页面 - // window.microApp.location.href = '/micro-app/vite2/page2' - // window.microApp.location.href = 'http://localhost:7001/micro-app/vite2/page2' // path改变,刷新浏览器 - // window.microApp.location.href = 'http://localhost:7001/micro-app/vite2/page2#abc' // path不变,hash改变,不刷新浏览器,发送popstate、hashchange事件 - // window.microApp.location.href = 'http://localhost:7001/micro-app/vite2/page2/' // hash从有到无,刷新浏览器 - // window.microApp.location.href = 'http://localhost:7001/micro-app/vite2' - // window.microApp.location.href = 'http://localhost:7001/micro-app/vite2/' // path相同,刷新浏览器 - // window.microApp.location.href = 'http://localhost:7001/micro-app/vite2/?a=1' // search变化,刷新浏览器 + // window.microApp.location.href = `${baseRoute}/element-plus` + // window.microApp.location.href = `http://localhost:7002${baseRoute}/element-plus` // path改变,刷新浏览器 + // window.microApp.location.href = `http://localhost:7002${baseRoute}/element-plus#abc` // path不变,hash改变,不刷新浏览器,发送popstate、hashchange事件 + // window.microApp.location.href = `http://localhost:7002${baseRoute}/element-plus/` // hash从有到无,刷新浏览器 + // window.microApp.location.href = `http://localhost:7002${baseRoute}` + // window.microApp.location.href = `http://localhost:7002${baseRoute}/` // path相同,刷新浏览器 + // window.microApp.location.href = `http://localhost:7002${baseRoute}?a=1` // search变化,刷新浏览器 - // window.microApp.location.pathname = '/micro-app/vite2/page2' // path改变,刷新浏览器 - // window.microApp.location.pathname = '/micro-app/vite2/page2#hash1' // 无法直接通过pathname修改hash的值,这里的写法是错误的,而且会导致浏览器刷新,需要完善一下 - // window.microApp.location.pathname = '/micro-app/vite2/page2?b=2' + // window.microApp.location.pathname = `${baseRoute}/element-plus` // path改变,刷新浏览器 + // window.microApp.location.pathname = `${baseRoute}/element-plus#hash1` // 无法直接通过pathname修改hash的值,这里的写法是错误的,而且会导致浏览器刷新,需要完善一下 + // window.microApp.location.pathname = `${baseRoute}/element-plus?b=2` // window.microApp.location.search = '?c=3' // search改变,刷新浏览器 // window.microApp.location.search = '?c=3' // search不变,刷新浏览器 @@ -317,13 +317,13 @@ setTimeout(() => { // window.microApp.location.hash = '#a' // hash不变,不发送popstate、hashchange事件 - // window.microApp.location.assign('/micro-app/vite2/page2') // path改变,刷新浏览器 - // window.microApp.location.assign('http://localhost:7001/micro-app/vite2/page2') // path不改变,刷新浏览器 - // window.microApp.location.assign('http://localhost:7001/micro-app/vite2/page2#abc') // path不变,hash改变,不刷新浏览器,发送popstate、hashchange事件 + // window.microApp.location.assign(`${baseRoute}/element-plus`) // path改变,刷新浏览器 + // window.microApp.location.assign(`http://localhost:7002${baseRoute}/element-plus`) // path不改变,刷新浏览器 + // window.microApp.location.assign(`http://localhost:7002${baseRoute}/element-plus#abc`) // path不变,hash改变,不刷新浏览器,发送popstate、hashchange事件 - // window.microApp.location.assign('/micro-app/vite2/page2') // 同上 - // window.microApp.location.replace('http://localhost:7001/micro-app/vite2/page2') // 同上 - // window.microApp.location.replace('http://localhost:7001/micro-app/vite2/page2#abc') // 同上 + // window.microApp.location.replace(`${baseRoute}/element-plus`) // 同上 + // window.microApp.location.replace(`http://localhost:7002${baseRoute}/element-plus`) // 同上 + // window.microApp.location.replace(`http://localhost:7002${baseRoute}/element-plus#abc`) // 同上 // window.microApp.location.reload() @@ -336,7 +336,7 @@ setTimeout(() => { * 基座和子应用都设置了/sugrec的代理,两者都可以正常拿到数据 * 但是当走子应用的代理时,headers信息只能拿到 content-length 和 content-type(with和iframe都一样) * 走基座的代理时,可以拿到所有的headers头信息 - * 子应用:/sugrec,默认补全为 http://localhost:7001/sugrec + * 子应用:/sugrec,默认补全为 http://localhost:7002/sugrec * 主应用:http://localhost:3000/sugrec * 注意:!! * iframe环境下,会自动使用base补全fetch的地址 diff --git a/dev/children/vite4/src/pages/home.vue b/dev/children/vite4/src/pages/home.vue index 6e0e678d0..6237c0db1 100644 --- a/dev/children/vite4/src/pages/home.vue +++ b/dev/children/vite4/src/pages/home.vue @@ -20,14 +20,14 @@ import HelloWorld from '../components/HelloWorld.vue' const testHref = () => { // 通过原生跳转会导致报错 - // location.href = 'http://localhost:7001/micro-app/vite2/#/page2' // 报错 - // location.href = '/micro-app/vite2/#/page2' // 报错 + // location.href = 'http://localhost:7001/micro-app/vite4/#/page2' // 报错 + // location.href = '/micro-app/vite4/#/page2' // 报错 // location.href = 'https://www.baidu.com/' // 报错 - // location.href = 'http://localhost:3000/micro-app/vite2/#/page2' // -- 不报错 + // location.href = 'http://localhost:3000/micro-app/vite4/#/page2' // -- 不报错 // vite环境下,通过window.microApp.location进行跳转 // window.microApp.location.href = 'https://www.baidu.com/' // origin不同,直接跳转页面 - window.microApp.location.href = '/micro-app/vite2/page2' + window.microApp.location.href = window.__MICRO_APP_BASE_ROUTE__ ? window.__MICRO_APP_BASE_ROUTE__ + '/element-plus' : '/micro-app/vite4/element-plus' } // parent.console.timeEnd('vite') diff --git a/dev/main-react16/src/global.jsx b/dev/main-react16/src/global.jsx index a7e94f9b2..9a67dcff9 100644 --- a/dev/main-react16/src/global.jsx +++ b/dev/main-react16/src/global.jsx @@ -195,17 +195,17 @@ microApp.start({ // }) // }, 10000) -window.addEventListener('popstate', (e) => { +window.addEventListener('hashchange', (e) => { // const a = document.createElement('div') - // a.innerHTML = '55555555' + // a.innerHTML = '666666666' // document.body.appendChild(a) - console.log('基座 popstate', 'state:', e.state) - // history.replaceState(history.state, '', location.href) + console.log('基座 hashchange', e,) }) -window.addEventListener('hashchange', (e) => { +window.addEventListener('popstate', (e) => { // const a = document.createElement('div') - // a.innerHTML = '666666666' + // a.innerHTML = '55555555' // document.body.appendChild(a) - console.log('基座 hashchange', e, e.newURL, e.oldURL) + console.log('基座 popstate', 'state:', e.state) + // history.replaceState(history.state, '', location.href) }) diff --git a/dev/main-react16/src/pages/vite2/vite2.js b/dev/main-react16/src/pages/vite2/vite2.js index c3668a571..1413318c7 100644 --- a/dev/main-react16/src/pages/vite2/vite2.js +++ b/dev/main-react16/src/pages/vite2/vite2.js @@ -104,7 +104,7 @@ function vite2 (props) { // disableSandbox iframe keep-router-state - disable-memory-router + // disable-memory-router // disable-patch-request // keep-alive // default-page='/micro-app/vite2/page2' diff --git a/dev/main-react16/src/pages/vite4/vite4.js b/dev/main-react16/src/pages/vite4/vite4.js index 4ef322557..3207d46b8 100644 --- a/dev/main-react16/src/pages/vite4/vite4.js +++ b/dev/main-react16/src/pages/vite4/vite4.js @@ -29,15 +29,15 @@ function vite4 (props) { } function jumpToHome () { - microApp.router.push({name: 'vite4', path: '/micro-app/vite4/'}) + microApp.router.push({name: 'vite4', path: '/micro-app/demo/vite4/'}) } function jumpToPage2 () { - microApp.router.push({name: 'vite4', path: '/micro-app/vite4/element-plus'}) + microApp.router.push({name: 'vite4', path: '/micro-app/demo/vite4/element-plus'}) } function jumpToPage3 () { - microApp.router.push({name: 'vite4', path: '/micro-app/vite4/ant-design-vue'}) + microApp.router.push({name: 'vite4', path: '/micro-app/demo/vite4/ant-design-vue'}) } function consoleRouteCurrent () { diff --git a/src/sandbox/iframe/index.ts b/src/sandbox/iframe/index.ts index 75fe1790a..5b5f6f4f2 100644 --- a/src/sandbox/iframe/index.ts +++ b/src/sandbox/iframe/index.ts @@ -169,6 +169,7 @@ export default class IframeSandbox { * 2. withSandbox location is browser location when disable memory-router, so no need to do anything */ /** + * TODO: * 做一些记录: * 1. iframe关闭虚拟路由系统后,default-page无法使用,推荐用户直接使用浏览器地址控制首页渲染 * 补充:keep-router-state 也无法配置,因为keep-router-state一定为true。 diff --git a/src/sandbox/router/api.ts b/src/sandbox/router/api.ts index 467bbd378..0eb5d60e8 100644 --- a/src/sandbox/router/api.ts +++ b/src/sandbox/router/api.ts @@ -39,6 +39,7 @@ import { getActiveApps } from '../../micro_app' import globalEnv from '../../libs/global_env' import { navigateWithNativeEvent, attachRouteToBrowserURL } from './history' import bindFunctionToRawTarget from '../bind_function' +import { updateMicroLocationWithEvent } from './event' export interface RouterApi { router: Router, @@ -99,13 +100,15 @@ function createRouterApi (): RouterApi { return function (to: RouterTarget): void { const appName = formatAppName(to.name) if (appName && isString(to.path)) { - const app = appInstanceMap.get(appName) - if (app && !isMemoryRouterEnabled(appName)) { - return logError(`navigation failed, memory router of app ${appName} is closed`) - } - // active apps, include hidden keep-alive app - if (getActiveApps({ excludePreRender: true }).includes(appName)) { - const microLocation = app!.sandBox!.proxyWindow.location as MicroLocation + /** + * active apps, exclude prerender app or hidden keep-alive app + * NOTE: + * 1. prerender app or hidden keep-alive app clear and record popstate event, so we cannot control app jump through the API + * 2. disable memory-router + */ + if (getActiveApps({ excludeHiddenApp: true, excludePreRender: true }).includes(appName)) { + const app = appInstanceMap.get(appName)! + const microLocation = app.sandBox!.proxyWindow.location as MicroLocation const targetLocation = createURL(to.path, microLocation.href) // Only get path data, even if the origin is different from microApp const currentFullPath = microLocation.pathname + microLocation.search + microLocation.hash @@ -113,24 +116,48 @@ function createRouterApi (): RouterApi { if (currentFullPath !== targetFullPath || getMicroPathFromURL(appName) !== targetFullPath) { const methodName = (replace && to.replace !== false) || to.replace === true ? 'replaceState' : 'pushState' navigateWithRawHistory(appName, methodName, targetLocation, to.state) + /** + * TODO: + * 1. 关闭虚拟路由的跳转地址不同:baseRoute + 子应用地址,文档中要说明 + * 2. 关闭虚拟路由时跳转方式不同:1、基座跳转但不发送popstate事件 2、控制子应用更新location,内部发送popstate事件。 + * 补充: + * 核心思路:减小对基座的影响(就是子应用跳转不向基座发送popstate事件,其他操作一致),但这是必要的吗,只是多了一个触发popstate的操作 + * 未来的思路有两种: + * 1、减少对基座的影响,主要是解决vue循环刷新的问题 + * 2、全局发送popstate事件,解决主、子都是vue3的冲突问题 + * 两者选一个吧,如果选2,则下面这两行代码可以去掉 + * 要不这样吧,history和search模式采用2,这样可以解决vue3的问题,custom采用1,避免vue循环刷新的问题,这样在用户出现问题时各有解决方案。但反过来说,每种方案又分别导致另外的问题,不统一,导致复杂度增高 + * 如果关闭虚拟路由,同时发送popstate事件还是无法解决vue3的问题(毕竟history.state理论上还是会冲突),那么就没必要发送popstate事件了。 + * 。。。。先这样吧 + */ + if (!isMemoryRouterEnabled(appName)) { + updateMicroLocationWithEvent(appName, targetFullPath) + } } } else { - /** - * app not exit or unmounted, update browser URL with replaceState - * use base app location.origin as baseURL - */ - const rawLocation = globalEnv.rawWindow.location - const targetLocation = createURL(to.path, rawLocation.origin) - const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash - if (getMicroPathFromURL(appName) !== targetFullPath) { - navigateWithRawHistory( - appName, - to.replace === false ? 'pushState' : 'replaceState', - targetLocation, - to.state, - ) - } + logWarn('navigation failed, app does not exist or is inactive') } + + // /** + // * app not exit or unmounted, update browser URL with replaceState + // * use base app location.origin as baseURL + // * 应用不存在或已卸载,依然使用replaceState来更新浏览器地址 -- 不合理 + // */ + // /** + // * TODO: 应用还没渲染或已经卸载最好不要支持跳转了,我知道这是因为解决一些特殊场景,但这么做是非常反直觉的 + // * 并且在新版本中有多种路由模式,如果应用不存在,我们根本无法知道是哪种模式,那么这里的操作就无意义了。 + // */ + // const rawLocation = globalEnv.rawWindow.location + // const targetLocation = createURL(to.path, rawLocation.origin) + // const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash + // if (getMicroPathFromURL(appName) !== targetFullPath) { + // navigateWithRawHistory( + // appName, + // to.replace === false ? 'pushState' : 'replaceState', + // targetLocation, + // to.state, + // ) + // } } else { logError(`navigation failed, name & path are required when use router.${replace ? 'replace' : 'push'}`) } diff --git a/src/sandbox/router/event.ts b/src/sandbox/router/event.ts index 8bcd8c1f7..c13040b9e 100644 --- a/src/sandbox/router/event.ts +++ b/src/sandbox/router/event.ts @@ -50,28 +50,7 @@ export function addHistoryListener (appName: string): CallableFunction { }).includes(appName) && !e.onlyForBrowser ) { - const microPath = getMicroPathFromURL(appName) - const app = appInstanceMap.get(appName)! - const proxyWindow = app.sandBox!.proxyWindow - const microAppWindow = app.sandBox!.microAppWindow - let isHashChange = false - // for hashChangeEvent - const oldHref = proxyWindow.location.href - // Do not attach micro state to url when microPath is empty - if (microPath) { - const oldHash = proxyWindow.location.hash - updateMicroLocation(appName, microPath, microAppWindow.location as MicroLocation) - isHashChange = proxyWindow.location.hash !== oldHash - } - - // dispatch formatted popStateEvent to child - dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow) - - // dispatch formatted hashChangeEvent to child when hash change - if (isHashChange) dispatchHashChangeEventToMicroApp(appName, proxyWindow, microAppWindow, oldHref) - - // clear element scope before trigger event of next app - removeDomScope() + updateMicroLocationWithEvent(appName, getMicroPathFromURL(appName)) } } @@ -82,6 +61,41 @@ export function addHistoryListener (appName: string): CallableFunction { } } +/** + * Effect: use to trigger child app jump + * Actions: + * 1. update microLocation with target path + * 2. dispatch popStateEvent & hashChangeEvent + * @param appName app name + * @param targetFullPath target path of child app + */ +export function updateMicroLocationWithEvent ( + appName: string, + targetFullPath: string | null, +): void { + const app = appInstanceMap.get(appName)! + const proxyWindow = app.sandBox!.proxyWindow + const microAppWindow = app.sandBox!.microAppWindow + let isHashChange = false + // for hashChangeEvent + const oldHref = proxyWindow.location.href + // Do not attach micro state to url when targetFullPath is empty + if (targetFullPath) { + const oldHash = proxyWindow.location.hash + updateMicroLocation(appName, targetFullPath, microAppWindow.location as MicroLocation) + isHashChange = proxyWindow.location.hash !== oldHash + } + + // dispatch formatted popStateEvent to child + dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow) + + // dispatch formatted hashChangeEvent to child when hash change + if (isHashChange) dispatchHashChangeEventToMicroApp(appName, proxyWindow, microAppWindow, oldHref) + + // clear element scope before trigger event of next app + removeDomScope() +} + /** * dispatch formatted popstate event to microApp * @param appName app name diff --git a/src/sandbox/router/history.ts b/src/sandbox/router/history.ts index 696b3423a..f54653997 100644 --- a/src/sandbox/router/history.ts +++ b/src/sandbox/router/history.ts @@ -141,6 +141,7 @@ export function navigateWithNativeEvent ( const oldHref = result.isAttach2Hash && oldFullPath !== result.fullPath ? rawLocation.href : null // navigate with native history method nativeHistoryNavigate(appName, methodName, result.fullPath, state, title) + // TODO: 如果所有模式统一发送popstate事件,则isMemoryRouterEnabled(appName)要去掉 if (oldFullPath !== result.fullPath && isMemoryRouterEnabled(appName)) { dispatchNativeEvent(appName, onlyForBrowser, oldHref) } diff --git a/src/sandbox/router/index.ts b/src/sandbox/router/index.ts index 0ed440d37..b1d80e488 100644 --- a/src/sandbox/router/index.ts +++ b/src/sandbox/router/index.ts @@ -26,6 +26,15 @@ export { addHistoryListener } from './event' export { getNoHashMicroPathFromURL } from './core' export { patchHistory, releasePatchHistory } from './history' +/** + * TODO: 关于关闭虚拟路由系统的临时笔记 + * 1. with沙箱关闭虚拟路由最好和iframe保持一致 + * 2. default-page无法使用,但是用基座的地址可以实现一样的效果 + * 3. keep-router-state功能失效,因为始终为true + * 4. 基座控制子应用跳转地址改变,正确的值为:baseRoute + 子应用地址,这要在文档中说明,否则很容易出错,确实也很难理解 + * 5. 是否需要发送popstate事件,为了减小对基座的影响,现在不发送 + * 6. 关闭后导致的vue3路由冲突问题需要在文档中明确指出(2处:在关闭虚拟路由系统的配置那里着重说明,在vue常见问题中说明) + */ /** * The router system has two operations: read and write * Read through location and write through history & location diff --git a/src/sandbox/router/location.ts b/src/sandbox/router/location.ts index a45c0e22e..06ad10a75 100644 --- a/src/sandbox/router/location.ts +++ b/src/sandbox/router/location.ts @@ -1,14 +1,39 @@ /* eslint-disable no-void */ -import type { MicroLocation, GuardLocation, microAppWindowType } from '@micro-app/types' +import type { + MicroLocation, + GuardLocation, + microAppWindowType, +} from '@micro-app/types' import globalEnv from '../../libs/global_env' -import { assign as oAssign, createURL, rawDefineProperty } from '../../libs/utils' -import { setMicroPathToURL, isEffectiveApp, getMicroState } from './core' -import { dispatchNativeEvent } from './event' -import { executeNavigationGuard } from './api' -import { nativeHistoryNavigate, navigateWithNativeEvent } from './history' -import { appInstanceMap, isIframeSandbox } from '../../create_app' -import { hijackMicroLocationKeys } from '../iframe/special_key' import bindFunctionToRawTarget from '../bind_function' +import { + assign as oAssign, + createURL, + rawDefineProperty, +} from '../../libs/utils' +import { + setMicroPathToURL, + isEffectiveApp, + getMicroState, + isMemoryRouterEnabled, +} from './core' +import { + dispatchNativeEvent, +} from './event' +import { + executeNavigationGuard, +} from './api' +import { + nativeHistoryNavigate, + navigateWithNativeEvent, +} from './history' +import { + appInstanceMap, + isIframeSandbox, +} from '../../create_app' +import { + hijackMicroLocationKeys, +} from '../iframe/special_key' // origin is readonly, so we ignore when updateMicroLocation const locationKeys: ReadonlyArray = ['href', 'pathname', 'search', 'hash', 'host', 'hostname', 'port', 'protocol', 'search'] @@ -62,37 +87,40 @@ export function createMicroLocation ( // Even if the origin is the same, developers still have the possibility of want to jump to a new page if (targetLocation.origin === proxyLocation.origin) { const setMicroPathResult = setMicroPathToURL(appName, targetLocation) - /** - * change hash with location.href will not trigger the browser reload - * so we use pushState & reload to imitate href behavior - * NOTE: - * 1. if child app only change hash, it should not trigger browser reload - * 2. if address is same and has hash, it should not add route stack - */ - if ( - targetLocation.pathname === proxyLocation.pathname && - targetLocation.search === proxyLocation.search - ) { - let oldHref = null - if (targetLocation.hash !== proxyLocation.hash) { - if (setMicroPathResult.isAttach2Hash) oldHref = rawLocation.href - nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath) - } + // if disable memory-router, navigate directly through rawLocation + if (isMemoryRouterEnabled(appName)) { + /** + * change hash with location.href will not trigger the browser reload + * so we use pushState & reload to imitate href behavior + * NOTE: + * 1. if child app only change hash, it should not trigger browser reload + * 2. if address is same and has hash, it should not add route stack + */ + if ( + targetLocation.pathname === proxyLocation.pathname && + targetLocation.search === proxyLocation.search + ) { + let oldHref = null + if (targetLocation.hash !== proxyLocation.hash) { + if (setMicroPathResult.isAttach2Hash) oldHref = rawLocation.href + nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath) + } - if (targetLocation.hash) { - dispatchNativeEvent(appName, false, oldHref) - } else { + if (targetLocation.hash) { + dispatchNativeEvent(appName, false, oldHref) + } else { + reload() + } + return void 0 + /** + * when baseApp is hash router, address change of child can not reload browser + * so we imitate behavior of browser (reload) manually + */ + } else if (setMicroPathResult.isAttach2Hash) { + nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath) reload() + return void 0 } - return void 0 - /** - * when baseApp is hash router, address change of child can not reload browser - * so we imitate behavior of browser (reload) manually - */ - } else if (setMicroPathResult.isAttach2Hash) { - nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath) - reload() - return void 0 } return setMicroPathResult.fullPath @@ -192,22 +220,34 @@ export function createMicroLocation ( rawLocation.href = createURL(targetPath, rawLocation.origin).href } } else if (key === 'pathname') { - const targetPath = ('/' + value).replace(/^\/+/, '/') + proxyLocation.search + proxyLocation.hash - handleForPathNameAndSearch(targetPath, 'pathname') + if (isMemoryRouterEnabled(appName)) { + const targetPath = ('/' + value).replace(/^\/+/, '/') + proxyLocation.search + proxyLocation.hash + handleForPathNameAndSearch(targetPath, 'pathname') + } else { + rawLocation.pathname = value + } } else if (key === 'search') { - const targetPath = proxyLocation.pathname + ('?' + value).replace(/^\?+/, '?') + proxyLocation.hash - handleForPathNameAndSearch(targetPath, 'search') + if (isMemoryRouterEnabled(appName)) { + const targetPath = proxyLocation.pathname + ('?' + value).replace(/^\?+/, '?') + proxyLocation.hash + handleForPathNameAndSearch(targetPath, 'search') + } else { + rawLocation.search = value + } } else if (key === 'hash') { - const targetPath = proxyLocation.pathname + proxyLocation.search + ('#' + value).replace(/^#+/, '#') - const targetLocation = createURL(targetPath, url) - // The same hash will not trigger popStateEvent - if (targetLocation.hash !== proxyLocation.hash) { - navigateWithNativeEvent( - appName, - 'pushState', - setMicroPathToURL(appName, targetLocation), - false, - ) + if (isMemoryRouterEnabled(appName)) { + const targetPath = proxyLocation.pathname + proxyLocation.search + ('#' + value).replace(/^#+/, '#') + const targetLocation = createURL(targetPath, url) + // The same hash will not trigger popStateEvent + if (targetLocation.hash !== proxyLocation.hash) { + navigateWithNativeEvent( + appName, + 'pushState', + setMicroPathToURL(appName, targetLocation), + false, + ) + } + } else { + rawLocation.hash = value } } else { Reflect.set(target, key, value)