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) { return renderContext.renderScripts() } getPreloadFiles(renderContext) { return renderContext.getPreloadFiles() } renderResourceHints(renderContext) { return renderContext.renderResourceHints() } createRenderer() { // Create bundle renderer for SSR return createBundleRenderer( this.serverContext.resources.serverManifest, this.rendererOptions ) } async devRenderToString(renderContext) { const logs = [] const devReporter = { log(logObj) { logs.push({ ...logObj, args: logObj.args.map(format) }) } } consola.addReporter(devReporter) const APP = await this.vueRenderer.renderToString(renderContext) consola.removeReporter(devReporter) renderContext.nuxt.logs = logs return APP } async render(renderContext) { // Call ssr:context hook to extend context from modules await this.serverContext.nuxt.callHook('vue-renderer:ssr:prepareContext', renderContext) // Call Vue renderer renderToString let APP = await (this.options.dev ? this.devRenderToString(renderContext) : this.vueRenderer.renderToString(renderContext)) // Call ssr:context hook await this.serverContext.nuxt.callHook('vue-renderer:ssr:context', renderContext) // TODO: Remove in next major release await this.serverContext.nuxt.callHook('render:routeContext', renderContext.nuxt) // Fallback to empty response if (!renderContext.nuxt.serverRendered) { APP = `
` } // Inject head meta const m = renderContext.meta.inject() let HEAD = m.title.text() + m.meta.text() + m.link.text() + m.style.text() + m.script.text() + m.noscript.text() // Add