构建单页Web应用

单页应用是什么?

让咱们先来看几个网站:css

codinghtml

teambition前端

cloud9node

注意这几个网站的相同点,那就是在浏览器中,作了原先“应当”在客户端作的事情。它们的界面切换很是流畅,响应很迅速,跟传统的网页明显不同,它们是什么呢?这就是单页Web应用。git

所谓单页应用,指的是在一个页面上集成多种功能,甚至整个系统就只有一个页面,全部的业务功能都是它的子模块,经过特定的方式挂接到主界面上。它是AJAX技术的进一步升华,把AJAX的无刷新机制发挥到极致,所以能造就与桌面程序媲美的流畅用户体验。github

其实单页应用咱们并不陌生,不少人写过ExtJS的项目,用它实现的系统,很自然的就已是单页的了,也有人用jQuery或者其余框架实现过相似的东西。用各类JS框架,甚至不用框架,都是能够实现单页应用的,它只是一种理念。有些框架适用于开发这种系统,若是使用它们,能够获得不少便利。web

开发框架

ExtJS能够称为第一代单页应用框架的典型,它封装了各类UI组件,用户主要使用JavaScript来完成整个前端部分,甚至包括布局。随着功能逐渐增长,ExtJS的体积也逐渐增大,即便用于内部系统的开发,有时候也显得笨重了,更不用说开发以上这类运行在互联网上的系统。后端

jQuery因为偏重DOM操做,它的插件体系又比较松散,因此比ExtJS这个体系更适合开发在公网运行的单页系统,整个解决方案会相对比较轻量、灵活。设计模式

但因为jQuery主要面向上层操做,它对代码的组织是缺少约束的。如何在代码急剧膨胀的状况下控制每一个模块的内聚性,而且适当在模块之间产生数据传递与共享,就成为了一种有挑战的事情。浏览器

为了解决单页应用规模增大时候的代码逻辑问题,出现了很多MV*框架,他们的基本思路都是在JS层建立模块分层和通讯机制。有的是MVC,有的是MVP,有的是MVVM,并且,它们几乎都在这些模式上产生了变异,以适应前端开发的特色。

这类框架包括Backbone,Knockout,AngularJS,Avalon等。

组件化

这些在前端作分层的框架推进了代码的组件化,所谓组件化,在传统的Web产品中,更多的指UI组件,但其实组件是一个普遍概念,传统Web产品中UI组件占比高的缘由是它的厚度不足,随着客户端代码比例的增长,至关一部分的业务逻辑也前端化,由此催生了不少非界面型组件的出现。

分层带来的一个优点是,每层的职责更专注了,由此,能够对其做单元测试的覆盖,以保证其质量。传统UI层测试最头疼的问题是UI层和逻辑混杂在一块儿,好比每每会在远程请求的回调中更改DOM,当引入分层以后,这些东西均可以分别被测试,而后再经过场景测试来保证总体流程。

代码隔离

与开发传统页面型网站相比,实现单页应用的过程当中,有一些比较值得特别关注的点。

从单页应用的特色来看,它比页面型网站更加依赖于JavaScript,而因为页面的单页化,各类子功能的JavaScript代码汇集到了同一个做用域,因此代码的隔离、模块化变得很重要。

在单页应用中,页面模板的使用是很广泛的。不少框架内置了特定的模板,也有的框架须要引入第三方的模板。这种模板是界面片断,咱们能够把它们类比成JavaScript模块,它们是另外一种类型的组件。

模板也同样有隔离的须要。不隔离模板,会形成什么问题呢?模板间的冲突主要存在于id属性上,若是一个模板中包含固定的id,当它被批量渲染的时候,会形成同一个页面的做用域中出现多个相同id的元素,产生不可预测的后果。所以,咱们须要在模板中避免使用id,若是有对DOM的访问需求,应当经过其余选择器来完成。若是一个单页应用的组件化程度很是高,极可能整个应用中都没有元素id的使用。

代码合并与加载策略

人们对于单页系统的加载时间容忍度与Web页面不一样,若是说他们愿意为购物页面的加载等待3秒,有可能会愿意为单页应用的首次加载等待5-10秒,但在此以后,各类功能的使用应当都比较流畅,全部子功能页面尽可能要在1-2秒时间内切换成功,不然他们就会感受这个系统很慢。

从这些特色来看,咱们能够把更多的公共功能放到首次加载,以减少每次加载的载入量,有一些站点甚至把全部的界面和逻辑所有放到首页加载,每次业务界面切换的时候,只产生数据请求,所以它的响应是很是迅速的,好比青云的控制台就是这么作的。

一般在单页应用中,无需像网站型产品同样,为了防止文件加载阻塞渲染,把js放到html后面加载,由于它的界面基本都是动态生成的。

当切换功能的时候,除了产生数据请求,还须要渲染界面,这个新渲染的界面部件通常是界面模板,它从哪里来呢?来源无非是两种,一种是即时请求,像请求数据那样经过AJAX获取过来,另外一种是内置于主界面的某些位置,好比script标签或者不可见的textarea中,后者在切换功能的时候速度有优点,可是加剧了主页面的负担。

在传统的页面型网站中,页面之间是互相隔离的,所以,若是在页面间存在可复用的代码,通常是提取成单独的文件,而且可能会须要按照每一个页面的需求去进行合并。单页应用中,若是总的代码量不大,能够总体打包一次在首页载入,若是大到必定规模,再做运行时加载,加载的粒度能够搞得比较大,不一样的块之间没有重复部分。

路由与状态的管理

咱们最开始看到的几个在线应用,有的是对路由做了管理的,有的没有。

管理路由的目的是什么呢?是为了能减小用户的导航成本。好比说咱们有一个功能,经历过屡次导航菜单的点击,才呈现出来。若是用户想要把这个功能地址分享给别人,他怎么才能作到呢?

传统的页面型产品是不存在这个问题的,由于它就是以页面为单位的,也有的时候,服务端路由处理了这一切。可是在单页应用中,这成为了问题,由于咱们只有一个页面,界面上的各类功能区块是动态生成的。因此咱们要经过对路由的管理,来实现这样的功能。

具体的作法就是把产品功能划分为若干状态,每一个状态映射到相应的路由,而后经过pushState这样的机制,动态解析路由,使之与功能界面匹配。

有了路由以后,咱们的单页面产品就能够前进后退,就像是在不一样页面之间同样。

其实在Web产品以外,早就有了管理路由的技术方案,Adobe Flex中,就会把好比TabNavigator,甚至下拉框的选中状态对应到url上,由于它也是单“页面”的产品模式,须要面对一样的问题。

当产品状态复杂到必定程度的时候,路由又变得很难应用了,由于状态的管理极其麻烦,好比开始的时候咱们演示的c9.io在线IDE,它就无法把状态对应到url上。

缓存与本地存储

在单页应用的运做机制中,缓存是一个很重要的环节。

因为这类系统的前端部分几乎全是静态文件,因此它可以有机会利用浏览器的缓存机制,而好比动态加载的界面模板,也彻底能够作一些自定义的缓存机制,在非首次的请求中直接取缓存的版本,以加快加载速度。

甚至,也出现了一些方案,在动态加载JavaScript代码的同时,把它们也缓存起来。好比Addy Osmani的这个basket.js,就利用了HTML5 localStorage做了js和css文件的缓存。

在单页产品中,业务代码也经常会须要跟本地存储打交道,存储一些临时数据,可使用localStorage或者localStorageDB来简化本身的业务代码。

服务端通讯

传统的Web产品一般使用JSONP或者AJAX这样的方式与服务端通讯,但在单页Web应用中,有很大一部分采用WebSocket这样的实时通信方式。

WebSocket与传统基于HTTP的通讯机制相比,有很大的优点。它可让服务端很便利地使用反向推送,前端只响应确实产生业务数据的事件,减小一遍又一遍无心义的AJAX轮询。

因为WebSocket只在比较先进的浏览器上被支持,有一些库提供了在不一样浏览器中的兼容方案,好比socket.io,它在不支持WebSocket的浏览器上会降级成使用AJAX或JSONP等方式,对业务代码彻底透明、兼容。

内存管理

传统的Web页面通常是不须要考虑内存的管理的,由于用户的停留时间相对少,即便出现内存泄漏,可能很快就被刷新页面之类的操做冲掉了,但单页应用是不一样的,它的用户极可能会把它开一成天,所以,咱们须要对其中的DOM操做、网络链接等部分格外当心。

样式的规划

在单页应用中,由于页面的集成度高,全部页面汇集到同一做用域,样式的规划也变得重要了。

样式规划主要是几个方面:

基准样式的分离

这里面主要包括浏览器样式的重设、全局字体的设置、布局的基本约定和响应式支持。

组件样式的划分

这里面是两个层面的规划,首先是各类界面组件及其子元素的样式,其次是一些修饰样式。组件样式应当尽可能减小互相依赖,各组件的样式容许冗余。

堆叠次序的管理

传统Web页面的特色是元素多,可是层次少,单页应用会有些不一样。

在单页应用中,须要提早为各类UI组件规划堆叠次序,也就是z-index,好比说,咱们可能会有各类弹出对话框,浮动层,它们可能组合成各类堆叠状态。新的对话框的z-index须要比旧的高,才能确保盖在它上面。诸如此类,都须要咱们对这些可能的遮盖做规划,那么,怎样去规划呢?

了解通讯知识的人,应当会知道,不一样的频率段被划分给不一样的通讯方式使用,在一些国家,领空的使用也是有划分的,咱们也能够用一样的方式来预先分段,不一样类型的组件的z-index落到各自的区间,以免它们的冲突。

单页应用的产品形态

咱们在开始的时候提到,存在着不少新型Web产品,使用单页应用的方式构建,但实际上,这类产品不只仅存在于Web上。点开Chrome商店,咱们会发现不少离线应用,这些产品均可以算是单页应用的体现。

除了各类浏览器插件,借助node-webkit这样的外壳平台,咱们可使用Web技术来构建本地应用,产品的主要部分仍然是咱们熟悉的单页应用。

单页应用的流行程度正在逐渐增长,你们若是关注了一些初创型互联网企业,会发现其中很大一部分的产品模式是单页化的。这种模式能带给用户流畅的体验,在开发阶段,对JavaScript技能水平要求较高。

单页应用开发过程当中,先后端是自然分离的,双方以API为分界。前端做为服务的消费者,后端做为服务的提供者。在此模式下,前端将会推进后端的服务化。当后端再也不承担模板渲染、输出页面这样工做的状况下,它能够更专一于所提供的API的实现,而在这样的状况下,Web前端与各类移动终端的地位对等,也逐渐使得后端API没必要再为每一个端做差别化设计了。

部署模式的改变

在如今这个时代,咱们已经能够看到一种产品的出现了,那就是“无后端”的Web应用。这是一种什么东西呢?基于这种理念,你的产品极可能只须要本身编写静态Web页面,在某种BaaS(Backend as a Service)云平台上定制服务端API和云存储,集成这个平台提供的SDK,经过AJAX等方式与之打交道,实现注册认证、社交、消息推送、实时通讯、云存储等功能。

咱们观察一下这种模式,会发现先后端的部署已经彻底分离了,前端代码彻底静态化,这意味着能够把它们放置到CDN上,访问将大大地加速,而服务端托管在BaaS云上,开发者也没必要去关注一些部署方面的繁琐细节。

假设你是一名创业者,正在作的是一种实时协同的单页产品,能够在云平台上,快速定制后端服务,把绝大部分宝贵的时间花在开发产品自己上。

单页应用的缺陷

单页应用最根本的缺陷就是不利于SEO,由于界面的绝大部分都是动态生成的,因此搜索引擎很不容易索引它。

产品单页化带来的挑战

一个产品想要单页化,首先是它必须适合单页的形态。其次,在这个过程当中,对开发模式会产生一些变动,对开发技能也会有一些要求。

开发者的JavaScript技能必须过关,同时须要对组件化、设计模式有所认识,他所面对的再也不是一个简单的页面,而是一个运行在浏览器环境中的桌面软件。

相关文章
相关标签/搜索