diff --git a/lib/app/composables/head.js b/lib/app/composables/head.js index a0aadf27..89056c44 100644 --- a/lib/app/composables/head.js +++ b/lib/app/composables/head.js @@ -1,11 +1,20 @@ import { watchEffect } from 'vue' -import { useSiteData } from './siteData' +import { siteDataRef } from './siteData' /** * @param {import('./pageData').PageDataRef} pageData */ export function useUpdateHead(pageData) { - const siteData = useSiteData() + const descriptionTag = createHeadElement(['meta', { + name: 'description', + content: siteDataRef.value.description + }]) + document.head.appendChild(descriptionTag) + + const updateTitleAndDescription = () => { + document.title = siteDataRef.value.title + descriptionTag.setAttribute('content', siteDataRef.value.description) + } /** * @type {HTMLElement[]} @@ -24,14 +33,8 @@ export function useUpdateHead(pageData) { tags.forEach((el) => document.head.removeChild(el)) tags.length = 0 if (newTags && newTags.length) { - newTags.forEach(([tag, attrs, innerHTML]) => { - const el = document.createElement(tag) - for (const key in attrs) { - el.setAttribute(key, attrs[key]) - } - if (innerHTML) { - el.innerHTML = innerHTML - } + newTags.forEach((headConfig) => { + const el = createHeadElement(headConfig) document.head.appendChild(el) tags.push(el) }) @@ -39,7 +42,8 @@ export function useUpdateHead(pageData) { } watchEffect(() => { - updateHeadTags(siteHeadTags, siteData.value.head) + updateTitleAndDescription() + updateHeadTags(siteHeadTags, siteDataRef.value.head) }) watchEffect(() => { @@ -49,3 +53,17 @@ export function useUpdateHead(pageData) { ) }) } + +/** + * @param {import('src').HeadConfig} item + */ +function createHeadElement([tag, attrs, innerHTML]) { + const el = document.createElement(tag) + for (const key in attrs) { + el.setAttribute(key, attrs[key]) + } + if (innerHTML) { + el.innerHTML = innerHTML + } + return el +} diff --git a/lib/app/composables/siteData.js b/lib/app/composables/siteData.js index 25d28071..b3d171b3 100644 --- a/lib/app/composables/siteData.js +++ b/lib/app/composables/siteData.js @@ -11,7 +11,7 @@ const parse = (data) => readonly(JSON.parse(data)) /** * @type {import('vue').Ref} */ -const siteDataRef = ref(parse(serialized)) +export const siteDataRef = ref(parse(serialized)) export function useSiteData() { return siteDataRef diff --git a/lib/app/index.js b/lib/app/index.js index 7b844837..1709ea04 100644 --- a/lib/app/index.js +++ b/lib/app/index.js @@ -1,14 +1,9 @@ -import { - createApp as createClientApp, - createSSRApp, - ref, - readonly -} from 'vue' +import { createApp as createClientApp, createSSRApp, ref, readonly } from 'vue' import { Content } from './components/Content' import { createRouter, RouterSymbol } from './router' import { useUpdateHead } from './composables/head' -import { useSiteData } from './composables/siteData' -import { usePageData, pageDataSymbol } from './composables/pageData' +import { siteDataRef } from './composables/siteData' +import { pageDataSymbol } from './composables/pageData' import Theme from '/@theme/index' import { hot } from '@hmr' @@ -17,6 +12,8 @@ const inBrowser = typeof window !== 'undefined' const NotFound = Theme.NotFound || (() => '404 Not Found') export function createApp() { + // unlike site data which is static across all requests, page data is + // distinct per-request. const pageDataRef = ref() if (__DEV__ && inBrowser) { @@ -74,18 +71,16 @@ export function createApp() { app.component('Content', Content) - app.mixin({ - beforeCreate() { - const siteRef = useSiteData() - const pageRef = usePageData() - Object.defineProperties(this, { - $site: { - get: () => siteRef.value - }, - $page: { - get: () => pageRef.value - } - }) + Object.defineProperties(app.config.globalProperties, { + $site: { + get() { + return siteDataRef.value + } + }, + $page: { + get() { + return pageDataRef.value + } } }) @@ -93,7 +88,7 @@ export function createApp() { Theme.enhanceApp({ app, router, - siteData: useSiteData() + siteData: siteDataRef }) }