diff --git a/packages/vue-renderer/src/renderers/spa.js b/packages/vue-renderer/src/renderers/spa.js index 578d83466c..55a2b1bf31 100644 --- a/packages/vue-renderer/src/renderers/spa.js +++ b/packages/vue-renderer/src/renderers/spa.js @@ -1,6 +1,5 @@ import { extname } from 'path' import cloneDeep from 'lodash/cloneDeep' -import Vue from 'vue' import VueMeta from 'vue-meta' import { createRenderer } from 'vue-server-renderer' import LRU from 'lru-cache' @@ -13,29 +12,19 @@ export default class SPARenderer extends BaseRenderer { this.cache = new LRU() - // Add VueMeta to Vue (this is only for SPA mode) - // See app/index.js - Vue.use(VueMeta, { + this.vueMetaConfig = { keyName: 'head', attribute: 'data-n-head', ssrAttribute: 'data-n-head-ssr', + ssrAppId: '1', tagIDKeyName: 'hid' - }) + } } createRenderer () { return createRenderer() } - async getMeta () { - const vm = new Vue({ - render: h => h(), // Render empty html tag - head: this.options.head || {} - }) - await this.vueRenderer.renderToString(vm) - return vm.$meta().inject() - } - async render (renderContext) { const { url = '/', req = {}, _generate } = renderContext const modernMode = this.options.modern @@ -54,11 +43,19 @@ export default class SPARenderer extends BaseRenderer { HEAD_ATTRS: '', BODY_ATTRS: '', HEAD: '', + BODY_SCRIPTS_PREPEND: '', BODY_SCRIPTS: '' } // Get vue-meta context - const m = await this.getMeta() + let head + if (typeof this.options.head === 'function') { + head = this.options.head() + } else { + head = this.options.head + } + + const m = VueMeta.generate(head || {}, this.vueMetaConfig) // HTML_ATTRS meta.HTML_ATTRS = m.htmlAttrs.text() @@ -78,11 +75,23 @@ export default class SPARenderer extends BaseRenderer { m.script.text() + m.noscript.text() - // BODY_SCRIPTS - meta.BODY_SCRIPTS = m.script.text({ body: true }) + m.noscript.text({ body: true }) + // BODY_SCRIPTS (PREPEND) + meta.BODY_SCRIPTS_PREPEND = + m.meta.text({ pbody: true }) + + m.link.text({ pbody: true }) + + m.style.text({ pbody: true }) + + m.script.text({ pbody: true }) + + m.noscript.text({ pbody: true }) + + // BODY_SCRIPTS (APPEND) + meta.BODY_SCRIPTS = + m.meta.text({ body: true }) + + m.link.text({ body: true }) + + m.style.text({ body: true }) + + m.script.text({ body: true }) + + m.noscript.text({ body: true }) // Resources Hints - meta.resourceHints = '' const { resources: { modernManifest, clientManifest } } = this.serverContext @@ -131,7 +140,7 @@ export default class SPARenderer extends BaseRenderer { } } - const APP = `
${this.serverContext.resources.loadingHTML}
${meta.BODY_SCRIPTS}` + const APP = `${meta.BODY_SCRIPTS_PREPEND}
${this.serverContext.resources.loadingHTML}
${meta.BODY_SCRIPTS}` // Prepare template params const templateParams = { diff --git a/packages/vue-renderer/src/renderers/ssr.js b/packages/vue-renderer/src/renderers/ssr.js index e46afc8760..2891eaa219 100644 --- a/packages/vue-renderer/src/renderers/ssr.js +++ b/packages/vue-renderer/src/renderers/ssr.js @@ -109,6 +109,17 @@ export default class SSRRenderer extends BaseRenderer { // Inject styles HEAD += renderContext.renderStyles() + const BODY_PREPEND = + m.meta.text({ pbody: true }) + + m.link.text({ pbody: true }) + + m.style.text({ pbody: true }) + + m.script.text({ pbody: true }) + + m.noscript.text({ pbody: true }) + + if (BODY_PREPEND) { + APP = `${BODY_PREPEND}${APP}` + } + // Serialize state const serializedSession = `window.${this.serverContext.globals.context}=${devalue(renderContext.nuxt)};` if (shouldInjectScripts) { @@ -140,12 +151,17 @@ export default class SSRRenderer extends BaseRenderer { if (shouldInjectScripts) { APP += this.renderScripts(renderContext) } + + // Append body scripts + APP += m.meta.text({ body: true }) + APP += m.link.text({ body: true }) + APP += m.style.text({ body: true }) APP += m.script.text({ body: true }) APP += m.noscript.text({ body: true }) // Template params const templateParams = { - HTML_ATTRS: 'data-n-head-ssr ' + m.htmlAttrs.text(), + HTML_ATTRS: m.htmlAttrs.text(true /* addSrrAttribute */), HEAD_ATTRS: m.headAttrs.text(), BODY_ATTRS: m.bodyAttrs.text(), HEAD,