前后端路由的区别

什么是路由

在区别前后端路由之前,我们先了解一下路由的概念

简单来说,路由就是 URL 到函数的映射(这个函数是广义的,可以使前端的函数,也可以是后端的函数)。对于静态资源,可以认为映射函数是对文件的读取操作。对于动态资源,则是对数据库数据的处理、读取操作。

什么是后端路由

在早期的 web 开发中,后端路由占主导地位。像我们常见的 php、jsp 页面,用户在地址栏中输入 URL 并回车访问的时候,客户端会把对应的路由和参数以 GET 方式对后端进行请求。后端再进行路由匹配的时候,不仅会根据 URL 来匹配,也会查看请求方式是否匹配,匹配成功,将返回对应的页面模板数据给客户端。如果路由无法匹配的对应的页面模板,则会返回 404 状态码。

后端路由的优缺点

在后端路由的时代,网页中的 html 一般是由后端服务器将数据进行模板渲染再返回给前端,这种渲染方式我们称为服务器渲染。
服务器渲染的优势在于对 SEO 友好,因为数据由后端渲染返回,所以安全性更高。但随着 web 应用功能越来越多,需要处理更多的业务逻辑,单纯服务器渲染的弊端也慢慢显露出来:当需要返回大量数据时,页面白屏时间较长;代码维护难度大等等,这是在这种环境的要求下,前端路由慢慢的进入了人们的视线。

什么是前端路由

前端路由又被称为客户端路由,因为路由的切换变化主要发生在浏览器端,路由的映射函数通常是对 DOM 进行显隐操作,当用户访问不同的页面路径时,展示不同的页面组件,比如前端流行框架 vue.js,当我们查看生产环境的 vue 项目时,会发现他的入口文件 index.html 与我们想象中的很不一样

COPY
1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue</title>
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="xxxx.xxx.js"></script>
</body>
</html>

有使用 vue 开发过项目的同学应该都知道,vue 的单页面挂载在 app 下,而页面的渲染其实是通过 js 文件渲染出来的,这种渲染方式即我们常说的前端渲染。

前端路由的优缺点

前端渲染把数据的渲染任务交给了浏览器,将大的任务颗粒化,这样一来缓解了服务器的压力,使得后端同学更专注于 api 的提供和数据库操作。另一方面,因为减少了与后端服务器的交互,所以在进行页面切换时,给用户的观感体验会更好。但同时,前端渲染也带来了一些弊端。
由于前后端数据分离,前端负责页面样式和数据渲染,后端只负责返回数据,导致爬虫无法爬取到有效的数据,对 SEO 不友好。

在使用前端路由时,我们需要明确的是

  • 地址栏输入 URL 并回车访问,依旧会向后端服务器发起 GET 请求。如果由页面中的点击或者通过前端框架的 api 进行路由跳转则不会向后端发起请求
  • 凡是在浏览器地址栏里对 URL 进行操作都会对后端服务器发起请求

常见的前端路由模式

  • hash 模式
  • history 模式

Hash 模式

众所周知,hash 路由最明显的特征就是路由中的“#”符号,很特别,但也很不美观。
例如:http//abc.com/#/xx,该路由中的 hash 值为“#/xx”,我们可以通过 hashchange 事件,监听 hash 值的变化。
hash 模式利用的是浏览器不会将#符号后面的路径及参数对服务器发起请求,当我们在浏览器地址栏中输入

COPY
1
2
http://localhost/
http://localhost/#/user/1

这两个路由像服务端发起请求的时候,都是请求的 htt://localhost 页面的内容。
前端的路由管理通过上面提到的 hashchange 事件对 hash 值的变化进行监听,进行渲染对应的页面,这样路由的处理、切换就只是由前端来继续逻辑判断了

history 模式

相较于 Hash 模式,history 模式的路由最明显的变化就是去掉了其中的#符号,跟我们常见的 URL 路由没什么两样了。
history 模式的路由切换主要是通过 HTML5 提供的 history api 实现的。

两个操作历史栈的 api 有 history.pushState 和 history.replaceState
history.pushState(); // 向历史记录中追加一条记录
history.replaceState(); // 替换当前页在历史记录中的信息。

除此之外,HTML5 还在 window 对象中提供了 onpopstate 事件来监听历史栈的改变,只要历史栈有信息发生改变的话,就会触发该事件。

COPY
1
2
3
window.addEventListener("popstate", function (e) {
console.log(e);
});

当我们在页面中通过 router 的 api 进行路由跳转时,调用的通常是 history.pushState()这个 api,所以又是前端进行的逻辑处理。但是如果我们在地址栏中输入地址并访问,则依旧会向后端服务器发起 GET 请求,如果后端没有对对应的路由进行配置,页面则会返回 404,这也就是生产环境页面刷新 404 的问题所在。

当然,关于 history 和 Hash 路由还有更深的内容需要探讨,等有时间另写一篇

作者: 果汁
文章链接: https://guozhigq.github.io/post/a96b66e8.html
版权声明: All posts on this blog are licensed under the CC BY-NC-SA 4.0 license unless otherwise stated. Please cite 果汁来一杯 !