Server-side rendering supports this.
Basic Concepts of Server-Side Rendering
Server-Side Rendering (SSR) refers to rendering Vue components into HTML strings on the server side and sending them directly to the browser. This approach differs from traditional Client-Side Rendering (CSR), where the DOM is dynamically generated in the browser via JavaScript.
// Client-Side Rendering Example
new Vue({
el: '#app',
render: h => h(App)
})
The main advantages of SSR include:
- Better SEO: Search engines can directly crawl the rendered HTML content
- Faster initial page load: The browser doesn't need to wait for all JavaScript to download and execute
- Better compatibility with low-end devices: Reduces client-side computational burden
Implementation Principles of Vue SSR
Vue's SSR implementation is based on two key components: the vue-server-renderer
package and a Node.js server. The core process is as follows:
- Create a Vue instance factory function
- Use
createRenderer
to create a renderer - Render the Vue instance into HTML during server request handling
// Basic SSR Implementation Example
const Vue = require('vue')
const renderer = require('vue-server-renderer').createRenderer()
server.get('*', (req, res) => {
const app = new Vue({
data: () => ({ url: req.url }),
template: `<div>Visited URL: {{ url }}</div>`
})
renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Server Error')
return
}
res.end(`
<!DOCTYPE html>
<html>
<head><title>SSR Example</title></head>
<body>${html}</body>
</html>
`)
})
})
SSR Support in the Nuxt.js Framework
Nuxt.js is a popular framework that provides out-of-the-box SSR support for Vue applications. It simplifies SSR configuration and offers a convention-over-configuration development experience.
Typical Nuxt.js project structure:
├── pages/ // Auto-generated routes
├── components/ // Vue components
├── store/ // Vuex store
├── nuxt.config.js // Configuration file
Configuration example:
// nuxt.config.js
export default {
ssr: true, // Enable SSR
target: 'server', // Server-side rendering target
head: {
title: 'My Nuxt App',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
]
}
}
Client-Side Hydration
Client-side hydration is a key concept in SSR, referring to the process of "taking over" the server-rendered static HTML in the browser and turning it into a dynamic Vue application.
// Client entry file
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app', // Must match the mount point in the server HTML
render: h => h(App)
})
Important considerations for hydration:
- Vue versions on the client and server must match
- Initial state must be consistent
- Avoid using client-only APIs in component lifecycles
Data Prefetching Strategies
Common data fetching patterns in SSR applications:
- Component-Level Data Prefetching:
// Page component
export default {
async asyncData({ params }) {
const { data } = await axios.get(`/api/user/${params.id}`)
return { user: data }
}
}
- Vuex Store Prefetching:
// Store action
export const actions = {
async fetchUser({ commit }, userId) {
const { data } = await axios.get(`/api/user/${userId}`)
commit('SET_USER', data)
}
}
- Server-Side Data Injection:
// Server-side
const store = createStore()
await store.dispatch('fetchUser', userId)
const context = { url: req.url, state: store.state }
Performance Optimization Techniques
- Component Caching:
const LRU = require('lru-cache')
const renderer = createRenderer({
cache: LRU({
max: 10000,
maxAge: 1000 * 60 * 15 // 15-minute cache
})
})
- Code Splitting:
// Dynamic component import
const Foo = () => import('./Foo.vue')
// Route-level code splitting
const router = new VueRouter({
routes: [
{ path: '/foo', component: () => import('./Foo.vue') }
]
})
- Streaming Rendering:
// Use renderToStream instead of renderToString
const stream = renderer.renderToStream(app)
stream.pipe(res, { end: false })
stream.on('end', () => res.end('</body></html>'))
Common Issues and Solutions
Issue 1: window/document is undefined
// Solution: Use in mounted hook or check runtime environment
export default {
mounted() {
if (process.client) {
window.addEventListener('resize', this.handleResize)
}
}
}
Issue 2: Memory Leaks
// Ensure creating new Vue instance per request
export default context => {
return new Vue({
data: () => ({ count: 0 }),
template: `<div>{{ count }}</div>`
})
}
Issue 3: Async Component Loading
// Use Vue's async components with webpack magic comments
const AsyncComponent = () => ({
component: import(/* webpackChunkName: "async" */ './AsyncComponent.vue'),
loading: LoadingComponent,
error: ErrorComponent,
delay: 200,
timeout: 3000
})
Deployment and Monitoring
- PM2 Deployment Configuration:
{
"apps": [{
"name": "my-ssr-app",
"script": "server/index.js",
"instances": "max",
"exec_mode": "cluster",
"env": {
"NODE_ENV": "production"
}
}]
}
- Performance Monitoring:
// Use Performance API to monitor key metrics
const perfObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('[Perf]', entry.name, entry.duration)
}
})
perfObserver.observe({ entryTypes: ['measure'] })
- Error Tracking:
// Global error handling
Vue.config.errorHandler = (err, vm, info) => {
logErrorToService(err, {
component: vm.$options.name,
lifecycleHook: info
})
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn