diff --git a/packages/meta/package.json b/packages/meta/package.json index 72ca4aaac5..46a5b78469 100644 --- a/packages/meta/package.json +++ b/packages/meta/package.json @@ -10,9 +10,10 @@ "require": "./dist/module.js" } }, - "types": "./dist/runtime/index.d.ts", + "types": "./types.d.ts", "files": [ - "dist" + "dist", + "types.d.ts" ], "scripts": { "prepack": "unbuild" diff --git a/packages/meta/src/module.ts b/packages/meta/src/module.ts index f0639481e0..09c8cc0f2f 100644 --- a/packages/meta/src/module.ts +++ b/packages/meta/src/module.ts @@ -1,17 +1,38 @@ import { resolve } from 'upath' -import { defineNuxtModule } from '@nuxt/kit' +import { addPlugin, addTemplate, defineNuxtModule } from '@nuxt/kit' +import type { MetaObject } from '@nuxt/meta' export default defineNuxtModule({ name: 'meta', - setup (_options, nuxt) { + defaults: { + charset: 'utf-8', + viewport: 'width=device-width, initial-scale=1' + }, + setup (options, nuxt) { const runtimeDir = resolve(__dirname, 'runtime') + // Transpile @nuxt/meta nuxt.options.build.transpile.push('@nuxt/meta', runtimeDir) nuxt.options.alias['@nuxt/meta'] = resolve(runtimeDir, 'index') - nuxt.hook('app:resolve', (app) => { - app.plugins.push({ src: resolve(runtimeDir, 'vueuse-head') }) - app.plugins.push({ src: resolve(runtimeDir, 'meta') }) + // Global meta + const globalMeta: MetaObject = { + meta: [ + { charset: options.charset }, + { name: 'viewport', content: options.viewport } + ] + } + + // Add global meta configuration + addTemplate({ + filename: 'meta.config.mjs', + getContents: () => 'export default ' + JSON.stringify({ globalMeta }) }) + + // Add generic plugin + addPlugin({ src: resolve(runtimeDir, 'plugin') }) + + // Add library specific plugin + addPlugin({ src: resolve(runtimeDir, 'lib/vueuse-head.plugin') }) } }) diff --git a/packages/meta/src/runtime/components.ts b/packages/meta/src/runtime/components.ts index 07568a04ab..6af01fa28b 100644 --- a/packages/meta/src/runtime/components.ts +++ b/packages/meta/src/runtime/components.ts @@ -1,5 +1,5 @@ import { defineComponent, SetupContext } from 'vue' -import { useMeta } from './index' +import { useMeta } from './composables' type Props = Readonly> diff --git a/packages/meta/src/runtime/composables.ts b/packages/meta/src/runtime/composables.ts index 91664659f6..a36c5051af 100644 --- a/packages/meta/src/runtime/composables.ts +++ b/packages/meta/src/runtime/composables.ts @@ -1,7 +1,8 @@ // import { useMeta as useVueMeta } from 'vue-meta' import { isFunction } from '@vue/shared' import { computed, ComputedGetter } from '@vue/reactivity' -import { useHead } from '@vueuse/head' +import { useNuxt } from '@nuxt/app' +import type { MetaObject } from '@nuxt/meta' /** * You can pass in a meta object, which has keys corresponding to meta tags: @@ -10,16 +11,7 @@ import { useHead } from '@vueuse/head' * Alternatively, for reactive meta state, you can pass in a function * that returns a meta object. */ -export function useMeta (meta: Record | ComputedGetter) { - // TODO: refine @nuxt/meta API - - // At the moment we force all interaction to happen through passing in - // the meta object or function that returns a meta object. - const source = isFunction(meta) ? computed(meta) : meta - - // `vue-meta` - // useVueMeta(source) - - // `@vueuse/head` - useHead(source) +export function useMeta (meta: MetaObject | ComputedGetter) { + const resolvedMeta = isFunction(meta) ? computed(meta) : meta + useNuxt()._useMeta(resolvedMeta) } diff --git a/packages/meta/src/runtime/vue-meta.ts b/packages/meta/src/runtime/lib/vue-meta.plugin.ts similarity index 91% rename from packages/meta/src/runtime/vue-meta.ts rename to packages/meta/src/runtime/lib/vue-meta.plugin.ts index 5f59dbdefd..67e3837cb1 100644 --- a/packages/meta/src/runtime/vue-meta.ts +++ b/packages/meta/src/runtime/lib/vue-meta.plugin.ts @@ -1,12 +1,15 @@ import { defineNuxtPlugin } from '@nuxt/app' import { createApp } from 'vue' import { createMetaManager } from 'vue-meta' +import type { MetaObject } from '@nuxt/meta' export default defineNuxtPlugin((nuxt) => { const manager = createMetaManager(process.server) nuxt.app.use(manager) + nuxt._useMeta = (meta: MetaObject) => manager.addMeta(meta) + if (process.client) { const teleportTarget = document.createElement('div') teleportTarget.id = 'head-target' diff --git a/packages/meta/src/runtime/vueuse-head.ts b/packages/meta/src/runtime/lib/vueuse-head.plugin.ts similarity index 66% rename from packages/meta/src/runtime/vueuse-head.ts rename to packages/meta/src/runtime/lib/vueuse-head.plugin.ts index 6624a6f047..7c84927e07 100644 --- a/packages/meta/src/runtime/vueuse-head.ts +++ b/packages/meta/src/runtime/lib/vueuse-head.plugin.ts @@ -1,11 +1,15 @@ import { createHead, renderHeadToString } from '@vueuse/head' import { defineNuxtPlugin } from '@nuxt/app' +import { ref } from 'vue' +import type { MetaObject } from '@nuxt/meta' export default defineNuxtPlugin((nuxt) => { const head = createHead() nuxt.app.use(head) + nuxt._useMeta = (meta: MetaObject) => head.addHeadObjs(ref(meta as any)) + if (process.server) { nuxt.ssrContext.renderMeta = () => renderHeadToString(head) } diff --git a/packages/meta/src/runtime/meta.ts b/packages/meta/src/runtime/plugin.ts similarity index 77% rename from packages/meta/src/runtime/meta.ts rename to packages/meta/src/runtime/plugin.ts index a1e7be005b..04f0dfd7e3 100644 --- a/packages/meta/src/runtime/meta.ts +++ b/packages/meta/src/runtime/plugin.ts @@ -1,9 +1,13 @@ import { getCurrentInstance } from 'vue' import { defineNuxtPlugin } from '@nuxt/app' import * as Components from './components' -import { useMeta } from './index' +import { useMeta } from './composables' +// @ts-ignore +import metaConfig from '#build/meta.config.mjs' export default defineNuxtPlugin((nuxt) => { + useMeta(metaConfig.globalMeta) + nuxt.app.mixin({ created () { const instance = getCurrentInstance() diff --git a/packages/meta/types.d.ts b/packages/meta/types.d.ts new file mode 100644 index 0000000000..68faf7cf4a --- /dev/null +++ b/packages/meta/types.d.ts @@ -0,0 +1,23 @@ +export * from '@nuxt/meta/dist/runtime/composables' + +export interface MetaObject extends Record { + /** + * The character encoding in which the document is encoded => `` + * + * @default `'utf-8'` + */ + charset?: string + /** + * Configuration of the viewport (the area of the window in which web content can be seen), + * mapped to => `` + * + * @default `'width=device-width, initial-scale=1'` + */ + viewport?: string +} + +declare module '@nuxt/kit' { + interface NuxtConfig { + meta?: MetaObject, + } +}