同学,你真的了解spa吗

前言

此spa非彼spa,不是你所熟知的spa。你所熟知的spa作者肯定是没有你熟悉的。

我们这里指的是在前端开发中的一种模型,叫作单页应用程序,顾名思义,就是整个项目只有一个页面,而页面中的内容是动态的,以组件的形式展示,靠路由来映射组件。

spa的优点

组件化开发,易于维护 由于组件是独立的,当需要修改某个特定功能时,只需专注于对应的组件,而不必担心对整个应用程序造成影响。这大大简化了调试和维护的工作量。

一旦创建了一个组件,它就可以在应用的不同部分重复使用。例如,一个导航栏组件可以在网站的每个页面中使用,只需要编写一次代码。

页面切换快,体验好 在传统的多页应用中,每次页面跳转都会触发向服务器请求新页面的HTML文档,这通常包括重新加载CSS、JavaScript等资源文件,导致较长的等待时间。而在SPA中,初始加载时就会下载大部分必要的资源,后续的页面切换仅涉及数据的获取和局部DOM更新,无需重新加载整个页面。

前后端分离,提升开发效率 在前后端分离的架构中,前端团队专注于用户界面和用户体验的设计,而后端团队则负责业务逻辑和数据处理。这种分工允许两个团队同时工作,减少了相互等待的时间,每个团队只需关注自己的部分,降低了整体项目的复杂度,有助于提高代码质量和可维护性。

减轻服务器压力,提高性能

减少服务器请求次数:

  • MPA的问题:

    每次用户导航到新页面(如点击链接、提交表单),浏览器会向服务器发起完整的新请求,服务器需返回包含HTML、CSS、JavaScript等资源的完整页面。若用户频繁切换页面,服务器需处理大量重复请求,导致负载升高。

  • SPA的优势:

    • 应用仅首次加载时请求必要资源(HTML、CSS、JS)。
    • 后续交互通过客户端路由(如React Router、Vue Router)在内存中切换视图,无需向服务器请求新页面。
    • 数据更新通过轻量级API调用(如RESTful API或GraphQL)完成,仅传输JSON等精简数据,而非完整页面。

    结果:服务器仅需处理少量初始请求和API调用,显著降低负载。

利用浏览器缓存优化资源传输

  • MPA的局限:

    每个页面依赖独立的资源(如/page1.html/page2.js),即使部分资源(如全局CSS)未更改,浏览器也可能因URL不同而无法复用缓存,导致重复下载。

  • SPA的优化:

    • 所有资源通过单一入口(如index.html)加载,浏览器可高效缓存JS、CSS等静态资源。
    • 服务端渲染(SSR)或静态生成(SSG)技术还能缓存渲染后的HTML,进一步加速后续访问。

    结果:重复访问时,浏览器直接从本地加载资源,减少服务器带宽消耗。

spa的缺点

初次加载慢(Initial Load Time):

原因分析:

  • 资源体积庞大:SPA 需在首次加载时一次性下载核心 JavaScript、CSS、第三方库等资源(如 React、Vue、Axios),即使后续页面仅需少量功能,用户仍需等待完整依赖的加载。

  • 渲染阻塞:传统 SPA 采用单文件入口(如 index.js),浏览器需解析、编译、执行大量代码后才能显示首屏内容,延迟明显。

  • 网络依赖性强:若用户网络环境差(如移动网络或高延迟地区),大文件下载和解析时间会被放大。

影响:

  • 用户体验差:用户需长时间等待首屏渲染,可能导致流失(如电商网站跳出率升高)。
  • 性能评分低:Lighthouse 等工具会因首屏加载时间过长给出低分(如 FCP、LCP 指标)。

不利于搜索引擎优化(SEO) 下面是一份使用vue开发的网页

原因分析:

  • 内容动态渲染:SPA 的内容通常通过 JavaScript 在客户端渲染(CSR),搜索引擎爬虫(如 Googlebot)可能无法执行 JS,导致仅抓取到空 HTML 或初始占位符(如 div id="app"></div>)。

  • 元数据缺失:动态生成的标题(<title>)、描述(<meta name="description">)、OpenGraph 标签等可能未被爬虫正确识别。

  • 延迟索引:即使搜索引擎支持 JS 渲染(如 Google 的 Crawl via HTTP/2),内容仍需额外时间处理,导致 SEO 效果滞后。

影响:

  • 排名下降:内容无法被有效索引,长尾关键词流量减少。
  • 信任度降低:缺失元数据(如标题、描述)可能导致搜索结果中链接点击率(CTR)下降。

金牌优化师ssr

想解决这两个问题,首先就是要加载完整的html以便搜索SEO搜索引擎可以直接搜索到,第二就是就首页先进行加载,而不是等所有的组件都加载完成后才有首页,而我们的金牌优化师刚刚好能同时解决两个问题。

我们要知道在渲染浏览器页面之前,html要先将后端的的响应拿到才能开始给浏览器解析渲染,而我们的ssr是想跳过后端发送给前端响应,而是拿到前端的代码直接交给浏览器进行渲染,这样首页的内容不是js渲染的,而且不用等前端拿完所有的后端响应才开始解析然后给浏览器,而是执行到这个后端接口直接给浏览器html代码就可以渲染在页面上了

接下来我们看看后端接口怎么写,我们可以先下载node.js的一个框架

js 复制代码
npm i express

这里我们使用字符串来当作前端给过来的代码

js 复制代码
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);
// console.log(vueapp.ssrRender());

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 服务
    1. 读取 vue 组件
    1. 借助 vue 自带编译器函数编译 vue 组件 得到 AST
    1. 借助 vue 自带渲染器函数渲染 AST 得到 html
    1. 拼接 html 模板
    1. 发送响应
相关推荐
Anlici43 分钟前
跨域解决方案还有优劣!?
前端·面试
苹果电脑的鑫鑫1 小时前
在使用element-ui时表单的表头在切换页面时第一次进入页面容易是白色字体解决方法
javascript·vue.js·ui
庸俗今天不摸鱼1 小时前
【万字总结】构建现代Web应用的全方位性能优化体系学习指南(二)
前端·性能优化·webp
忧郁的蛋~1 小时前
JavaScript性能优化的12种方式
开发语言·javascript·性能优化
海盗强1 小时前
prototype和proto的区别
开发语言·javascript·原型模式
潜龙在渊灬1 小时前
杂谈:前端 UI 框架和 UI 组件库的区别
javascript·vue.js·react.js
追寻光1 小时前
Java 绘制图形验证码
java·前端
前端snow1 小时前
爬取数据利用node也行,你知道吗?
前端·javascript·后端
村头一颗草1 小时前
高德爬取瓦片和vue2使用
前端·javascript·vue.js
远山无期1 小时前
vue3+vite项目接入qiankun微前端关键点
前端·vue.js