This commit is contained in:
Pooya Parsa 2017-08-18 20:35:01 +04:30
parent b83f897339
commit 866e31d1a6
5 changed files with 93 additions and 17 deletions

View File

@ -151,6 +151,17 @@ export function flatRoutes (router, path = '', routes = []) {
return routes
}
export function attrsStr (attrObj = {}, exclude = []) {
return Object.keys(attrObj)
.filter(attr => !exclude.includes(attr))
.map(attr => {
if (typeof attrObj[attr] !== 'string') {
return attr
}
return `${attr}="${attrObj[attr].replace('"', '\'')}"`
}).join(' ')
}
export function cleanChildrenRoutes (routes, isChild = false) {
let start = -1
let routesIndex = []

58
lib/core/meta.js Normal file
View File

@ -0,0 +1,58 @@
import { attrsStr } from 'utils'
import LRU from 'lru-cache'
export default class MetaRenderer {
constructor (nuxt) {
this.nuxt = nuxt
this.options = nuxt.options
this.cache = LRU({})
}
render ({ url = '/' }) {
let head = this.cache.get(url)
if (head) {
return head
}
head = ''
// Title
if (typeof this.options.head.title === 'string') {
head += `<title data-n-head="true">${this.options.head.title || ''}</title>`
}
// Meta
if (Array.isArray(this.options.head.meta)) {
this.options.head.meta.forEach(meta => {
head += `<meta data-n-head="true" ${attrsStr(meta)} />`
})
}
// Links
if (Array.isArray(this.options.head.link)) {
this.options.head.link.forEach(link => {
head += `<link data-n-head="true" ${attrsStr(link)} " />`
})
}
// Style
if (Array.isArray(this.options.head.style)) {
this.options.head.link.forEach(style => {
head += `<style data-n-head="true" ${attrsStr(style, ['cssText'])} ">${style.cssText || ''}</style>`
})
}
// Script
if (Array.isArray(this.options.head.script)) {
this.options.head.script.forEach(script => {
head += `<script data-n-head="true" ${attrsStr(script, ['innerHTML'])} ">${script.innerHTML || ''}</script>`
})
}
this.cache.set(url, head)
return head
}
}

View File

@ -10,12 +10,13 @@ import _ from 'lodash'
import { join, resolve } from 'path'
import fs from 'fs-extra'
import { createBundleRenderer } from 'vue-server-renderer'
import { getContext, setAnsiColors, isUrl } from 'utils'
import { getContext, setAnsiColors, isUrl, attrsStr } from 'utils'
import Debug from 'debug'
import Youch from '@nuxtjs/youch'
import { SourceMapConsumer } from 'source-map'
import connect from 'connect'
import { Options } from 'common'
import MetaRenderer from './meta'
const debug = Debug('nuxt:render')
debug.color = 4 // Force blue color
@ -32,6 +33,7 @@ export default class Renderer extends Tapable {
// Will be set by createRenderer
this.bundleRenderer = null
this.metaRenderer = null
// Will be available on dev
this.webpackDevMiddleware = null
@ -128,7 +130,10 @@ export default class Renderer extends Tapable {
}
createRenderer () {
// Skip if SSR is disabled
// Create Meta Renderer
this.metaRenderer = new MetaRenderer(this.nuxt)
// Check if SSR is disabled
if (this.noSSR) {
return
}
@ -335,16 +340,17 @@ export default class Renderer extends Tapable {
async readSource (frame) {
const serverBundle = this.resources.serverBundle
// Initialize smc cache
if (!serverBundle.$maps) {
serverBundle.$maps = {}
}
// Remove webpack:/// & query string from the end
const sanitizeName = name => name ? name.replace('webpack:///', '').split('?')[0] : ''
// SourceMap Support for SSR Bundle
if (serverBundle && serverBundle.maps[frame.fileName]) {
// Initialize smc cache
if (!serverBundle.$maps) {
serverBundle.$maps = {}
}
// Read SourceMap object
const smc = serverBundle.$maps[frame.fileName] || new SourceMapConsumer(serverBundle.maps[frame.fileName])
serverBundle.$maps[frame.fileName] = smc
@ -423,17 +429,17 @@ export default class Renderer extends Tapable {
context.isServer = true
// Basic response if SSR is disabled or spa data provided
const SPAData = context.spa || (context.res && context.res.spa)
if (this.noSSR || SPAData) {
const data = {
HTML_ATTRS: '',
BODY_ATTRS: '',
HEAD: '',
APP: `<div id="__nuxt">${this.resources.loadingHTML}</div>`
}
const spa = context.spa || (context.res && context.res.spa)
if (this.noSSR || spa) {
const HEAD = this.metaRenderer.render(context)
const HTML_ATTRS = attrsStr(this.options.head.htmlAttrs)
const APP = `<div id="__nuxt">${this.resources.loadingHTML}</div>`
if (SPAData) {
Object.assign(data, SPAData)
const data = {
HTML_ATTRS,
BODY_ATTRS: '',
HEAD,
APP
}
const html = this.resources.spaTemplate(data)

View File

@ -92,6 +92,7 @@
"html-minifier": "^3.5.3",
"html-webpack-plugin": "^2.30.1",
"lodash": "^4.17.4",
"lru-cache": "^4.1.1",
"memory-fs": "^0.4.1",
"minimist": "^1.2.0",
"opencollective": "^1.0.3",

View File

@ -63,7 +63,7 @@
"compression": "^1.7.0",
"fs-extra": "^4.0.1",
"vue-server-renderer": "~2.4.2",
"@nuxtjs/youch": "3.0.1",
"@nuxtjs/youch": "3.0.2",
"source-map": "^0.5.6",
"connect": "^3.6.3",
"server-destroy": "^1.0.1"