From 958ccad570e9f4429e1b8d035f4b495f4616c5b8 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 6 Oct 2021 10:21:46 +0200 Subject: [PATCH 01/13] feat(bridge): use `useMeta` in bridge projects * includes `nuxt.app` shim and `vue` module that exports composition api functions --- packages/bridge/package.json | 1 + packages/bridge/src/global-imports.ts | 4 +- packages/bridge/src/meta.ts | 62 ++++++++++++++++++++++ packages/bridge/src/module.ts | 17 +++++- packages/bridge/src/nitro.ts | 6 --- packages/bridge/src/runtime/app.plugin.mjs | 21 ++++++++ packages/bridge/src/runtime/meta | 1 + packages/bridge/src/runtime/vue.mjs | 7 +++ packages/kit/src/config/schema/_app.ts | 16 ++++++ packages/nuxt3/src/meta/module.ts | 11 ++-- packages/nuxt3/src/meta/runtime/plugin.ts | 7 +-- test/fixtures/bridge/pages/index.vue | 6 +++ yarn.lock | 1 + 13 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 packages/bridge/src/meta.ts create mode 120000 packages/bridge/src/runtime/meta create mode 100644 packages/bridge/src/runtime/vue.mjs diff --git a/packages/bridge/package.json b/packages/bridge/package.json index f17f512ef71..e11da524f2a 100644 --- a/packages/bridge/package.json +++ b/packages/bridge/package.json @@ -19,6 +19,7 @@ "@nuxt/nitro": "3.0.0", "@nuxt/postcss8": "^1.1.3", "@vue/composition-api": "^1.2.3", + "@vueuse/head": "^0.6.0", "acorn": "^8.5.0", "defu": "^5.0.0", "enhanced-resolve": "^5.8.3", diff --git a/packages/bridge/src/global-imports.ts b/packages/bridge/src/global-imports.ts index 5fb4fc2758f..68a1100e013 100644 --- a/packages/bridge/src/global-imports.ts +++ b/packages/bridge/src/global-imports.ts @@ -3,7 +3,6 @@ import globalImports from '../../nuxt3/src/global-imports/module' // TODO: implement these: https://github.com/nuxt/framework/issues/549 const disabled = [ - 'useMeta', 'useAsyncData', 'asyncData' ] @@ -17,6 +16,9 @@ const identifiers = { 'useRouter', 'useRuntimeConfig' ], + '#meta': [ + 'useMeta' + ], '@vue/composition-api': [ // lifecycle 'onActivated', diff --git a/packages/bridge/src/meta.ts b/packages/bridge/src/meta.ts new file mode 100644 index 00000000000..13f10023659 --- /dev/null +++ b/packages/bridge/src/meta.ts @@ -0,0 +1,62 @@ +import { resolve } from 'pathe' +import defu from 'defu' +import { resolveModule, defineNuxtModule, addTemplate, addPlugin } from '@nuxt/kit' +import type { MetaObject } from '../../nuxt3/src/meta/runtime' +import { distDir } from './dirs' + +const checkDocsMsg = 'Please see https://v3.nuxtjs.org for more information.' +const msgPrefix = '[bridge] [meta]' + +export default defineNuxtModule({ + name: 'meta', + defaults: { + charset: 'utf-8', + viewport: 'width=device-width, initial-scale=1' + }, + setup (options, nuxt) { + // Alias vue to a vue3-compat version of vue2 + nuxt.options.alias['#vue'] = nuxt.options.alias.vue || resolveModule('vue/dist/vue.runtime.esm.js', { paths: nuxt.options.modulesDir }) + nuxt.options.alias['@vue/shared'] = 'vue' + nuxt.options.alias['@vue/reactivity'] = 'vue' + nuxt.options.alias.vue = resolve(distDir, 'runtime/vue.mjs') + + // Turn off vue-meta and migrate configuration + nuxt.options.features.meta = false + if (nuxt.options.head) { + if (typeof nuxt.options.head === 'function') { + throw new TypeError(`${msgPrefix} Please move head() function from \`nuxt.config\` to \`app.vue\`. ${checkDocsMsg}`) + } else { + console.warn(`${msgPrefix} Please rename \`head\` to \`meta\` in your \`nuxt.config\`. ${checkDocsMsg}`) + nuxt.options.meta = defu(nuxt.options.meta, nuxt.options.head) + } + } + + const runtimeDir = resolve(distDir, 'runtime/meta') + + // Transpile @nuxt/meta and @vueuse/head + nuxt.options.build.transpile.push(runtimeDir, 'vue', '@vueuse/head') + + // Add #meta alias + nuxt.options.alias['#meta'] = runtimeDir + + // Global meta + const globalMeta: MetaObject = defu(nuxt.options.meta, { + meta: [ + { charset: options.charset }, + { name: 'viewport', content: options.viewport } + ] + }) + + // Add global meta configuration + addTemplate({ + filename: 'meta.config.mjs', + getContents: () => 'export default ' + JSON.stringify({ globalMeta, mixinKey: 'setup' }) + }) + + // Add generic plugin + addPlugin({ src: resolve(runtimeDir, 'plugin') }) + + // Add library specific plugin + addPlugin({ src: resolve(runtimeDir, 'lib/vueuse-head.plugin') }) + } +}) diff --git a/packages/bridge/src/module.ts b/packages/bridge/src/module.ts index ef843c93b92..6ebe0fd7b17 100644 --- a/packages/bridge/src/module.ts +++ b/packages/bridge/src/module.ts @@ -1,11 +1,14 @@ import { createRequire } from 'module' -import { defineNuxtModule, installModule, checkNuxtCompatibilityIssues } from '@nuxt/kit' +import { defineNuxtModule, installModule, checkNuxtCompatibilityIssues, addPluginTemplate } from '@nuxt/kit' +import { resolve } from 'pathe' import { setupNitroBridge } from './nitro' import { setupAppBridge } from './app' import { setupCAPIBridge } from './capi' import { setupBetterResolve } from './resolve' import { setupGlobalImports } from './global-imports' import { setupTypescript } from './typescript' +import metaModule from './meta' +import { distDir } from './dirs' export interface BridgeConfig { nitro: boolean @@ -13,9 +16,9 @@ export interface BridgeConfig { app: boolean | {} capi: boolean | {} globalImports: boolean + meta: boolean constraints: boolean postcss8: boolean - swc: boolean resolve: boolean typescript: boolean } @@ -30,6 +33,7 @@ export default defineNuxtModule({ capi: {}, globalImports: true, constraints: true, + meta: true, // TODO: Remove from 2.16 postcss8: true, typescript: true, @@ -78,6 +82,15 @@ export default defineNuxtModule({ } }) } + if (opts.meta) { + await installModule(nuxt, metaModule) + } else if (nuxt.options.features.meta) { + // Nitro server plugin (for vue-meta) + addPluginTemplate({ + filename: 'nitro-bridge.server.mjs', + src: resolve(distDir, 'runtime/nitro-bridge.server.mjs') + }) + } } }) diff --git a/packages/bridge/src/nitro.ts b/packages/bridge/src/nitro.ts index a018ea2f2f6..82480ca8eda 100644 --- a/packages/bridge/src/nitro.ts +++ b/packages/bridge/src/nitro.ts @@ -80,12 +80,6 @@ export function setupNitroBridge () { src: resolve(nitroContext._internal.runtimeDir, 'app/nitro.client.mjs') }) - // Nitro server plugin (for vue-meta) - addPluginTemplate({ - filename: 'nitro-bridge.server.mjs', - src: resolve(distDir, 'runtime/nitro-bridge.server.mjs') - }) - // Fix module resolution nuxt.hook('webpack:config', (configs) => { for (const config of configs) { diff --git a/packages/bridge/src/runtime/app.plugin.mjs b/packages/bridge/src/runtime/app.plugin.mjs index 82c18b0ef48..0762815b075 100644 --- a/packages/bridge/src/runtime/app.plugin.mjs +++ b/packages/bridge/src/runtime/app.plugin.mjs @@ -1,14 +1,31 @@ +import Vue from 'vue' import { createHooks } from 'hookable/dist/index.mjs' import { setNuxtInstance } from '#app' export default (ctx, inject) => { const nuxt = { + app: { + component: Vue.component.bind(Vue), + config: { + globalProperties: {} + }, + directive: Vue.directive.bind(Vue), + mixin: Vue.mixin.bind(Vue), + mount: () => {}, + provide: inject, + unmount: () => {}, + use (vuePlugin) { + vuePlugin.install(this) + }, + version: Vue.version + }, provide: inject, globalName: 'nuxt', payload: process.client ? ctx.nuxtState : ctx.ssrContext.nuxt, isHydrating: ctx.isHMR, legacyNuxt: ctx.app } + nuxt.hooks = createHooks() nuxt.hook = nuxt.hooks.hook nuxt.callHook = nuxt.hooks.callHook @@ -17,6 +34,10 @@ export default (ctx, inject) => { ctx.app.created = [ctx.app.created] } + if (process.server) { + nuxt.ssrContext = ctx.ssrContext + } + ctx.app.created.push(function () { nuxt.legacyApp = this }) diff --git a/packages/bridge/src/runtime/meta b/packages/bridge/src/runtime/meta new file mode 120000 index 00000000000..211ee41b7fe --- /dev/null +++ b/packages/bridge/src/runtime/meta @@ -0,0 +1 @@ +../../../nuxt3/src/meta/runtime \ No newline at end of file diff --git a/packages/bridge/src/runtime/vue.mjs b/packages/bridge/src/runtime/vue.mjs new file mode 100644 index 00000000000..52d77b5b148 --- /dev/null +++ b/packages/bridge/src/runtime/vue.mjs @@ -0,0 +1,7 @@ +import Vue from '#vue' + +export * from '@vue/composition-api' + +export const isFunction = fn => fn instanceof Function + +export { Vue as default } diff --git a/packages/kit/src/config/schema/_app.ts b/packages/kit/src/config/schema/_app.ts index e246afa8e60..07cff87001f 100644 --- a/packages/kit/src/config/schema/_app.ts +++ b/packages/kit/src/config/schema/_app.ts @@ -103,6 +103,22 @@ export default { script: [] }, + /** + * Set default configuration for `` on every page. + * + * @version 3 + */ + meta: { + /** Each item in the array maps to a newly-created `` element, where object properties map to attributes. */ + meta: [], + /** Each item in the array maps to a newly-created `` element, where object properties map to attributes. */ + link: [], + /** Each item in the array maps to a newly-created `