Skip to content

Commit e5ab067

Browse files
committed
perf: hoist expensive operations in useLayout
1 parent 2803b7e commit e5ab067

File tree

3 files changed

+39
-20
lines changed

3 files changed

+39
-20
lines changed

Diff for: docs/en/reference/default-theme-config.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -466,15 +466,15 @@ Returns layout-related data. The returned object has the following type:
466466
interface {
467467
isHome: ComputedRef<boolean>
468468

469-
sidebar: ComputedRef<DefaultTheme.SidebarItem[]>
469+
sidebar: Readonly<ShallowRef<DefaultTheme.SidebarItem[]>>
470470
sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]>
471471
hasSidebar: ComputedRef<boolean>
472472
isSidebarEnabled: ComputedRef<boolean>
473473

474474
hasAside: ComputedRef<boolean>
475475
leftAside: ComputedRef<boolean>
476476

477-
headers: ShallowRef<DefaultTheme.OutlineItem[]>
477+
headers: Readonly<ShallowRef<DefaultTheme.OutlineItem[]>>
478478
hasLocalNav: ComputedRef<boolean>
479479
}
480480
```

Diff for: src/client/theme-default/composables/layout.ts

+35-16
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
1-
import { useMediaQuery } from '@vueuse/core'
2-
import { onContentUpdated, useRoute } from 'vitepress'
3-
import type { DefaultTheme } from 'vitepress/theme'
4-
import { computed, shallowRef, watch } from 'vue'
1+
import { inBrowser, onContentUpdated, useRoute } from 'vitepress'
2+
import type { DefaultTheme, useLayout as expected } from 'vitepress/theme'
3+
import { computed, shallowReadonly, shallowRef, watch } from 'vue'
54
import { getSidebar, getSidebarGroups } from '../support/sidebar'
65
import { useData } from './data'
76
import { getHeaders } from './outline'
87
import { useCloseSidebarOnEscape } from './sidebar'
98

109
const headers = shallowRef<DefaultTheme.OutlineItem[]>([])
10+
const sidebar = shallowRef<DefaultTheme.SidebarItem[]>([])
1111

12-
export function useLayout() {
13-
const { frontmatter, page, theme } = useData()
14-
const is960 = useMediaQuery('(min-width: 960px)')
12+
const is960 = shallowRef(false)
13+
14+
export function useLayout(): ReturnType<typeof expected> {
15+
const { frontmatter, theme } = useData()
1516

1617
const isHome = computed(() => {
1718
return !!(frontmatter.value.isHome ?? frontmatter.value.layout === 'home')
1819
})
1920

20-
const sidebar = computed(() => {
21-
const sidebarConfig = theme.value.sidebar
22-
const relativePath = page.value.relativePath
23-
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : []
24-
})
25-
2621
const hasSidebar = computed(() => {
2722
return (
2823
frontmatter.value.sidebar !== false &&
@@ -56,13 +51,13 @@ export function useLayout() {
5651

5752
return {
5853
isHome,
59-
sidebar,
54+
sidebar: shallowReadonly(sidebar),
6055
sidebarGroups,
6156
hasSidebar,
6257
isSidebarEnabled,
6358
hasAside,
6459
leftAside,
65-
headers,
60+
headers: shallowReadonly(headers),
6661
hasLocalNav
6762
}
6863
}
@@ -72,12 +67,36 @@ interface RegisterWatchersOptions {
7267
}
7368

7469
export function registerWatchers({ closeSidebar }: RegisterWatchersOptions) {
75-
const { frontmatter, theme } = useData()
70+
const { frontmatter, page, theme } = useData()
71+
72+
watch(
73+
() => [page.value.relativePath, theme.value.sidebar] as const,
74+
([relativePath, sidebarConfig]) => {
75+
const newSidebar = sidebarConfig
76+
? getSidebar(sidebarConfig, relativePath)
77+
: []
78+
if (JSON.stringify(newSidebar) !== JSON.stringify(sidebar.value)) {
79+
sidebar.value = newSidebar
80+
}
81+
},
82+
{ immediate: true, deep: true, flush: 'sync' }
83+
)
7684

7785
onContentUpdated(() => {
7886
headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline)
7987
})
8088

89+
if (inBrowser) {
90+
is960.value = window.innerWidth >= 960
91+
window.addEventListener(
92+
'resize',
93+
() => {
94+
is960.value = window.innerWidth >= 960
95+
},
96+
{ passive: true }
97+
)
98+
}
99+
81100
const route = useRoute()
82101
watch(() => route.path, closeSidebar)
83102

Diff for: theme.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default theme
1616
export declare const useLayout: () => {
1717
isHome: ComputedRef<boolean>
1818

19-
sidebar: ComputedRef<DefaultTheme.SidebarItem[]>
19+
sidebar: Readonly<ShallowRef<DefaultTheme.SidebarItem[]>>
2020
sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]>
2121
hasSidebar: ComputedRef<boolean>
2222
isSidebarEnabled: ComputedRef<boolean>
@@ -27,7 +27,7 @@ export declare const useLayout: () => {
2727
/**
2828
* The outline headers of the current page.
2929
*/
30-
headers: ShallowRef<DefaultTheme.OutlineItem[]>
30+
headers: Readonly<ShallowRef<DefaultTheme.OutlineItem[]>>
3131
/**
3232
* Whether the current page has a local nav. Local nav is shown when the
3333
* "outline" is present in the page. However, note that the actual

0 commit comments

Comments
 (0)