2018-03-16 16:12:06 +00:00
|
|
|
import Vue from 'vue'
|
|
|
|
import VueMeta from 'vue-meta'
|
|
|
|
import VueServerRenderer from 'vue-server-renderer'
|
|
|
|
import LRU from 'lru-cache'
|
2017-08-18 16:05:01 +00:00
|
|
|
|
2018-03-16 16:12:06 +00:00
|
|
|
export default class MetaRenderer {
|
2017-10-30 16:51:11 +00:00
|
|
|
constructor(nuxt, renderer) {
|
2017-08-18 16:05:01 +00:00
|
|
|
this.nuxt = nuxt
|
2017-08-19 09:50:45 +00:00
|
|
|
this.renderer = renderer
|
2017-08-18 16:05:01 +00:00
|
|
|
this.options = nuxt.options
|
2017-08-21 09:38:21 +00:00
|
|
|
this.vueRenderer = VueServerRenderer.createRenderer()
|
2017-08-18 16:05:01 +00:00
|
|
|
this.cache = LRU({})
|
|
|
|
|
2017-08-21 09:38:21 +00:00
|
|
|
// Add VueMeta to Vue (this is only for SPA mode)
|
|
|
|
// See lib/app/index.js
|
|
|
|
Vue.use(VueMeta, {
|
|
|
|
keyName: 'head',
|
|
|
|
attribute: 'data-n-head',
|
|
|
|
ssrAttribute: 'data-n-head-ssr',
|
|
|
|
tagIDKeyName: 'hid'
|
|
|
|
})
|
|
|
|
}
|
2017-08-18 16:05:01 +00:00
|
|
|
|
2017-11-24 04:11:52 +00:00
|
|
|
async getMeta(url) {
|
|
|
|
const vm = new Vue({
|
|
|
|
render: h => h(), // Render empty html tag
|
|
|
|
head: this.options.head || {}
|
2017-08-21 09:38:21 +00:00
|
|
|
})
|
2017-11-24 04:11:52 +00:00
|
|
|
await this.vueRenderer.renderToString(vm)
|
|
|
|
return vm.$meta().inject()
|
2017-08-21 09:38:21 +00:00
|
|
|
}
|
2017-08-18 16:05:01 +00:00
|
|
|
|
2017-10-30 16:51:11 +00:00
|
|
|
async render({ url = '/' }) {
|
2017-08-21 09:38:21 +00:00
|
|
|
let meta = this.cache.get(url)
|
2017-08-18 16:05:01 +00:00
|
|
|
|
2017-08-21 09:38:21 +00:00
|
|
|
if (meta) {
|
|
|
|
return meta
|
2017-08-18 16:05:01 +00:00
|
|
|
}
|
|
|
|
|
2017-08-21 09:38:21 +00:00
|
|
|
meta = {
|
|
|
|
HTML_ATTRS: '',
|
|
|
|
BODY_ATTRS: '',
|
2017-11-06 12:33:19 +00:00
|
|
|
HEAD: '',
|
|
|
|
BODY_SCRIPTS: ''
|
2017-08-21 09:38:21 +00:00
|
|
|
}
|
|
|
|
// Get vue-meta context
|
|
|
|
const m = await this.getMeta(url)
|
|
|
|
// HTML_ATTRS
|
2017-09-05 09:04:59 +00:00
|
|
|
meta.HTML_ATTRS = m.htmlAttrs.text()
|
2017-08-21 09:38:21 +00:00
|
|
|
// BODY_ATTRS
|
|
|
|
meta.BODY_ATTRS = m.bodyAttrs.text()
|
|
|
|
// HEAD tags
|
2018-01-13 05:22:11 +00:00
|
|
|
meta.HEAD =
|
|
|
|
m.meta.text() +
|
|
|
|
m.title.text() +
|
|
|
|
m.link.text() +
|
|
|
|
m.style.text() +
|
|
|
|
m.script.text() +
|
|
|
|
m.noscript.text()
|
2017-11-06 12:33:19 +00:00
|
|
|
// BODY_SCRIPTS
|
2018-01-23 10:42:25 +00:00
|
|
|
meta.BODY_SCRIPTS = m.script.text({ body: true }) + m.noscript.text({ body: true })
|
2017-08-30 12:47:07 +00:00
|
|
|
// Resources Hints
|
|
|
|
meta.resourceHints = ''
|
2017-08-19 09:50:45 +00:00
|
|
|
// Resource Hints
|
|
|
|
const clientManifest = this.renderer.resources.clientManifest
|
|
|
|
if (this.options.render.resourceHints && clientManifest) {
|
|
|
|
const publicPath = clientManifest.publicPath || '/_nuxt/'
|
|
|
|
// Pre-Load initial resources
|
|
|
|
if (Array.isArray(clientManifest.initial)) {
|
2018-01-13 05:22:11 +00:00
|
|
|
meta.resourceHints += clientManifest.initial
|
|
|
|
.map(
|
|
|
|
r => `<link rel="preload" href="${publicPath}${r}" as="script" />`
|
|
|
|
)
|
|
|
|
.join('')
|
2017-08-19 09:50:45 +00:00
|
|
|
}
|
|
|
|
// Pre-Fetch async resources
|
|
|
|
if (Array.isArray(clientManifest.async)) {
|
2018-01-13 05:22:11 +00:00
|
|
|
meta.resourceHints += clientManifest.async
|
|
|
|
.map(r => `<link rel="prefetch" href="${publicPath}${r}" />`)
|
|
|
|
.join('')
|
2017-08-30 12:47:07 +00:00
|
|
|
}
|
|
|
|
// Add them to HEAD
|
|
|
|
if (meta.resourceHints) {
|
|
|
|
meta.HEAD += meta.resourceHints
|
2017-08-19 09:50:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-04 22:33:46 +00:00
|
|
|
// Emulate getPreloadFiles from vue-server-renderer (works for JS chunks only)
|
2018-01-13 05:22:11 +00:00
|
|
|
meta.getPreloadFiles = () =>
|
|
|
|
clientManifest.initial.map(r => ({
|
|
|
|
file: r,
|
|
|
|
fileWithoutQuery: r,
|
|
|
|
asType: 'script',
|
|
|
|
extension: 'js'
|
|
|
|
}))
|
2018-01-04 22:33:46 +00:00
|
|
|
|
2017-08-21 09:38:21 +00:00
|
|
|
// Set meta tags inside cache
|
|
|
|
this.cache.set(url, meta)
|
2017-08-18 16:05:01 +00:00
|
|
|
|
2017-08-21 09:38:21 +00:00
|
|
|
return meta
|
2017-08-18 16:05:01 +00:00
|
|
|
}
|
|
|
|
}
|