最通俗易懂的VUE-SSR服务器渲染

281 阅读2分钟

前提条件

因为这个涉及到了许多知识,了解一点的话更容易理解

  • vue
  • webpack (简单了解)
  • nodejs (简单了解)

我就直接讲基本概念吧.. SSR 服务器渲染 , 意思是 由服务器来进行将Vue 组件进行渲染 ... 并且挂载至模板上(html)

首先我们来讲讲普通的vue渲染 ...
首先我们知道, 如果我们用vue-cli创建一个普通的项目 , 在mian.js 里面有这样一句话 ..

import App from './App.vue'   // 引入App.vue 这个组件 
new Vue ({      
    render : h => h(App)   // 这个Vue实例将直接渲染App组件 
}).$mount('#root');     // 将这个Vue 实例挂载到id为 root 节点上  

那么以上是我们vue-cli 创建出来的 main.js 里面的代码,那么我们这串代码呢,是从客户端运行,为什么能看出来是客户端运行的呢, 其实很简单,你使用一个console.log,那么这个console.log 会在浏览器里面运行, 那么这个就是客户端环境,所以呢,这个是Vue的客户端渲染

然后我们来直接看看服务端渲染(其实官网都有代码,官网也比我说的好很多,但是一开始会让人很蒙... 特别是webpack构建那里) SSR 官方文档

首先我们还是安装官方文档走 安装必备环境

  1. 安装SSR必备的依赖 vue 和 vue-server-renderer 因为之后就是靠这个vue-server-renderer 这个依赖去渲染
npm install vue vue-server-renderer --save
  1. 渲染一个Vue 实例渲染到html上面
// 第 1 步:创建一个 Vue 实例
const Vue = require('vue')
const app = new Vue({
  template: `<div>Hello World</div>`
})

// 第 2 步:创建一个 renderer
const renderer = require('vue-server-renderer').createRenderer()

// 第 3 步:将 Vue 实例渲染为 HTML
// 通过renderer.renderToString() 将这个app 挂载到模板上 生成的html 字符串给客户端,意思是直接给浏览器一个页面 
// vue-ssr 定义本来也就如此嘛
renderer.renderToString(app, (err, html) => {
  if (err) throw err
  console.log(html)
  // => <div data-server-rendered="true">Hello World</div>
})
  1. 与服务器集成

首先先安装express来进行nodejs服务端开发 npm install express --save


const Vue = require('vue') // 引入vue 依赖 
const server = require('express')() // 创建出一个服务器  , 这个属于 express 用法 
const renderer = require('vue-server-renderer').createRenderer() // 创建一个renderer

 // 不管任何请求都会进入这个方法 
 /*
    如果你的服务器启动的是localhost:8080 ,那么你访问 localhost:8080/index  or localhost:8080/xxx 都会进入这个方法
    req : 请求 
    res : 响应
 */
server.get('*', (req, res) => {  
    // 不管任何请求 , 都创建出一个vue 实例 , 而这个实例显示得内容为template 中的内容 
  const app = new Vue({
    data: {
      url: req.url
    },
    template: `<div>访问的 URL 是: {{ url }}</div>`
  })
    // 这个vue 实例 渲染成html文本    .... 
  renderer.renderToString(app, (err, html) => {
    if (err) {
    // 如果渲染出错了, 或者其他错误  ..  
    // 直接响应出500 错误 , 并且返回的字符串为 .... xxxx
      res.status(500).end('Internal Server Error')
      return
    }
    // 如果一切正常, 将渲染出的html文本 放入到body中  一起给浏览器  
    res.end(`
      <!DOCTYPE html>
      <html lang="en">
        <head><title>Hello</title></head>
        <body>${html}</body>
      </html>
    `)
  })
})

server.listen(8080)

  1. 使用一个页面模板
 // 创建出一个html 模板, 名叫 index.template.html  
 内容为 
 <!DOCTYPE html>
    <html lang="en">
      <head><title>Hello</title></head>
      <body>
        <!-- 这个代码不能删, 这个地方存在的意义在于,等会我们会把之前Vue实例渲染出来的html 代码放到这里 -->
        <!--vue-ssr-outlet-->
      </body>
    </html>
    //然后将 第三部的服务器 renderer 换一种获取方式 
    const renderer = createRenderer({
      template: require('fs').readFileSync('./index.template.html', 'utf-8')
    })
    
    // 并且直接生成html  ,不需要在使用第三步中的end 中的字符串手动拼接到body上面  
    renderer.renderToString(app, (err, html) => {
      console.log(html) // html 将是注入应用程序内容的完整页面
    })
const Vue = require('vue') // 引入vue 依赖 
const server = require('express')() // 创建出一个服务器  , 这个属于 express 用法 
创建并且增加一个模板 
const renderer =  require('vue-server-renderer').createRenderer({
      template: require('fs').readFileSync('./index.template.html', 'utf-8')
    })

 // 不管任何请求都会进入这个方法 
 /*
    如果你的服务器启动的是localhost:8080 ,那么你访问 localhost:8080/index  or localhost:8080/xxx 都会进入这个方法
    req : 请求 
    res : 响应
 */
server.get('*', (req, res) => {  
    // 不管任何请求 , 都创建出一个vue 实例 , 而这个实例显示得内容为template 中的内容 
  const app = new Vue({
    data: {
      url: req.url
    },
    template: `<div>访问的 URL 是: {{ url }}</div>`
  })
    // 这个vue 实例 渲染成html文本    .... 
  renderer.renderToString(app, (err, html) => {
    if (err) {
    // 如果渲染出错了, 或者其他错误  ..  
    // 直接响应出500 错误 , 并且返回的字符串为 .... xxxx
      res.status(500).end('Internal Server Error')
      return
    }
    // 如果一切正常, 将渲染出的html文本 直接给浏览器
    res.end(html)
  })
})

server.listen(8080)

好了 这就是一个有模板的 服务器渲染Demo