perf: hoist expensive operations in useLayout

pull/4600/merge
Divyansh Singh 5 months ago
parent 2803b7e330
commit e5ab0676a9

@ -466,7 +466,7 @@ Returns layout-related data. The returned object has the following type:
interface { interface {
isHome: ComputedRef<boolean> isHome: ComputedRef<boolean>
sidebar: ComputedRef<DefaultTheme.SidebarItem[]> sidebar: Readonly<ShallowRef<DefaultTheme.SidebarItem[]>>
sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]> sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]>
hasSidebar: ComputedRef<boolean> hasSidebar: ComputedRef<boolean>
isSidebarEnabled: ComputedRef<boolean> isSidebarEnabled: ComputedRef<boolean>
@ -474,7 +474,7 @@ interface {
hasAside: ComputedRef<boolean> hasAside: ComputedRef<boolean>
leftAside: ComputedRef<boolean> leftAside: ComputedRef<boolean>
headers: ShallowRef<DefaultTheme.OutlineItem[]> headers: Readonly<ShallowRef<DefaultTheme.OutlineItem[]>>
hasLocalNav: ComputedRef<boolean> hasLocalNav: ComputedRef<boolean>
} }
``` ```

@ -1,28 +1,23 @@
import { useMediaQuery } from '@vueuse/core' import { inBrowser, onContentUpdated, useRoute } from 'vitepress'
import { onContentUpdated, useRoute } from 'vitepress' import type { DefaultTheme, useLayout as expected } from 'vitepress/theme'
import type { DefaultTheme } from 'vitepress/theme' import { computed, shallowReadonly, shallowRef, watch } from 'vue'
import { computed, shallowRef, watch } from 'vue'
import { getSidebar, getSidebarGroups } from '../support/sidebar' import { getSidebar, getSidebarGroups } from '../support/sidebar'
import { useData } from './data' import { useData } from './data'
import { getHeaders } from './outline' import { getHeaders } from './outline'
import { useCloseSidebarOnEscape } from './sidebar' import { useCloseSidebarOnEscape } from './sidebar'
const headers = shallowRef<DefaultTheme.OutlineItem[]>([]) const headers = shallowRef<DefaultTheme.OutlineItem[]>([])
const sidebar = shallowRef<DefaultTheme.SidebarItem[]>([])
export function useLayout() { const is960 = shallowRef(false)
const { frontmatter, page, theme } = useData()
const is960 = useMediaQuery('(min-width: 960px)') export function useLayout(): ReturnType<typeof expected> {
const { frontmatter, theme } = useData()
const isHome = computed(() => { const isHome = computed(() => {
return !!(frontmatter.value.isHome ?? frontmatter.value.layout === 'home') return !!(frontmatter.value.isHome ?? frontmatter.value.layout === 'home')
}) })
const sidebar = computed(() => {
const sidebarConfig = theme.value.sidebar
const relativePath = page.value.relativePath
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : []
})
const hasSidebar = computed(() => { const hasSidebar = computed(() => {
return ( return (
frontmatter.value.sidebar !== false && frontmatter.value.sidebar !== false &&
@ -56,13 +51,13 @@ export function useLayout() {
return { return {
isHome, isHome,
sidebar, sidebar: shallowReadonly(sidebar),
sidebarGroups, sidebarGroups,
hasSidebar, hasSidebar,
isSidebarEnabled, isSidebarEnabled,
hasAside, hasAside,
leftAside, leftAside,
headers, headers: shallowReadonly(headers),
hasLocalNav hasLocalNav
} }
} }
@ -72,12 +67,36 @@ interface RegisterWatchersOptions {
} }
export function registerWatchers({ closeSidebar }: RegisterWatchersOptions) { export function registerWatchers({ closeSidebar }: RegisterWatchersOptions) {
const { frontmatter, theme } = useData() const { frontmatter, page, theme } = useData()
watch(
() => [page.value.relativePath, theme.value.sidebar] as const,
([relativePath, sidebarConfig]) => {
const newSidebar = sidebarConfig
? getSidebar(sidebarConfig, relativePath)
: []
if (JSON.stringify(newSidebar) !== JSON.stringify(sidebar.value)) {
sidebar.value = newSidebar
}
},
{ immediate: true, deep: true, flush: 'sync' }
)
onContentUpdated(() => { onContentUpdated(() => {
headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline) headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline)
}) })
if (inBrowser) {
is960.value = window.innerWidth >= 960
window.addEventListener(
'resize',
() => {
is960.value = window.innerWidth >= 960
},
{ passive: true }
)
}
const route = useRoute() const route = useRoute()
watch(() => route.path, closeSidebar) watch(() => route.path, closeSidebar)

4
theme.d.ts vendored

@ -16,7 +16,7 @@ export default theme
export declare const useLayout: () => { export declare const useLayout: () => {
isHome: ComputedRef<boolean> isHome: ComputedRef<boolean>
sidebar: ComputedRef<DefaultTheme.SidebarItem[]> sidebar: Readonly<ShallowRef<DefaultTheme.SidebarItem[]>>
sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]> sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]>
hasSidebar: ComputedRef<boolean> hasSidebar: ComputedRef<boolean>
isSidebarEnabled: ComputedRef<boolean> isSidebarEnabled: ComputedRef<boolean>
@ -27,7 +27,7 @@ export declare const useLayout: () => {
/** /**
* The outline headers of the current page. * The outline headers of the current page.
*/ */
headers: ShallowRef<DefaultTheme.OutlineItem[]> headers: Readonly<ShallowRef<DefaultTheme.OutlineItem[]>>
/** /**
* Whether the current page has a local nav. Local nav is shown when the * Whether the current page has a local nav. Local nav is shown when the
* "outline" is present in the page. However, note that the actual * "outline" is present in the page. However, note that the actual

Loading…
Cancel
Save