美文网首页前端开发那些事儿
SSR介绍-2: 传统SSR实现

SSR介绍-2: 传统SSR实现

作者: miao8862 | 来源:发表于2021-04-10 02:18 被阅读0次

    此篇文章将结合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的一大特点,本来想自己写激活的博客的,突然发现别的大佬讲得更清楚,我就不献丑了,直接上链接:

    https://segmentfault.com/a/1190000019618170
    https://segmentfault.com/a/1190000019462324?utm_source=sf-similar-article

    相关文章

      网友评论

        本文标题:SSR介绍-2: 传统SSR实现

        本文链接:https://www.haomeiwen.com/subject/sqsgkltx.html