Skip to content
This repository was archived by the owner on Apr 6, 2023. It is now read-only.
/frameworkPublic archive
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/nuxt/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,8 @@
"@nuxt/vite-builder": "3.0.0-rc.13",
"@vue/reactivity": "^3.2.45",
"@vue/shared": "^3.2.45",
"@vueuse/head": "~1.0.0-rc.14",
"@vueuse/head": "^1.0.0",
"@unhead/ssr": "^0.6.0",
"chokidar": "^3.5.3",
"cookie-es": "^0.5.0",
"defu": "^6.1.0",
Expand Down
8 changes: 4 additions & 4 deletions packages/nuxt/src/head/runtime/composables.ts
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
import type { MetaObject } from '@nuxt/schema'
import type { MaybeComputedRef } from '@vueuse/head'
import type { UseHeadInput } from '@vueuse/head'
import type { HeadAugmentations } from '@nuxt/schema'
import { useNuxtApp } from '#app'

/**
Expand All@@ -9,12 +9,12 @@ import { useNuxtApp } from '#app'
* Alternatively, for reactive meta state, you can pass in a function
* that returns a meta object.
*/
export function useHead(meta: MaybeComputedRef<MetaObject>) {
export function useHead<T extends HeadAugmentations> (meta: UseHeadInput<T>) {
useNuxtApp()._useHead(meta)
}

// TODO: remove useMeta support when Nuxt 3 is stable
/** @deprecated Please use new `useHead` composable instead */
export function useMeta(meta: MaybeComputedRef<MetaObject>) {
export function useMeta<T extends HeadAugmentations> (meta: UseHeadInput<T>) {
return useHead(meta)
}
5 changes: 4 additions & 1 deletion packages/nuxt/src/head/runtime/index.ts
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
import type { UseHeadInput } from '@vueuse/head'
import type { HeadAugmentations } from '@nuxt/schema'
export * from './composables'
export type { MetaObject } from '@nuxt/schema'

export type MetaObject = UseHeadInput<HeadAugmentations>
63 changes: 24 additions & 39 deletions packages/nuxt/src/head/runtime/lib/vueuse-head.plugin.ts
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,49 @@
import type { HeadEntryOptions, MaybeComputedRef } from '@vueuse/head'
import { createHead, renderHeadToString } from '@vueuse/head'
import { onBeforeUnmount, getCurrentInstance } from 'vue'
import type { MetaObject } from '@nuxt/schema'
import { defineNuxtPlugin, useRouter } from '#app'
import { createHead, useHead } from '@vueuse/head'
import { defineNuxtPlugin } from '#app'
// @ts-expect-error untyped
import { appHead } from '#build/nuxt.config.mjs'

export default defineNuxtPlugin((nuxtApp) => {
const head = createHead()

head.addEntry(appHead, { resolved: true })
// we can server side render the head without having the client hydrate it
if (process.server) {
head.push(appHead, { mode: 'server' })
}

if (process.client && nuxtApp.ssrContext?.noSSR) {
head.push(appHead)
}

nuxtApp.vueApp.use(head)

if (process.client) {
// pause dom updates until page is ready and between page transitions
let pauseDOMUpdates = true
head.hooks['before:dom'].push(() => !pauseDOMUpdates)
nuxtApp.hooks.hookOnce('app:mounted', () => {
const unpauseDom = () => {
pauseDOMUpdates = false
head.updateDOM()

// start pausing DOM updates when route changes (trigger immediately)
useRouter().beforeEach(() => {
pauseDOMUpdates = true
})
// watch for new route before unpausing dom updates (triggered after suspense resolved)
useRouter().afterEach(() => {
// only if we have paused (clicking on a link to the current route triggers this)
if (pauseDOMUpdates) {
pauseDOMUpdates = false
head.updateDOM()
}
})
})
}

nuxtApp._useHead = (_meta: MaybeComputedRef<MetaObject>, options: HeadEntryOptions) => {
if (process.server) {
head.addEntry(_meta, options)
return
// triggers dom update
head.hooks.callHook('entries:updated', head)
}

const cleanUp = head.addReactiveEntry(_meta, options)

const vm = getCurrentInstance()
if (!vm) { return }

onBeforeUnmount(() => {
cleanUp()
head.updateDOM()
head.hooks.hook('dom:beforeRender', (context) => {
context.shouldRender = !pauseDOMUpdates
})
nuxtApp.hooks.hook('page:start', () => { pauseDOMUpdates = true })
// watch for new route before unpausing dom updates (triggered after suspense resolved)
nuxtApp.hooks.hook('page:finish', unpauseDom)
nuxtApp.hooks.hook('app:mounted', unpauseDom)
}

nuxtApp._useHead = useHead

if (process.server) {
nuxtApp.ssrContext!.renderMeta = async () => {
const meta = await renderHeadToString(head)
const { renderSSRHead } = await import('@unhead/ssr')
const meta = await renderSSRHead(head)
return {
...meta,
// resolves naming difference with NuxtMeta and @vueuse/head
bodyScriptsPrepend: meta.bodyTagsOpen,
bodyScripts: meta.bodyTags
}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/nuxt/src/head/runtime/mixin-plugin.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,6 +15,8 @@ const metaMixin = {
? () => options.head(nuxtApp)
: options.head

console.log('mixin', source)

useHead(source)
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/build.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,7 @@ export default defineBuildConfig({
'vue-meta',
'vue-router',
'vue-bundle-renderer',
'@vueuse/head',
'@unhead/schema',
'vue',
'hookable',
'nitropack',
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,9 +17,9 @@
"@types/lodash.template": "^4",
"@types/semver": "^7",
"@vitejs/plugin-vue": "^3.2.0",
"@vueuse/head": "~1.0.0-rc.14",
"nitropack": "^0.6.1",
"unbuild": "latest",
"@unhead/schema": "^0.6.0",
"vite": "~3.2.3"
},
"dependencies": {
Expand Down
71 changes: 2 additions & 69 deletions packages/schema/src/types/meta.ts
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
import type { HeadObjectPlain, HeadObject } from '@vueuse/head'
import type { Head } from '@unhead/schema'

export interface HeadAugmentations {
// runtime type modifications
Expand All@@ -12,7 +12,7 @@ export interface HeadAugmentations {
bodyAttrs?: {}
}

export type MetaObjectRaw = HeadObjectPlain<HeadAugmentations>
export type MetaObjectRaw = Head<HeadAugmentations>

export type AppHeadMetaObject = MetaObjectRaw & {
/**
Expand All@@ -29,70 +29,3 @@ export type AppHeadMetaObject = MetaObjectRaw & {
*/
viewport?: string
}

export interface MetaObject {

@harlan-zwharlan-zwNov 11, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't figure out why this needed to be exposed by @nuxt/schema exactly. The reactive object is only passed used as an argument for the useHead function, nuxt.config.ts uses the non-reactive schema.

The nuxt app itself exposes it as well. If we remove it then we don't need to depend on import the full module for the types

/**
* The <title> HTML element defines the document's title that is shown in a browser's title bar or a page's tab.
* It only contains text; tags within the element are ignored.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title
*/
title?: HeadObject<HeadAugmentations>['title']
/**
* Generate the title from a template.
*/
titleTemplate?: HeadObject<HeadAugmentations>['titleTemplate']
/**
* The <base> HTML element specifies the base URL to use for all relative URLs in a document.
* There can be only one <base> element in a document.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
*/
base?: HeadObject<HeadAugmentations>['base']
/**
* The <link> HTML element specifies relationships between the current document and an external resource.
* This element is most commonly used to link to stylesheets, but is also used to establish site icons
* (both "favicon" style icons and icons for the home screen and apps on mobile devices) among other things.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#attr-as
*/
link?: HeadObject<HeadAugmentations>['link']
/**
* The <meta> element represents metadata that cannot be expressed in other HTML elements, like <link> or <script>.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
*/
meta?: HeadObject<HeadAugmentations>['meta']
/**
* The <style> HTML element contains style information for a document, or part of a document.
* It contains CSS, which is applied to the contents of the document containing the <style> element.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style
*/
style?: HeadObject<HeadAugmentations>['style']
/**
* The <script> HTML element is used to embed executable code or data; this is typically used to embed or refer to JavaScript code.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
*/
script?: HeadObject<HeadAugmentations>['script']
/**
* The <noscript> HTML element defines a section of HTML to be inserted if a script type on the page is unsupported
* or if scripting is currently turned off in the browser.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript
*/
noscript?: HeadObject<HeadAugmentations>['noscript']
/**
* Attributes for the <html> HTML element.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html
*/
htmlAttrs?: HeadObject<HeadAugmentations>['htmlAttrs']
/**
* Attributes for the <body> HTML element.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body
*/
bodyAttrs?: HeadObject<HeadAugmentations>['bodyAttrs']
}
Loading