Understanding Server‑Side Rendering (SSR) with Vue: Principles, Architecture, and Implementation
This article explains the concepts, use cases, advantages, and limitations of server‑side rendering (SSR) for Vue applications, details the Vue SSR architecture and core packages, and provides practical code examples and ready‑to‑use scaffolds for building SSR projects.
Preface
In front‑end development, when first‑screen rendering speed is critical, server‑side rendering (SSR) is often mentioned. This article uses Vue to dissect SSR implementation logic, covering its usage scenarios, core principles, and ready‑to‑use scaffolds.
Server‑Side Rendering
SSR (Server‑Side Rendering) means assembling the page’s HTML on the server, sending it to the browser, and then binding events and state on the client to produce a fully interactive application.
Applicable Scenarios
Better SEO support : Search engines crawl the HTML synchronously, so SSR helps when the page relies on asynchronous data.
Faster time‑to‑content : In slow‑network or low‑performance device contexts, SSR shows the first screen earlier than a full SPA.
Unsuitable Scenarios
Handling universal resources : Only beforeCreate and created lifecycle hooks run in SSR, requiring special handling for third‑party APIs.
Deployment and build configuration : The code must run in a Node.js server environment.
Server‑side caching preparation : High‑traffic scenarios need extra caching strategies, and SSR consumes more CPU.
Vue SSR Implementation Principles
Prerequisites
Component Rendering Based on VNode
VNode is a JavaScript object with strong compatibility, allowing rendering on both server and client. Virtual DOM diffing enables partial rendering and reduces performance loss.
vue‑server‑renderer
This package provides the core SSR capabilities for Vue.
SSR Rendering Architecture
Combining the official diagram and project structure gives a full view of SSR.
src ├── components ├── App.vue ├── app.js ---- common entry ├── entry-client.js ---- runs only in the browser └── entry-server.js ---- runs only on the server
import Vue from 'vue' import App from './App.vue' // Export a factory function that creates a new app instance export function createApp () { const app = new Vue({ render: h => h(App) }) return { app } }
import { createApp } from './app' const { app } = createApp() // #app is the root element app.$mount('#app')
import { createApp } from './app' export default context => { const { app } = createApp() return app }
Server and Client Code Writing Principles
Two principles guide code separation:
Common code: Shared between client and server, configured via webpack resolve.alias.
Non‑common code: Client entry mounts DOM and loads third‑party libraries; server entry only creates the Vue instance.
Two Build Outputs
After webpack bundling, two bundles are produced:
vue‑SSR‑server‑bundle.json { "entry": ..., "files": { // All server‑side code files // Entry file } }
vue‑SSR‑client‑manifest.json { "publicPath": ..., "all": [...], "initial": "html string", "async": [...], "modules": {...} }
vue‑server‑renderer Core
The package focuses on application initialization and output.
Application Initialization
Key steps:
Generate Vue object.
Create renderer with render and templateRenderer objects.
Create sandbox VM and load the entry file.
Handle errors with renderToString and renderToStream promises.
const renderer = require('vue-server-renderer').createRenderer() function createRenderer (ref) { // render: renders HTML components var render = createRenderFunction(modules, directives, isUnaryTag, cache) // templateRenderer: handles template rendering var templateRenderer = new TemplateRenderer({ template, inject, shouldPreload, shouldPrefetch, clientManifest, serializer }) }
function createBundleRunner (entry, files, basedir, runInNewContext) { var evaluate = compileModule(files, basedir, runInNewContext) }
function getCompiledScript (filename) { if (compiledScripts[filename]) return compiledScripts[filename] var code = files[filename] var wrapper = NativeModule.wrap(code) var script = new vm.Script(wrapper, { filename, displayErrors: true }) compiledScripts[filename] = script return script }
function evaluateModule (filename, sandbox, evaluatedFiles) { var script = getCompiledScript(filename) var compiledWrapper = runInNewContext === false ? script.runInThisContext() : script.runInNewContext(sandbox) var m = { exports: {} } var r = function (file) { return require(file) } }
Preventing Cross‑Pollution
Node.js processes run long‑lived, so shared state can leak between requests. Using rendererOptions.runInNewContext (true, false, once) isolates each render.
// rendererOptions.runInNewContext options true: create a new context for each render (isolated but slower) false: reuse the same context (faster, but must avoid state leakage) once: initial context for style collection only
Application Output
During output, SSR focuses on loading script content and template rendering. templateRenderer assembles HTML with resource hints, state, scripts, and styles.
TemplateRenderer.prototype.bindRenderFns = function (context) { var renderer = this ['ResourceHints','State','Scripts','Styles'].forEach(function (type) { context['render' + type] = renderer['render' + type].bind(renderer, context) }) }
TemplateRenderer.prototype.render = function (content, context) { if (!this.parsedTemplate) throw new Error('render cannot be called without a template.') if (typeof this.parsedTemplate === 'function') { return this.parsedTemplate(content, context) } if (this.inject) { return ( this.parsedTemplate.head(context) + (context.head || '') + this.renderResourceHints(context) + this.renderStyles(context) + this.parsedTemplate.neck(context) + content + this.renderState(context) + this.renderScripts(context) + this.parsedTemplate.tail(context) ) } else { // ... } }
Ready‑to‑Use SSR Scaffolds
Popular front‑end stacks provide out‑of‑the‑box SSR frameworks:
React: Next.js
Vue: Nuxt.js
Angular: Nest.js
Conclusion
SSR is a universal rendering technique; its adoption depends on the importance of initial load time for the application. For learning purposes, studying the source helps understand advanced architecture, while ready‑made scaffolds offer a smoother setup experience.
References
Vue SSR Official Site (https://ssr.vuejs.org/zh)
Vue Guide (https://www.w3cschool.cn/vuessr/vuessr-jep83epx.html)
Vue SSR Source Analysis (https://juejin.cn/post/6844903812700831757)
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.