📜  SSR 渲染 (1)

📅  最后修改于: 2023-12-03 14:47:42.262000             🧑  作者: Mango

SSR 渲染

SSR 渲染是指服务器在渲染页面时,会把 JavaScript 代码在服务器端执行,并将执行后的 HTML 文档传回客户端。这种方式可以提升网站的性能,减少客户端渲染的压力,同时还可以提高 SEO 的效果。

为什么需要 SSR 渲染?

随着 Web 应用的发展,JavaScript 动态交互的方式越来越多。而客户端渲染(CSR)模式是指前端使用浏览器渲染 JavaScript 生成 HTML 和 CSS 等文档,这是一种以 JavaScript 为核心的、专注于用户体验的渲染方式。但这种渲染方式也受到一些限制,如 SEO、首屏渲染速度等。

SEO 的问题是因为某些搜索引擎在爬取站点时会直接忽略 JavaScript 脚本。如果网站页面全部由 JavaScript 接管的话,这些搜索引擎就无法正常爬取网站的内容,而网站将失去 SEO 的效果。

另外,如果网站首页耗时过长,那么用户将会面临较长的等待时间,这同样会给用户体验带来负面影响。

SSR 的原理

SSR(Server-Side Rendering)在渲染页面时会先在服务器端将 JavaScript 代码执行,再将得到的 HTML 文档传回客户端。这就相当于在客户端渲染之前,就已经得到所有需要展示的 HTML 文档,而不再需要等待 JavaScript 加载和执行,因此可以提高首屏渲染速度,使得用户可以更快的看到网站的展示内容。

同时,由于浏览器已经得到了所有需要展示的内容,因此搜索引擎也可以正常地爬取网站的内容,提高了网站的 SEO 效果。

SSR 的实现方式

SSR 的实现方式有很多种,我们这里以 Vue.js 为例,简单介绍其实现方式:

1. 服务端使用 Node.js 进行 SSR

在 Node.js 中,我们可以使用 createRenderer 函数创建一个 renderer 对象,这个对象包含了一个 render 方法,该方法可以将一个 Vue 实例渲染为 HTML 字符串。服务端可以调用 Vue 实例的 renderToString 方法来得到 HTML 字符串,再将该字符串传回客户端即可。

import Vue from 'vue'
import { createRenderer } from 'vue-server-renderer'

const app = new Vue({
  template: '<div>Hello World</div>'
})

const renderer = createRenderer()

renderer.renderToString(app, (err, html) => {
  if (err) throw err
  console.log(html) // <div data-server-rendered="true">Hello World</div>
})
2. 客户端和服务端共用一个入口文件

另外一种更优雅的方式是,客户端和服务端共用一个入口文件。在这种方式中,我们需要通过 webpack 对代码进行打包,同时生成两个 bundle 文件,一个是服务端的 bundle 文件,一个是客户端的 bundle 文件,服务端的 bundle 文件用于在 Node.js 中进行 SSR,客户端的 bundle 文件则用于在浏览器中进行 CSR。

// webpack.config.js

const webpack = require('webpack')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')

const isServer = process.env.WEBPACK_TARGET === 'node'
const target = isServer ? 'server' : 'client'

const plugins = [
  // DefinePlugin 用于定义环境变量
  new webpack.DefinePlugin({
    'process.env': {
      VUE_ENV: target === 'server' ? '"server"' : '"client"'
    }
  })
]

if (isServer) {
  plugins.push(new VueSSRServerPlugin())
} else {
  plugins.push(new VueSSRClientPlugin())
}

module.exports = {
  target,
  plugins
}

使用 webpack 打包后,我们可以得到两个 bundle 文件,一个是 server-bundle.js,一个是 client-bundle.js,我们需要在服务端创建一个 HTTP 服务器,提供一个路由,当浏览器访问 / 路由时,服务端应该返回渲染好的 HTML 内容,当浏览器请求 js、css 等静态资源时,服务端应该返回对应的资源路径。

客户端的渲染可以在 window.onload 事件中进行,当文档准备好后再进行渲染:

// client.js

import Vue from 'vue'
import App from './App.vue'

const app = new Vue({
  el: '#app',
  render: h => h(App)
})

window.onload = () => {
  app.$mount('#app')
}
SSR 的缺点

尽管 SSR 有很多优点,但它也存在一些缺点:

  1. 首次加载时,服务器需要花费更多的时间来处理渲染请求,这可能导致一些性能瓶颈。

  2. SSR 通常使用 Node.js 来渲染页面,这意味着需要采用其他工具来支持 TypeScript 或其他强类型语言。

  3. 兼容性问题,不支持服务端渲染或在低版本浏览器中使用的组件可能会导致一些兼容性问题。

总结

SSR 渲染可以提高网站的性能,同时提高 SEO 的效果,但也存在一些缺点。对于 Web 应用来说,如何选择渲染方式仍需根据实际场景具体分析。