谈谈你对spa的理解

161 阅读3分钟

前言

当面试官问你谈谈你对spa的理解时,各位彦祖可千万别说:"面试官我认识xx会所的xx技师,待会一起去吗?"现在我们聊聊spa(single page web application)单页应用.

什么是spa

spa是指的是单页应用,认识vue的兄弟们可能对此并不陌生,没错vue就是单页应用,单页应用有以下两个特点:

  1. 整个项目只有一个页面
  2. 页面中的内容是动态的,以组件的形式展示,靠路由的映射关系匹配组件

在vue中只有一个html文件,我们写的vue后缀的文件就是一个代码片段,我们可以将代码片段在需要展示时挂载出来,根据这个特点有个很明显的优点就是组件化开发,当出现问题时重要检查对应的组件代码即可,易于代码的维护

在多页应用中,我们需要写很多的html文件,当url发生改变时,就要重新请求相应的资源;但是单页应用不需要,单页应用会在初次读取时会将所有文件加载好,当需要对应的文件时直接展示,这就是它的第二个优点:页面切换快,体验好

但是有有优点就一定有缺点,这种模式会带来两个严重的问题:

1.因为初次读取时会将所有文件加载好,所以会导致首页加载慢

2.当我们查看源代码,就会看到这样的情况,看不到js代码,没有有效的内容,这样虽然可以防止被爬虫爬到,但是不利于搜索引擎搜索到,不利于seo(搜索引擎)

image.png

ssr

ok,我们讲完了spa的优缺点,那我们该怎么解决?现在我来介绍一下mvp,SSR(server side render)服务端渲染

服务器端渲染(Server-Side Rendering,SSR)是一种将页面的 HTML 内容在服务器端生成并发送给客户端的技术。

1. 服务器端渲染的基本流程

  1. 客户端发起请求

    • 用户在浏览器中输入 URL 或点击链接,浏览器向服务器发送请求。
  2. 服务器处理请求

    • 服务器接收到请求后,根据路由和参数生成页面的 HTML 内容。
    • 服务器会执行 JavaScript 代码(如 React、Vue.js 的组件渲染逻辑),生成完整的 HTML 字符串。
  3. 返回 HTML 给客户端

    • 服务器将生成的 HTML 内容发送给客户端浏览器。
  4. 客户端渲染

    • 浏览器接收到 HTML 后,立即显示页面内容。
    • 同时,浏览器会下载并执行 JavaScript 文件,接管页面的交互逻辑(即“注水”,Hydration)。

代码实现:

const express = require('express');
const app = express();
const Vue = require('vue');
const vue3Compiler = require('@vue/compiler-ssr');//编译器
const renderer = require('@vue/server-renderer')//渲染器

const vueapp = {//模拟前端传来要展示的首页
  template: `
    <div>
      <h1 @click='add'>Hello, SSR!</h1>
      <ul>
        <li v-for="item in items" :key="item">{{ item }}</li>
      </ul>
    </div>
  `,
  data() {
    return {
      items: ['Item 1', 'Item 2', 'Item 3']
    }
  },
  methods: {
    add() {
      this.items.push(`Item ${this.items.length + 1}`);
    }
  }
}

// 读取vue文件,编译成js代码
vueapp.ssrRender = new Function('require', vue3Compiler.compile(vueapp.template).code)(require);


app.get('/', async (req, res) => {
  let vapp = Vue.createSSRApp(vueapp);
  let html = await renderer.renderToString(vapp); // 渲染成html
  const title = 'SSR Demo';
  let ret = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>${title}</title>
    </head>
    <body>
      ${html}
    </body>
    </html>`;

  res.send(ret);
})



app.listen(3000, () => {
  console.log('SSR server is running on port 3000');
});


实现原理:

  1. 创建 node 服务

  2. 读取 vue 组件

  3. 借助 vue 自带编译器函数编译 vue 组件 得到 AST

  4. 借助 vue 自带渲染器函数渲染 AST 得到 html

  5. 拼接 html 模板

  6. 发送响应

这时就会有人说:主播主播.你的操作确实很强有没有更加简单强势的操作呢?

有的,兄弟,有的,

直接使用createssrapp就行了,人家尤雨溪早就想到了,cn.vuejs.org/guide/scali…