今天看啥  ›  专栏  ›  miao8862

传统SSR实现

miao8862  · 简书  ·  · 2021-04-10 02:18

此篇文章将结合vue来简单介绍如何实现传统的SSR,为后续实现现今流行的SSR打个基础。
参考vue ssr官网: https://ssr.vuejs.org/zh/guide/#%E5%AE%89%E8%A3%85

新建工程

创建项目(vue-cli): vue create ssr
安装依赖: npm install vue-server-renderer express -D
安装时,注意保证依赖vue, vue-server-renderer,vue-template-compiler版本一致,不然可能会报错(这里我的版本是2.6.12)

创建服务器

这里使用express作为服务器,使用vue-server-renderer实现将vue实例渲染成html字符串功能

// 导入express服务器,将vue ssr集成进来
const express = require('express')

// 1. 创建express实例,用于启动web服务器
const server = express()

// 导入vue,用于声明待渲染的vue实例
const Vue = require("vue")
// 2. 获取渲染器实例
const { createRenderer } = require('vue-server-renderer')
const renderer = createRenderer()

// 创建后端路由
server.get('*', (req, res) => {

  // 1. 创建vue实例
  const app = new Vue({
    // 注意模板最外层只能有一个元素,不然会报错
    template: `<div>
        <h1>hello ssr</h1>
        <div @click="onClick">{{msg}}</div>
      </div>
    `,
    data() {
      return {
        msg: 'vue ssr'
      }
    },
    methods: {
      logMsg() {
        console.log(this.msg);
      }
    }
  })
  // 2. 用渲染器渲染vue实例,将vue实例渲染成html字符串
  renderer.renderToString(app).then(html => {
    console.log(html);
    res.send(html)
  }).catch(err => {
    res.status(500)
    res.send('Internet Server Error')
  })

})

server.listen(3000, () => {
  console.log('server is running!');
})

根据不同的路由,动态渲染不同的模板页面

上面的例子,是将模板给写死的,但在实际过程中,我们一般是将模板(html页面)给抽离出来,根据不同的路由,加载对应的模板文件,下面来改进一下

  1. 创建模板文件,用于测试不同路由渲染模板的功能
<!-- server/home.html -->
<body>
  <div>
    <h1>首页</h1>
    <div @click="onClick">{{msg}}</div>
  </div>
</body>

<!-- server/detail.html -->
<body>
  <div>这是详情页</div>
</body>
  1. 修改服务器文件,改为根据路由名称来加载不同的模板文件
// server/index.js

// 1. 引入fs(进行IO操作)和path(用于读取和拼接路径)库
const fs = require('fs')
const path = require('path')

server.get('*', (req, res) => {

  console.log(req.url);

  // 2. 这里简单的截取/后的路由(暂时不考虑多级路由的情况)
  const templateName = req.url.substring(1) || 'index' 
  // 3. 根据路由名称,读取对应的html页面
  const template = fs.readFileSync(path.join(__dirname, `${templateName}.html`), 'utf-8')

  const app = new Vue({
    // 4. 将模板文件由写死的改为动态读取的html页面
    template: template,
    data() {
      return {
        msg: `这是访问'${req.url}'后的页面,渲染的是${templateName}.html文件`
      }
    },
    methods: {
      logMsg() {
        console.log(this.msg);
      }
    }
  })

  renderer.renderToString(app).then(html => {
    res.send(html)
  }).catch(err => {
    res.status(500)
    res.send('Internet Server Error')
  })
})

启动服务

可以安装nodemon,用于热启动(即修改服务后不需要手动重新启服务)服务: npm i nodemon -g
启动服务: nodemon ./server/index.js

在浏览器中访问'/'和'detail'的效果如下:


访问/.png

访问/detail.png

可以看到启动效果,此时已经返回一个完整html结构,怎么确认它是服务端渲染的页面呢?它会有个标识 data-server-rendered="true" ,这就代表着是服务端渲染的。

image.png

可以看到,即使我们在创建vue实例时,写了click点击事件,但在经过ssr后,它会变成一个静态文件,你点击msg时,并不会有日志输出,这是因为经过ssr后,后端返回的是一个静态页面,是不能进行任何交互的。

那么,怎么实现在前端激活这些交互呢?这就是我们现在流行的ssr区别于传统ssr的一大特点,我会在下一篇文章中具体介绍。




原文地址:访问原文地址
快照地址: 访问文章快照