初步认识前端SSR(服务端渲染)

背景知识

  • 最初的php,jsp等技术是曾经主流的前后端不分离的解决方案。当服务器接收到一个请求后,根据一定的逻辑,获取数据库的数据,然后把运算好的数据传递到html模板文件,生成完整的html代码,返回到客户端展示。

  • 前端框架(Vue,React等)是前后端分离思想的优秀产物。它们常见都是生成SPA应用。而SPA的优点是用户体验好,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染。

  • 前端SSR方案结合了MPA和SPA的思想,针对spa首屏加载较慢和不利于seo的缺点,采用了服务端客户端同构的方案。

关键知识点

  • 服务端客户端同构
  • 服务端渲染(SSR)
  • 静态生成(SSG)

渲染方式与spa的差异

js 复制代码
// react JSX渲染
function Hello() {
  return <div>Hello world</div>
}

export default Hello

spa页面例子(蓝湖):

ssr例子(百度):

  • spa应用的特点是依赖 JS 运算生成对应的 DOM 节点, html 文件里本来是不存在具体的DOM节点。而 SSR 是可以在服务器渲染好完整的DOM结构再返回给客户端。

生命周期与spa的差异

  • 服务端渲染时候执行的生命周期顺序和客户端渲染是一致的,但是需要注意是在服务端执行的生命周期钩子内,是无法执行浏览器特有的api

特有的渲染方法(以next.js框架为例)

静态生成(SSG)

出于性能原因,Next官方更推崇使用静态生成。 如果页面没有数据请求,Next会采用静态生成的方式,在构建的时候就生成好对应HTML;

如果页面内容依赖外部数据,可以在页面组件中export一个名叫getStaticProps的方法,这个函数会在构建时被调用,然后将获取的数据传递到页面的props中,进行预渲染;

js 复制代码
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

// This function gets called at build time
export async function getStaticProps() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

export default Blog

服务端渲染(SSR)

通常面对更新比较快,或者跟用户信息相关的页面,我们都不能使用静态生成的方式来提前生成页面,此时就需要使用服务端渲染,每次请求都重新生成页面HTML;要对页面使用服务器端渲染,需要名为getServerSideProps的方法, 服务器将在每次请求时都会调用此函数

javascript 复制代码
function Page({ data }) {
  // Render data...
}

// This gets called on every request
export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

export default Page

getServerSideProps跟之前静态生成用到的getStaticProps方法非常相似,不同之处在于getServerSideProps在每个请求都会运行,而getStaticProps是在构建时运行。

增量生成(ISR)

SSG这种静态页面虽然好,但缺点也十分突出,如果只能在构建时生成页面,那就意味着,每次在管理后台里改动了业务数据,都需要重新构建以刷新页面。如果没有办法解决这个缺点,SSG虽好,但可使用的业务场景也非常少,所幸,next提供了在构建站点后创建或更新静态页面的能力,这就是ISR。

服务端客户端同构的工作方式

如上介绍,服务端会预先生成需要展示的html结构,那是不是就意味着每次在浏览器输入不同的url,都会访问一次服务器获取新的html内容呢?

如果是这样,就牺牲了spa的特性。所以当访问一个新的url,需要先区分是否由客户端路由跳转产生的访问,如果是则执行spa路由跳转的逻辑,否则就执行产生一条服务端请求最新的html文件内容。这就意味着同一份代码既有可能在服务端执行,也有可能在客户端执行。

SSR优点

  • 利于seo优化,方便搜索引擎抓取数据。
  • 服务端和客户端分工明确,仍保留客户端路由管理,全局数据状态管理等功能。
  • 大幅提高页面访问性能。

在这里,我主要想展开说说为什么可以明显地提升性能。

  1. 把依赖接口的数据提前在服务端获取,节省了等待接口响应的时间。
  2. 获取到了接口数据,根据特定逻辑渲染成真正的DOM结构。这个步骤也放到了服务端执行,节省客户端渲染时间。(客户端机型性能差的时候尤其明显)
  3. 浏览器加载资源,无需等待任何JS文件的加载,就可以渲染出初始页面,LCP和FCP性能指标很好。(客户端网络差的时候尤其明显)

疑问点

  • Q. 现在的前端SSR和以前的PHP等前后端不分离技术方案有何区别?

A. 前后端是否真正解耦,前端是否具备工程化能力(路由管理,全局数据状态管理,前端生态工具链)

  • Q. 使用了nuxt.js或者next.js搭建的项目后,引入一些第三方的库或组件,会报错

A. 一些三方库使用了window,localStorage等客户端特有的对象,如果该逻辑是在服务端运行的,那么这些对象肯定是为空值,所以就报错了。解决方案也不复杂,使用条件控制渲染组件,在特定的生命周期再允许渲染该组件。

总结

从以前的前后端不分离的后端语言渲染html,到spa应用,再到目前的前端SSR解决方案,历史是在螺旋上升的。前端技术方案也越来越成熟,处理大型项目的能力也越来越强大。

相关推荐
Jiaberrr4 分钟前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy28 分钟前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白28 分钟前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、29 分钟前
Web Worker 简单使用
前端
web_learning_32132 分钟前
信息收集常用指令
前端·搜索引擎
tabzzz39 分钟前
Webpack 概念速通:从入门到掌握构建工具的精髓
前端·webpack
200不是二百1 小时前
Vuex详解
前端·javascript·vue.js
滔滔不绝tao1 小时前
自动化测试常用函数
前端·css·html5
码爸1 小时前
flink doris批量sink
java·前端·flink
深情废杨杨1 小时前
前端vue-父传子
前端·javascript·vue.js