Web应用的组件化开发(一)

标签: IT技术 前端开发 徐飞 | 发表时间:2014-01-16 00:53 | 作者:穆逸伦
出处:http://blog.jobbole.com

基本思路

1. 为什么要做组件化?

无论前端也好,后端也好,都是整个软件体系的一部分。软件产品也是产品,它的研发过程也必然是有其目的。绝大多数软件产品是追逐利润的,在产品目标确定的情况下,成本有两个途径来优化:减少部署成本,提高开发效率。

减少部署成本的方面,业界研究得非常多,比如近几年很流行的“去IOE”,就是很典型的,从一些费用较高的高性能产品迁移到开源的易替换的产品集群,又比如使用Linux + Mono来部署.net应用,避开Windows Server的费用。

提高开发效率这方面,业界研究得更多,主要途径有两点:加快开发速度,减少变更代价。怎样才能加快开发速度呢?如果我们的开发不是重新造轮子,而是 每一次做新产品都可以利用已有的东西,那就会好很多。怎样才能减少变更代价呢?如果我们能够理清模块之间的关系,合理分层,每次变更只需要修改其中某个部 分,甚至不需要修改代码,仅仅是改变配置就可以,那就更好了。 我们先不看软件行业,来看一下制造行业,比如汽车制造业,他们是怎么造汽车的呢?造汽车之前,先设计,把整个汽车分解为不同部件,比如轮子,引擎,车门, 座椅等等,分别生产,最后再组装,所以它的制造过程可以较快。如果一辆汽车轮胎被扎破了,需要送去维修,维修的人也没有在每个地方都修一下,而是只把轮胎 拆下来修修就好了,这个轮胎要是实在坏得厉害,就干脆换上个新的,整个过程不需要很多时间。

席德梅尔出过一款很不错的游戏,叫做《文明》(Civilization),在第三代里面,有一项科技研究成功之后,会让工人工作效率加倍,这项科技的名字就叫做:可替换部件(Replacement Parts)。所以,软件行业也应当引入可替换的部件,一般称为组件。

2. 早期的前端怎么做组件化的?

在服务端,我们有很多组件化的途径,像J2EE的Beans就是一种。组件建造完成之后,需要引入一些机制来让它们可配置,比如说,工作流引擎,规 则引擎,这些引擎用配置的方式组织最基础的组件,把它们串联为业务流程。不管使用什么技术、什么语言,服务端的组件化思路基本没有本质差别,大家是有共识 的,具体会有服务、流程、规则、模型等几个层次。

早期展示层基本以静态为主,服务端把界面生成好,浏览器去拿来展示,所以这个时期,有代码控制的东西几乎全在服务端,有分层的,也有不分的。如果做了分层,大致结构就是下图这样:

120140115115021

这个图里,JSP(或者其他什么P,为了举例方便,本文中相关的服务端技术都用Java系的来表示)响应浏览器端的请求,把HTML生成出来,跟相 关的JavaScript和CSS一起拿出去展示。注意这里的关键,浏览器端对界面的形态和相关业务逻辑基本都没有控制权,属于别人给什么就展示什么,想 要什么要先提申请的尴尬局面。

这个时期的Web开发,前端的逻辑是基本可忽略的,所以前端组件化方式大同小异,无论是ASP还是JSP还是其他什么P,都可以自定义标签,把HTML代码和行间逻辑打包成一个标签,然后使用者直接放置在想要的地方,就可以了。

在这一时代,所谓的组件化,基本都是taglib这样的思路,把某一块界面包括它的业务逻辑一起打成一个端到端的组件,整个非常独立,直接一大块从界面到逻辑都有,而且逻辑基本上都是在服务端控制,大致结构如下图所示。

220140115115033

3. SPA时代,出现了新问题

自从Web2.0逐渐流行,Web前端已经不再是纯展示了,它逐渐把以前在C/S里面做的一些东西做到B/S里面来,比如说Google和微软的在线Office,这种复杂度的Web应用如果还用传统那种方式做组件化,很显然是行不通的。

我们看看之前这种组件化的方式,本质是什么?是展现层跟业务逻辑层的隔离,后端在处理业务逻辑,前端纯展现。如果现在还这么划分,就变成了前端有界 面和逻辑,后端也有逻辑,这就比较乱了。我们知道,纯逻辑的分层组件化还是比较容易的,任何逻辑如果跟展现混起来,就比较麻烦了,所以我们要把分层的点往 前推,推到也能把单独的展现层剥离出来。

如下图所示,因为实际上HTML、CSS、JavaScript这些都逐渐静态化,所以不再需要把它们放在应用服务器上了,我们可以把它们放在专门 的高性能静态服务器上,再进一步发展,就可以是CDN(Content Delivery Network,内容分发网络)。前端跟后端的通信,基本都是通过AJAX来,也会有一些其他的比如WebSocket之类,总之尽量少刷新了。

320140115115047

在这张图里面可以看到,真正的前端已经形成了,它跟应用服务器之间形成了天然的隔离,所以也能够很独立地进行一些发展演进。

现在很多Web程序在往SPA(单页面程序,Single Page Application)的方向发展,这类系统通常比较类似传统的C/S程序,交互过程比较复杂,因此它的开发过程也会遇到一些困难。

那为什么大家要做SPA呢?它有很多明显的好处,最核心的优势就是高效。这个高效体现在两个方面:一是对于用户来说,这种方式做出来的东西体验较 好,类似传统桌面程序,对于那些需要频繁操作的行业用户,有很大优势。二是运行的效率较高,之前集成一些菜单功能,可能要用iframe的方式引入,但每 个iframe要独立引入一些公共文件,服务器文件传输的压力较大,还要初始化自己的一套内存环境,比较浪费,互相之间也不太方便通信,一般要通过 postMessage之类的方式去交互。

有了SPA之后,比如一块界面,就可以是一个HTML片段,用AJAX去加载过来处理之后放到界面上。如果有逻辑的JavaScript代码,也可以用require之类的异步加载机制去运行时加载,整体的思路是比较好的。

很多人说,就以这样的需求,用jQuery再加一个异步js加载框架,不是很足够了吗?这两个东西用得好的话,也是能够解决一些问题的,但它们处理 的并不是最关键的事情。在Web体系中,展现层是很天然的,因为就是HTML和CSS,如果只从文件隔离的角度,也可以做出一种划分的方式,逻辑放在单独 的js文件里,html内部尽量不写js,这就是之前比较主流的前端代码划分方式。

刚才我们提到,SPA开发的过程中会遇到一些困难,这些困难是因为复杂度大为提升,导致了一些问题,有人把这些困难归结为纯界面的复杂度,比如说, 控件更复杂了之类,没有这么简单。问题在于什么呢?我打个比方:我们在电脑上开两个资源管理器窗口,浏览到同一个目录,在一个目录里把某个文件删了,你猜 猜另外一个里面会不会刷新?

毫无疑问,也会刷新,但是你看看你用的Web页面,如果把整个复杂系统整合成单页的,能保证对一个数据的更新就实时反馈到所有用它的地方吗?怎么做,是不是很头疼?代码组织的复杂度大为提高,所以需要做一些架构方面的提升。

4. 架构的变更

提到架构,我们通常会往设计模式上想。在著名的《设计模式》一书中,刚开始就讲了一种典型的处理客户端开发的场景,那就是MVC。

传统的MVC理念我们并不陌生,因为有Struts,所以在Web领域也有比较经典的MVC架构,这里面的V,就负责了整个前端的渲染,而且是服务端的渲染,也就是输出HTML。如下图所示:

420140115115100

在SPA时代,这已经不合适了,所以浏览器端形成了自己的MVC等层次,这里的V已经变成客户端渲染了,通常会使用一些客户端的HTML模版去实现,而模型和控制器,也相应地在浏览器端形成了。

520140115115113

我们有很多这个层面的框架,比如Backbone,Knockout,Avalon,Angular等,采用了不同的设计思想,有的是MVC,有的是MVP,有的是MVVM,各有其特点。

以Angular为例,它推荐使用双向绑定去实现视图和模型的关联,这么一来,如果不同视图绑定在同一模型上,就解决了刚才所说的问题。而模型本身也通过某种机制,跟其他的逻辑模块进行协作。

这种方式就是依赖注入。依赖注入的核心理念就是通过配置来实例化所依赖的组件。使用这种模式来设计软件架构,会牺牲一些性能,在跟踪调试的便利性等方面也会有所损失,但换来的是无与伦比的松耦合和可替代性。

比如说,这些组件就可以单独测试,然后在用的时候随手引入,毫无压力。对于从事某一领域的企业来说,光这一条就足以吸引他在上面大量投入,把所有不常变动领域模型的业务代码都用此类办法维护起来,这是一种财富。

5. MV*框架的基本原理

如果我们来设计Angular这么一个前端框架,应当如何入手呢?很显然,逻辑的控制必须使用JavaScript,一个框架,最本质的事情在于它的逻辑处理方式。

我们的界面为什么可以多姿多彩?因为有HTML和CSS,注意到这两种东西都是配置式的写法,参照后端的依赖注入,如果把这两者视为跟Spring框架中一些XML等同的配置文件,思路就豁然开朗了。

与后端不同的是,充当前端逻辑工具的JavaScript不能做入口,必须挂在HTML里才能运行,所以出现了一个怪异的状况:逻辑要先挂在配置文 件(HTML)上,先由另外的容器(浏览器或者Hybird的壳)把配置文件加载起来,然后才能从某个入口开始执行逻辑。好消息是,过了这一步,逻辑层就 开始大放异彩了。

从这个时候开始,框架就启动了,它要做哪些事情呢?

  • 初始化自身(bootstrap)
  • 异步加载可能尚未引入的JavaScript代码(require)
  • 解析定义在HTML上的规则(template parser)
  • 实例化模型(scope)
  • 创建模型和DOM的关联关系(binding, injection)

这些是主线流程,还有一些支线,比如:

  • 解析url的search字符串,恢复状态(route)
  • 加载HTML部件模板(template url)
  • 部件模板和模型的关联(binding)

6. 如何做组件化

6.1. HTML的组件化

SPA的一个典型特征就是部分加载,界面的部件化也是其中比较重要的一环。界面片段在动态请求得到之后,借助模版引擎之类的技术,经过某种转换,放置到主界面相应的地方。所以,从这个角度来看,HTML的组件化非常容易理解,那就是界面的片段化和模板化。

6.2. JavaScript的组件化

JavaScript这个部分有好几个发展阶段。

  • 早期的共享文件,把公共功能的代码提出出来,多个页面共用
  • 动态引用,消灭全局变量
  • 在某些框架上进一步划分,比如Angular里面又分为provider,service,factory,controller

JavaScript组件化的目标是什么呢,是清晰的职责,松耦合,便于单元测试和重复利用。这里的松耦合不仅体现在js代码之间,也体现在js跟 DOM之间的关系,所以像Angular这样的框架会有directive的概念,把DOM操作限制到这类代码中,其他任何js代码不操作DOM。

620140115115446

如上图所示,总的原则是先分层次,层内再作切分。这么做的话,不再存在之前那种端到端组件了,使用起来没有原先那么方便,但在另外很多方面比较好。

6.3. CSS的组件化

这方面,业界也有很多探索,比如LESS,SASS,Stylus等。为什么CSS也要做组件化呢?传统的CSS是一种扁平的文本结构,变更成本较 高,比如说想要把结构从松散改紧凑,需要改动很多。如果把实际使用的CSS只当作输出结果,而另外有一种适合变更的方式当作中间过程,这就好多了。比如 说,我们把一些东西定义成变量,每个细节元素使用这些变量,当需要整体变更的时候,只需修改这些变量然后重新生成一下就可以了。

以上,我们讨论了大致的Web前端开发的组件化思路,后续将阐述组件化之后的协作过程和管控机制。

Web应用的组件化开发(一),首发于 博客 - 伯乐在线

相关 [web 应用 开发] 推荐:

Web应用程序的开发步骤

- xxg - 月光博客
  如今已进入了web2.0高速发展的互联网时代,各种互联网的Web应用程序如雨后春笋般出现. 那么作为一名Web开发人员,怎样去开发一款优秀的Web应用程序呢. 这个问题没有一个简单的答案,甚至那些教育机构都未必能清楚的知道. 所以,像大多数在这个领域里的web开发人员一样,我们只是通过去做,去实验才学会了这些.

Web应用的组件化开发(一)

- - 博客 - 伯乐在线
无论前端也好,后端也好,都是整个软件体系的一部分. 软件产品也是产品,它的研发过程也必然是有其目的. 绝大多数软件产品是追逐利润的,在产品目标确定的情况下,成本有两个途径来优化:减少部署成本,提高开发效率. 减少部署成本的方面,业界研究得非常多,比如近几年很流行的“去IOE”,就是很典型的,从一些费用较高的高性能产品迁移到开源的易替换的产品集群,又比如使用Linux + Mono来部署.net应用,避开Windows Server的费用.

Web开发者必备:Web应用检查清单

- - ITeye博客
想做一个高质量的Web应用,前前后后要做的事情非常多. 国外开发者 Ata Sasmaz 为 Web 开发者制作分享了一份检查清单,包括应用开发、性能、安全、分析、可用性、可靠性、转换策略、竞争策略这些方面需要注意的事项. 清单内容可能不全面,欢迎大家在评论中补充. JavaScript 允许捕获异常.

web开发设计人员不可不用的在线web工具和应用

- - 前端观察
大家可能还记得在过去的文章我们我们曾经介绍我们收集的 前端开发人员必备的工具,脚本和资源,在今天的这篇文章中,我们将继续推荐给大家一组我们精挑细选的web开发设计必备的在线工具应用. 相信会在web开发和设计的过程中给你带来方便和快捷. jsfiddle是老牌的在线调试和分享代码的网站,它可以帮助你在线调试javascript/css/html代码, 并且方便的发布到社区,论坛或者社交媒体上与朋友们分享或者提问.

Chrome和Firefox联手开发跨浏览器Web App应用

- pansin - Solidot
whuhacker 写道 "Mozilla曾经计划发布一个开放的跨浏览器Web App Store,使得Web应用可以运行于Firefox、Chrome、IE、Safari、Opera等多种浏览器. 现在,Chrome正和Firefox联手推进这项计划. 一个名为Web Intents的框架正在开发以帮助Web Apps更加顺畅地运行.

[译]使用YUI 3开发Web应用的诀窍

- 小伟 - Taobao UED Team
导语:这篇“基于YUI3开发web应用的诀窍”是比较经典的介绍 YUI3 工作机制的文章,文章发布在yuiblog上,总体难度适中,比较适合初学者认识、了解 YUI3. 以此纠集了三名应届同学来翻译这篇文章:函谷、郝黎、张勉,并希望能对正在学习YUI3的同学有所帮助和启发. 原文标题:A Recipe for a YUI 3 Application.

Native Client让你使用C/C++开发Web应用

- 冷月 - ITeye资讯频道
最新版的Chrome Beta已经可以使用C以及C++语言来开发Web应用了,而这一切正是得益于Google的Native Client. Native Client应用是运行在Web平台上的,所以开发者不需要为每一个操作系统都做一个版本. 同时Native Client应用使用的是Pepper插件API,这个API可以让你用C和C++语言开发具有HTML 5功能的应用程序.

10个优秀的移动Web应用开发框架

- 幻幽 or A書 - 伯乐在线 -博客
  在最近几年里,移动互联网高速发展、市场潜力巨大. 继计算机、互联网之后,移动互联网正掀起第三次信息技术革命的浪潮,新技术、新应用不断涌现. 今天这篇文章向大家推荐10大优秀的移动Web开发框架,帮助开发者更加高效的开发移动Web应用.   Sencha Touch 是世界上第一个基于 HTML5 的移动 Web 开发框架,支持最新的 HTML5 和 CSS3 标准,全面兼容 Android 和 Apple iOS 设备,提供了丰富的 WEB UI 组件,可以快速的开发出运行于移动终端的应用程序.

10个最好的移动Web应用开发框架

- Yangan - Creative奥涛的博客_Creative奥涛的博客
在最近几年里,移动互联网高速发展、市场潜力巨大. 继计算机、互联网之后,移动互联网正掀起第三次信息技术革命的浪潮,新技术、新应用不断涌现. 今天这篇文章向大家推荐10大优秀的移动Web开发框架,帮助开发者更加高效的开发移动Web应用. Sencha Touch 是世界上第一个基于 HTML5 的移动 Web 开发框架,支持最新的 HTML5 和 CSS3 标准,全面兼容 Android 和 Apple iOS 设备,提供了丰富的 WEB UI 组件,可以快速的开发出运行于移动终端的应用程序.

Diffbot:开发者工具 将web内容转换成应用

- 书皮 - 互联网的那点事...
据国外媒体报道,Diffbot公司的技术不仅具有“极客气质”, 而且非常有趣:它利用机器人、算法、计算机视觉和人工智能,像人类一样处理Web上的内容. Diffbot的联合创始人Mike Tung说:“互联网上的页面可以分成30种不同的类型,Diffbot可以识别出其中的每一种. ”这就是说,Diffbot能区别社交网站个人资料、博客、网站首页、产品页面、活动页面等等之间的差异.