import path from 'path'
import crypto from 'crypto'
import { format } from 'util'
import fs from 'fs-extra'
import consola from 'consola'
import devalue from '@nuxt/devalue'
import { createBundleRenderer } from 'vue-server-renderer'
import BaseRenderer from './base'
export default class SSRRenderer extends BaseRenderer {
get rendererOptions () {
const hasModules = fs.existsSync(path.resolve(this.options.rootDir, 'node_modules'))
return {
clientManifest: this.serverContext.resources.clientManifest,
// for globally installed nuxt command, search dependencies in global dir
basedir: hasModules ? this.options.rootDir : __dirname,
...this.options.render.bundleRenderer
}
}
renderScripts (renderContext) {
const scripts = renderContext.renderScripts()
const { build: { crossorigin } } = this.options
if (!crossorigin) {
return scripts
}
return scripts.replace(
/`
}
// Calculate CSP hashes
const cspScriptSrcHashes = []
if (csp) {
if (shouldHashCspScriptSrc) {
const hash = crypto.createHash(csp.hashAlgorithm)
hash.update(serializedSession)
cspScriptSrcHashes.push(`'${csp.hashAlgorithm}-${hash.digest('base64')}'`)
}
// Call ssr:csp hook
await this.serverContext.nuxt.callHook('vue-renderer:ssr:csp', cspScriptSrcHashes)
// Add csp meta tags
if (csp.addMeta) {
HEAD += ``
}
}
// Prepend scripts
if (shouldInjectScripts) {
APP += this.renderScripts(renderContext)
}
if (meta) {
// Append body scripts
APP += meta.meta.text({ body: true })
APP += meta.link.text({ body: true })
APP += meta.style.text({ body: true })
APP += meta.script.text({ body: true })
APP += meta.noscript.text({ body: true })
}
// Template params
const templateParams = {
HTML_ATTRS: meta ? meta.htmlAttrs.text(true /* addSrrAttribute */) : '',
HEAD_ATTRS: meta ? meta.headAttrs.text() : '',
BODY_ATTRS: meta ? meta.bodyAttrs.text() : '',
HEAD,
APP,
ENV: this.options.env
}
// Call ssr:templateParams hook
await this.serverContext.nuxt.callHook('vue-renderer:ssr:templateParams', templateParams)
// Render with SSR template
const html = this.renderTemplate(this.serverContext.resources.ssrTemplate, templateParams)
let preloadFiles
if (this.options.render.http2.push) {
preloadFiles = this.getPreloadFiles(renderContext)
}
return {
html,
cspScriptSrcHashes,
preloadFiles,
error: renderContext.nuxt.error,
redirected: renderContext.redirected
}
}
}