背景
在早期的 Web 应用中,前端的作用很弱,业务逻辑和数据处理都在后端,后端给前端返回一个 HTML 页面,前端只负责展示。在这种模式下,单个 HTML 页面被当做一个功能原件,表单提交,超链接跳转都可以用来重新请求新的 HTML 页面,从而达到给用户展示新的页面的目的。在这种方式中,你可以感觉到页面总是在不停的刷新,一个点击可能都需要等待很久,这是因为,当页面变化时,所有资源都需要重新请求。这些问题导致了用户体验不佳,也浪费了资源。单页应用便很好的解决了这些问题。
基本概念
单页应用的全称是single-page application,简称 SPA,它是一种网站应用的模型,它可以动态重写当前的页面来与用户交互,而不需要重新加载整个页面。常用于PC端官网、购物等网站.
简单来说——SPA是只有一张Web页面的应用,一种从Web服务器加载的富客户端,单页面跳转仅刷新局部资源 ,公共资源(js、css等)仅需加载一次。
基本元素:页面路由
工作原理
SPA 的一个重要实现就是改变路由时,页面不刷新。实现这个功能,通常有两种方式:使用window.history对象或 location.hash。
优点
流畅性更好
1
单页应用的流畅性让 Web 应用更像桌面端或 Native 应用了。
前后端分离
1
2
3相对于传统的 Web 应用,单页应用做到了前后端分离.
后端只负责处理数据提供接口,页面逻辑和页面渲染都交给了前端。
各司其职,不会把前后端的逻辑混杂在一起;应用广泛
1
目前时兴的 React、Vue、Angular 等前端框架均采用了 SPA 原则。
前端掌握了主动权
1
让前端代码更复杂和庞大,模块化、组件化以及架构设计都变得越来越重要。
无刷新体验
1
2用户在切换页面过程中不会频繁被“打断”.
因为界面框架都在本地,对用户的响应非常及时,因此提升了用户体验;减轻服务器压力
1
服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍;
API 共享
1
同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端;
完全的前端组件化
1
2前端开发不再以页面为单位,更多地采用组件化的思想.
代码结构和组织方式更加规范化,便于修改和调整。
缺点
对SEO不太友好,尽管可以通过Prerender预渲染优化等技术解决一部分,但是相对还是不容易索引到它;
(注:SEO本质是一个服务器向另一个服务器发起请求,解析请求内容;Prerender可以对这些使用了前端渲染的 JavaScript 框架做的网站进行良好的 SEO 优化, 可以对 JavaScript 页面进行静态化。)
解决方案:
1
2
3服务端渲染:服务器合成完整的 html 文件再输出到浏览器;
页面预渲染;
路由采用h5 history模式;易出错,需要使用程序管理前进、后退、地址栏等信息;
较高的前端开发门槛,对技术能力要求较高,需要对设计模式有一定理解,因为面对不是一个简单的页面,而是一个运行在浏览器环境里面的桌面软件。
首屏加载慢:如果不对路由进行处理,在加载首页的时候,就会将所有组件全部加载,并向服务器请求数据,这必将拖慢加载速度;通过查看Network,发现整个网站加载试讲长达10几秒,加载时间最长的就是js、css文件和媒体文件及图片
解决方案:1
2
3
4
5Vue-router懒加载:Vue-router懒加载就是按需加载组件,只有当路由被访问时才会加载对应的组件,而不是在加载首页的时候就 加载,项目越大,对首屏加载的速度提升得越明显。
使用CDN加速:在做项目时,我们会用到很多库,采用CDN加载可以加快加载速度。
异步加载组件:这里可以参考别人的介绍(https://segmentfault.com/a/1190000012138052)
服务端渲染:服务端渲染还能对seo优化起到作用,有利于搜索引擎抓取更多有用的信息(如果页面纯前端渲染,搜索引擎抓取到的就只是空页面)
不适合开发大型项目:大型项目中可能会涉及大量的DOM操作、复杂的动画效果,也就不适合使用Vue、react框架进行开发。
单页面与多页面对比
- 结构示意图

- 具体对比分析
实现流程
拓展
1.hash模式和history模式
Hash: 这里的hash是指url尾巴后的#号及后面的字符。
这里的#和css里的#是一个意思。hash也称作锚点,本身是用来做页面定位的,它可以使对应id的元素显示在可是区域内。
由于hash值变化不会导致浏览器向服务器发出请求,而且hash改变会触发hashchange事件,浏览器的进后退也能对其进行控制,所以人们在 html5 的 history 出现前,基本都是使用 hash 来实现前端路由的。
History: HTML5规范提供了history.pushState和history.replaceState来进行路由控制。通过这两个方法可以改变url且不向服务器发送请求。同时不会像hash有一个#,更加的美观。但是history路由需要服务器的支持,并且需将所有的路由重定向倒根页面。
2.history与hash比较
Hash 能兼容到IE8, history 只能兼容到 IE10;
首先,Hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。
其次,Hash 的传参是基于 url 的,如果要传递复杂的数据,会有体积的限制,而 history 模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。
vue-router默认Hash模式,使用 URL 的 Hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。不过这种模式要玩好,还需要后台配置支持。
因为我们的应用是个单页客户端应用,如果后台没有正确的配置。当用户在浏览器直接访问http://oursite.com/user/id 就会返回 404,这就不好看了。所以,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个index.html 页面,这个页面就是你 app 依赖的页面。