赞
踩
任何一个技术的出现都不是凭空产生的,一定是为了解决原有技术上的痛点。
SSR:Server Side Rendering,服务端渲染。指的是服务器端生成完整的 HTML 页面后,发送给客户端直接渲染呈现。早期的页面都是通过服务器端渲染来完成的。
服务端渲染的缺点:有可能某次请求只是一些数据发生了变化,但服务器却需要重绘整个 HTML 页面,返回给浏览器重新渲染,不仅浪费了带宽,也增加了浏览器的性能消耗。
CSR:Client Side Rendering,客户端渲染。指的是客户端解析服务器端发送过来的文件后先生成完整的 HTML 页面,再渲染呈现。这种模式就是前后端分离。
SPA 页面通常依赖的就是客户端渲染。
一个 Web 应用包含很多 HTML 页面。每一次页面跳转的时候,服务器都会给返回一个新的 HTML 文档。
整个应用只有一个完整的页面,点击页面中的链接不会刷新页面,只会做页面的局部更新。第一次进入页面的时候会请求一个 HTML 文件,跳转到其他路径,并不会请求新的 HTML 文件,但是页面内容也变化了。
JS 会感知到 URL 的变化,通过这一点,可以用 JS 动态的将当前页面的内容清除掉,然后将下一个页面的内容挂载到当前页面上。
index.html
文件。index.html
中通过 script 引入的 JS 文件,浏览器下载完成后,解析执行,生成完整的 HTML 页面后渲染显示。不利于 SEO 搜索引擎优化。
- 百度的服务器集群 24 小时不间断地在网络上爬取数据,爬取单页应用的时候其实主要就是把网站的
index.html
下载下来,但是单页应用的index.html
中的 body 内其实只有一个 div 而已(使用 Webpack 打包构建),虽然 meta 等配置信息也是可以被爬取到的,但是页面的具体内容是爬取不到的。因此在百度的数据库中收录的网站的关键字很少,当用户在浏览器中通过百度的搜索引擎来搜索关键字的时候,由于匹配到的关键字很少,匹配度很低,因此排名会很靠后。- 对比早期的 SSR 的页面,服务器会直接生成完整的 HTML 页面后再返回给客户端,爬虫从网页中就能爬取到更多有效的数据。
谷歌在爬取数据方面做得要比百度好,也会执行 JS 文件,爬取单页应用时爬取到的关键字也会更多一些。
首屏渲染速度慢:
- 单页应用首次请求到的只是一个
index.html
页面,然后才会去请求index.html
中通过 script 引入的 JS 文件,浏览器下载完成后,还需要解析执行,生成完整的 HTML 页面后才会渲染显示。- 对比早期的 SSR 的页面,服务器会直接生成完整的 HTML 页面后再返回给客户端,客户端下载到的直接就是完整的网站,直接渲染出来显示就可以了。
不过,现代浏览器执行 JS 的速度已经很快了,差异也不是特别巨大。
路由:一个路由就是一个映射关系(key-value:key 就是路径,value 就是 Function 或者 Component)。
早期的网站开发整个 HTML 页面都是由服务器来渲染的。每个页面都有自己对应的 URL,客户端发送 URL 给服务器,服务器通过对该 URL 进行匹配后生成对应的 HTML 页面,返回给客户端进行展示。
客户端请求不同的 URL,服务器渲染好对应的整个页面后将页面返回给客户端,这就是后端路由。本质上 URL 请求地址与服务器资源之间的对应关系。在后端路由中一个路径对应一个 Function,用来处理客户端提交的请求。
后端路由会刷新整个页面。
以下为 Node 的后端路由:当 Node 接收到一个请求时,根据请求路径找到匹配的路由,调用路由中的函数来处理请求,返回响应函数。
前端路由的核心是 URL 发生变化,但是并不会向服务器发送新的请求,页面不会进行整体的刷新。本质上就是检测 URL 的变化,然后解析来匹配路由规则,通过 JS 来实现页面内容的更换。在前端路由中一个路径对应一个 Component,用于展示页面内容。
前端路由不会刷新整个页面。
主流的实现方式是通过 hash 模式和 history 模式。
hash 模式利用的是浏览器不会对 # 号后面的路径对服务端发起路由请求。
可以通过 hashchange 事件监听 URL 的变化。
hash 是 URL 中 # 及后面的部分,常用作锚点在页面内进行导航。
<body> <ul> <!-- 定义路由 --> <li><a href="#/home">home</a></li> <li><a href="#/about">about</a></li> <!-- 渲染路由对应的 UI --> <div id="routeView"></div> </ul> </body> // 页面加载完不会触发 hashchange,这里主动触发一次 hashchange 事件 window.addEventListener('DOMContentLoaded', onLoad) // 监听路由变化 window.addEventListener('hashchange', onHashChange) // 路由视图 var routerView = null function onLoad () { routerView = document.querySelector('#routeView') onHashChange() } // 路由变化时,根据路由渲染对应 UI function onHashChange () { switch (location.hash) { case '#/home': routerView.innerHTML = 'Home' return case '#/about': routerView.innerHTML = 'About' return default: return } }
history 模式利用的是 HTML5 新增的 history API。history API 用来操作浏览器的路由地址。浏览器会提供一个 history 对象,用来保存用户操作过的历史 URL,因此使用前进后退按钮时,URL 地址会发生变化,但不会向服务器发送请求,不会触发页面的整体刷新,因此可以使用 pushState 和 replaceState 这两个 API 来将 URL 添加到 history 历史记录中就可以实现不发送请求的路由跳转。
可以通过 popstate 事件来监听 URL 的变化,通过 pushState 和 replaceState 这两个方法改变 URL 的 path 部分而不引起页面的整体刷新。
<body> <ul> <!-- 定义路由 --> <li><a href="#/home">home</a></li> <li><a href="#/about">about</a></li> <!-- 渲染路由对应的 UI --> <div id="routeView"></div> </ul> </body> // 页面加载完不会触发 popstate,这里主动触发一次 popstate 事件 window.addEventListener('DOMContentLoaded', onLoad) // 监听路由变化 window.addEventListener('popstate', onPopState) // 路由视图 var routerView = null function onLoad () { routerView = document.querySelector('#routeView') onPopState() // 拦截 <a> 标签点击事件默认行为, 点击时使用 pushState 修改 URL并更新手动 UI,从而实现点击链接更新 URL 和 UI 的效果。 var linkList = document.querySelectorAll('a[href]') linkList.forEach(el => el.addEventListener('click', function (e) { e.preventDefault() history.pushState(null, '', el.getAttribute('href')) onPopState() })) } // 路由变化时,根据路由渲染对应 UI function onPopState () { switch (location.pathname) { case '/home': routerView.innerHTML = 'Home' return case '/about': routerView.innerHTML = 'About' return default: return } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。