`
wusuoya
  • 浏览: 641317 次
  • 性别: Icon_minigender_2
  • 来自: 成都
社区版块
存档分类
最新评论

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

    博客分类:
  • web
 
阅读更多

管控平台

在上一篇中我们提到了组件化的大致思路,这一篇主要讲述在这么做之后,我们需要哪些外围手段去管控整个开发过程。从各种角度看,面对较大规模前端开发团队,都有必要建立这么一个开发阶段的协作平台。

在这个平台上,我们要做哪些事情呢?

1. HTML片段

我们为什么要管理HTML片段?因为有界面要用它们,当这些片段多了之后,需要有个地方来管理起来,可以检索、预览它们,还能看到大致描述。

这应该是整个环节中一个相对很简单的东西,照理说,有目录结构,然后剩下的就是单个的HTML片段文件了,这就可以解决存储和检索的问题了,但我们还要考虑更多。

已有的HTML片段,如何被使用呢?这肯定是一种类似include的方式,通过某种特殊标签(不管是前端还是后端的方式)把这些片段引用进来,这时候就有了第一个问题:

假设有界面A和界面B同时引用了片段C,在某个开发人员修改片段C内容的时候,他如何得知将会影响到界面A和B呢?一个比较勉强的方式是全项目查找,但这在很多情况下是不够的。

如果我们的HTML片段是作为独立的公共库存在的,它已经不能通过项目内查找去解决这一问题了,因为不管A还是B,只要他不处于片段C的项目空间,就无从追寻。

这时候很多人会问两个问题:

  1. 跨项目的界面片段重用,意义在哪里?

    如果我们的产品是针对一个小领域,它的复杂度根本不需要划分多个项目部分来协作完成。设想场景是面对很大的行业,各项目都是子产品,将来可能是其中若干个 联合部署,这时候,保持其中的一致性是非常重要的。比如我们有个基本配置界面,在多个子产品中都要用,如果各自开发一个,其操作风格很可能就是不一致的, 给人的印象就是不专业。所以会需要把常见的界面片段都归集起来,供业务方挑选使用。

  2. 修改C,只提供说明,但是不通知A和B,不实时更新他们的版本,然后自行决定怎样升级,如何?

    这会有一个问题,每次有小功能升级的时候,代码是最容易同步合并的,所以才会有“持续集成”这个概念,如果是一直伴随升级,总要比隔一个大阶段才升级好,升级成本应尽量分摊到平时,就像农妇养小猪,小猪每天长一点,每天都抱来抱去,不觉得吃力,即使长大了也还能抱得动。

现在问题就很明确了,一定要有一种方式来把这个依赖关系管理起来,很显然,已有的版本库是肯定管不了这些的,所以只能在外围做一些处理。

我们建立一个管理平台,除了管理实体文件的版本,还管它们之间的关系。具体这个关系如何收集整理,有两种方式:手动配置,代码分析。

手动配置是比较土的方式,开发人员每提交一个文件,就去这系统上手动配置它的依赖关系。代码分析的话,要在每次提交文件的时候解析文件的包含规则,找出确切的文件。这两者各有利弊,前者比较笨,但容易做,后者对代码格式的要求比较高,要考虑的情况较多。

我们的界面往往不是那么简单,HTML片段也可能有层次的,举例来说:

界面A里面包含了片段B,但是片段B自身又包含了片段C,所以这个依赖关系也是有层级的,需要在设计的时候一并考虑。

2. JavaScript模块

JavaScript代码的管理,比HTML片段的状况好一些,因为业界很多这方面的解决方案。但它们还是没有解决当依赖项产生变更的时候反向通知的问题。

所以我们还是得像HTML片段一样,把它们的依赖关系都管理到平台里。于是,每个JavaScript模块都显式配置了自己所依赖的其他模块,通过这种单向关系,形成了一套完整的视图。

在JavaScript模块的代码实现中,我们是不提倡直接写依赖关系的。很多通用规范,比如AMD,往往建议我们这样写模块:

define(['dep1', 'dep2'], function (dep1, dep2) {
    var moduleA = function () {};
    return moduleA;
});

但我们的系统是面向行业的,比这种通用解决方案要苛刻一些。比如说,如果有一天重构代码,JavaScript模块们调整了目录或者名字,这么写的 就痛苦了,他必须把所有影响到的都去调整一遍,这是要搜索替换的。况且,就像上面HTML模板的部分提到的,影响了处于其他项目中依赖它的代码,缺少合适 的方式去通知他们修改。

所以我们期望的是,在每个编写的JavaScript模块中只存放具体实现,而把依赖关系放在我们的平台上管理,这样,即使当前模块作了改名之类的重构处理,处于外部项目中依赖它的那些代码也不必修改,下一次版本发布的生成过程会自动把这些事情干掉。

对应到上面的这段代码,我们需要开发人员做的只是其中的实现,也就是moduleA的那个部分,外面这些依赖的壳子,是会在发布阶段根据已配置的依赖关系自动生成的。

如果需要,JavaScript模块还可以细分,比如类似Angular里面那样,把factory,controller和directive分离出来,这会对后续有些处理提供方便。

现在我们有必要讨论一下模块的粒度了,我们这里提到的都是基本的粒度,每个JavaScript模块中存放的应该只有一个很具体东西的实现。那么,有个问题,在我们发布的时候,是不是就按照这个粒度发布出去呢?

很显然不行,如果这么做,很可能会出现复杂界面一次要用10多个HTTP请求才能加载完它所需要的所有JavaScript代码的情况,所以需要做一些合并。

那么,合并的策略是什么?在我们这个平台上,开发人员又是要怎样定义这个合并关系的呢?我们需要在模块之上定义一个更大粒度的组织方式,这个方式与 模块的关系,就好比Java里面,jar文件与class的关系。如果开发人员不显式配置,也可以通过全局策略,比如按最下层目录来合并。

这个时候,在实际使用这些代码的时候,需要带两个配置信息过去,一个是要动态载入的JavaScript文件(合并之后的),二是每个JavaScript文件中包含的原始模块。

3. 单元测试

如果JavaScript模块都已经被良好有序管理起来,就可以为它们考虑单元测试的事情了。单元测试对于提高基础单元的可靠度,是有非常重要意义的。

在我们这个平台里,可以把单元测试跟JavaScript模块关联起来,每个JavaScript模块可以挂一组单元测试代码,这些代码可以在线编写,在线运行。

单元测试的本质就是编写模拟代码来调用已有模块,考虑到我们的模块是JavaScript,所以很多思路都倾向于在浏览器端执行它们,对于单个模块的单元测试,这不是个问题。

如果要批量执行整个系统的单元测试,那就不一样了。把JavaScript代码先加载到浏览器中,然后再执行,很多时候并不需要这么复杂。我们完全可以在服务端把它们做了。

借助Node.js的能力,我们可以在服务端执行JavaScript代码,也就意味着能够把绝大多数JavaScript模块的单元测试在服务端就执行掉。当然,我们为此可能要多做不少事情,比如说,有些库需要移植一份node版的,常见的有AJAX调用等等。

注意了,能够在服务端做JavaScript单元测试是有先决条件的,代码的分层必须很良好,除了视图层,其他任何层面都不能操作DOM。所以我们 这里主要测试的也正是除了视图层之外的所有JavaScript业务逻辑。至于视图层怎么办?这个真的很难解决,这世界上不是所有东西都能自动做的,只能 先把可做的做了,以后再来考虑这些。

4. 文档和示例管理

4.1. 文档

现在我们有HTML片段和JavaScript模块了,需要给它们多一些描述信息。简单描述显然是不够的,我们还要详细文档。

这种详细文档可以通过某种方式生成,也可以由开发人员手动编写。与传统的离线文档不同,在线的文档更实时,并且,每当一个开发人员变更了他的文档之后,不需要经过全量构建,访问者可以实时访问到他的最新版本。

熟悉GitHub的朋友们可能早已习惯这种方式,在项目库里面存在一些以md格式结尾的文本文件,使用markdown语法来编写一些说明文档。

毫无疑问,这类格式很适合在线协作,所以我们也会在平台上集成这么一种编写文档的方式,无论是针对HTML模板还是JavaScript模块,或者是其他什么类型,甚至还可以用来当博客,就像月影同学的gitpress平台,能直接从GitHub上拉取文本或者HTML文件形成博客。

文档除了以集成的形式浏览之外,应当也可以以单独链接的方式发出去,这时候用户就可以像看一个新闻网页一样去浏览。如果再进一步做下去,还可以做电子书的生成,提供打包的离线文档。

4.2. 示例

在编写代码文档的过程中,可能免不了要插入示例,示例有两种形态,一种是纯文本,类似gist这样,一种是可在线运行,类似jsfiddle和jsbin这样。

这两种都有各自的优点,所以可以都做,示例的存放可以与文档类似,也应当能通过一个链接独立运行。

4.3. 幻灯片

有时候我们看到一些在线的幻灯片,觉得效果很帅,比如reveal.js,我们的开发人员有时候作代码分析或者走查的时候也不免要写一些演示,如果能把这些东西也随项目管理起来,能在线查看,会是很不错的一件事。所以我们也可以考虑给它们加个存储界面,甚至做个简易的在线编写器。

5. 项目与目录管理

说到现在,我们似乎还遗漏了一点什么。那就是以上提到的这些东西,以什么为组织单位来存储?

考虑到我们的这个平台是要管理一整个大产品的全部前端内容的,它里面应该分了很多项目,对应到子产品上,这么一来,很自然地,项目就成了第一级组织单位。项目之下,没有悬念地,只有目录了。

对于一个项目而言,它有哪些要做的事情呢?首先要能配置其实体存储位置。前面提到的这么多代码、文档之类,最终都是要实体存储的,怎么存?我们当然 可以自己搞一套,在文件系统上做起来,但是还要考虑它们的版本管理,非常麻烦,所以不如直接对接某个版本库,调用它的接口去存取文件,这里配置的就是版本 库的路径。

其次,要考虑从已有项目复制,类似GitHub里面的fork功能,不过内部处理机制可以略有不同,fork的项目默认未必要有实体文件,只有当产 生了修改或者新增操作的时候才创建,剩下的还引用原来的就可以了。我们这里的项目复制功能是为项目化版本而考虑的,经常出现一个产品版本支持多个客户项目 的情况,所以可能会用得着这个特性。

然后,也要考虑项目的依赖关系。依赖一个项目,意思是需要用到它里面的组件,所以实质是组件的依赖。提供项目依赖这个视图,只是为了未来变更的一些考虑。

6. 评论管理

之前提到,我们整个平台的目的是为了提高大型前端团队的协作能力,协作是离不开交流的。上述的任何功能,都应当带有交流沟通的能力。

比如说,如果开发人员A使用了其他人写的一个代码组件a,对其中一些细节有疑问,他应当可以对它进行评论。在他评论的时候,任何参与维护过这个组件的人员都能收到一个提醒,这时候他可以选择过来看看,回复这个疑问。同理,在文档、示例下也可以如此操作。

在互联网上有这类产品,用于在任意URL下挂接评论交流系统,比较有名的就是Disqus,我们可以看到很多网站下面挂着它,用于做交流评论,这样用户可以用一个账号在多个网站之间交流。国内也有同类的,比如多说,能够用微博、QQ等账号登录进行交流。

从我们这个平台本身看,如果是部署在企业内部作流程提升,引入外部评论系统的可能性就比较小了。因为在企业内部用,一定是希望这个员工的账号信息跟工号挂钩,也能够跟版本服务器账号等模块作集成,权限也便于控制。

从另外一个角度讲,某个人员登录这个系统的时候,他可能收到很多消息,来自不同的代码或文档位置,挨个点过去回复也有些麻烦,我们应当给他提供一个全局视图,让他能在一个统一的界面把这些问题都答复掉,如果他需要的话,也是可以点进去到实际的位置。

7. 用户和权限控制

从以上部分我们已经看到,这个系统是一个比较复杂的开发过程管控平台。这样的话,每个使用的人就应当可以登录,然后分配不同的权限等级。

未登录用户应当有一些东西的查看权限,但是不能发表评论。已登录的用户根据权限级别,可以控制能否创建、修改项目,创建、修改目录,代码,单元测试,文档等。

8. 国际化字符串管理

一个跨语言区域的Web应用不可避免要跟国际化打交道,这个事情通常是在服务端做,比如通过在界面代码中嵌入类似<% =getRes(key, lan) %>这样的代码,去获取相应的字符串,替换到界面里来。

这个事情是要占用应用服务器资源的,而且国际化本身其实是一个在运行之前就已经确定的事,完全可以把这个过程放在发布阶段就做掉。比如说,我们给每种语言预先就把代码生成多份,只是部署在一起,根据需要的情况来动态加载特定的那一份。

有不少客户端的国际化方案,是把资源文件拆细,以页面为单位存储,但这其实是不太合理的。第一个原因就是在Web2.0时代,“页面”这个概念本身就已经弱化了,到了单页应用里,整个应用都只是一个页面,这个时候,资源文件以什么粒度来组织呢?

我们提到过,采用MV*框架去做Web应用的架构,有一个目标是做组件化。组件化的意图就是某个组件可以尽可能随心所欲地放在需要的地方用。如果把资源文件的粒度弄小到对应HTML片段和JavaScript模块这一级,灵活性倒是有了,带来的问题就是管理成本增大。

做一个行业应用,最重要的就是业务一致性,这包括逻辑的一致性,也包括了术语的一致性。某一个词,可能在多个资源文件中都出现,这就增加了不一致的可能性。

所以,应当有一个统一的术语管理平台,一切界面上出现的文字或者提示,都必须来自这个平台。

9. 静态资源的管理

在发布系统的时候,除了需要发布代码,还需要发布图片等静态资源,这些东西也应当被管理起来。

静态资源在两种情况下可用:随产品发布,在本平台被引用。比如说有一个图片,在这个平台上作了管理,它可以被配置到某个项目上,在发布的时候导出。这个图片还可以被用链接的方式查看或者下载,如果本平台内部的一个文档或者示例要引用它,也是可以的。

10. 样式与主题管理

在Web系统里,样式和主题是很重要的一环。样式的管理和发布一直是一个比较复杂的话题,早几年一般都是分块写,然后组合合并,最近这些年有LESS,SASS和Stylus这类技术,解决了编写和发布的分离问题。

我们看看发布的最大问题是什么?是不同部分的合并。为了追求灵活性,不得不把东西拆得很细,之前HTML片段和JavaScript模块的处理方式都是这样。这么做,我们就需要另外一件事:这些细小的东西,尽可能要覆盖全面。

对应到CSS里面,我们要做的是把每种在系统中可能出现的元素、类别都作为单独的规则维护起来,生成一个全局的规则列表。不同项目间,实现可以不 同,但规则的名字是固定的,定制只允许修改实现,不允许修改规则。如果要新增之前没有的规则,也必须在全局规则列表里先添加,再作实现。

样式规则被管理之后,可以在界面组件上对它作关联,也可以不做。做的好处是发布的时候能只把用到的那些样式规则生成发布出去,如果能接受每次发布全量CSS,那也无所谓。

除了规则,也需要考虑一些变量的管理,在CSS中合理使用变量,会大为减轻定制化所导致的工作量。

11. 一键发布

我们引入了这么一堆东西,其实是增加了发布的复杂度。为什么呢?

之前不管HTML、JavaScript还是CSS,都是手写出来,最多经过一个minify的工作,就发布了,整个过程很简单,两句脚本搞定。

现在可复杂了,先要分析依赖关系,然后提取文件,然后国际化字符串替换,然后合并,然后代码压缩,整个过程很折腾,不给配置管理员一个解释的话,他一定过来砍人。

我们有个原则:解决问题的过程中,如果引入了新的问题,要求负责解决原问题的人也一起解决掉。现在为了一些意图,增加了版本发布的复杂度,那也要有个办法再把这事摆平,至少不能比原来复杂。

所以我们就要把这些过程都集成到管控平台里,做一个一键发布的过程,把所有的这些操作都集成起来,配置管理员发布版本的时候只要点一下就可以把所有这些事情做掉。甚至说,这些流程还可以配置,能够加减环节。

这时候我们做到了跟之前发版本一样方便,能不能多做点什么呢?

可以把JavaScript单元测试集成到版本发布阶段。因为我们已经把JavaScript按照职责做了分层,并且把UI部分做了隔离,就可以在浏览器之外把这个单元测试做掉,平时提交代码的时候也可以做,最终在版本发布阶段再全量做一下,也是很有意义的。

代码依赖关系管理的另一个目的是什么呢?是最小化发布,既然我们都管理了文件之间的关系,那么,从根出发,显然是能够得出哪些代码文件在本项目中使用的,就可以每次从我们的全量代码库中取得确切需要的一部分来发布。这也是我们整个管控平台带来的优势。

12. 小结

我们这一篇比较复杂,提出了一整套解决大规模前端协作的管控机制。这套理论的本质是在开发和版本发布之间加了一个环节,把Web体系中除了服务之外的一切静态资源都纳入其中,强化了现有主流的一些基于命令行的前端工程化组织模式。

相比于传统行业,比如汽车制造,我们这个环节相当于生产流水线的设计,其中一些组件的存储就类似仓储机制,发布就类似出厂过程。

这个平台本身还有不少其他的可做的东西,比如甚至可以在上面做界面的可视化定制等,这些是长远的终极目标,在后面的文章里会谈谈一些考虑。

后续文章中,我们会展望有了这个平台之后,整个前端的协作流程是怎样的。

分享到:
评论

相关推荐

    Web前端工程化与组件化开发实践

    在现代Web开发中,"Web前端工程化与组件化开发实践"已经成为提升开发效率和代码质量的重要手段。本文将深入探讨这两个概念,并结合具体的实践案例,解析如何在JavaScript开发中应用它们。 首先,前端工程化是指通过...

    多组件Web可视化开发平台在调度自动化系统中的应用.pdf

    1. **零编码、可视化开发Web应用系统**:这种开发方式极大地降低了Web应用开发的门槛,使得没有编程背景的业务人员也能够参与到Web应用的开发中,有效提高了开发效率,并能够快速响应需求变化。 2. **业务逻辑和...

    用PB开发WEB应用

    PowerBuilder(PB)是一款强大的企业级应用程序开发工具,尤其适合构建数据库驱动的Web应用程序。它以其易用性、高效的数据库访问以及内置的数据窗口组件而受到开发者喜爱。在本主题中,我们将深入探讨如何利用Power...

    NetBeans可视化Web开发之数据库应用开发

    通过学习上述知识点,开发者不仅可以熟练运用NetBeans进行Web应用的可视化开发,还能掌握数据库应用开发的核心技术。结合提供的"NetBeans可视化Web开发之数据库应用开发.pdf"文件,相信你将能深入理解和实践这一主题...

    SUN web组件开发认证教程

    【SUN Web组件开发认证教程】是一门针对Java EE(Enterprise Edition)平台中Web应用程序开发的专业教程,旨在帮助开发者掌握创建高效、可扩展的Web组件技术。这门课程与SUN(现在已被Oracle公司收购)的认证体系...

    基于web的教育信息化产品开发-阅读辅助平台vue组件化的开发与实现 毕业论文.docx

    本文主要讨论基于web的教育信息化产品开发-阅读辅助平台的vue组件化开发与实现。该论文的研究背景是当前教育信息化的发展对教育的影响,旨在开发一个基于web的阅读辅助平台,以提高学生的阅读能力和学习效率。 知识...

    AE 组件式开发及应用

    AE组件式开发是一种高效、模块化的软件开发方法,它允许开发者将应用程序分解为一系列可重用的组件,每个组件都负责...通过理解并应用组件化开发的最佳实践,开发者可以构建出更高质量的应用程序,同时提高开发效率。

    C++Builder开发Web应用程序

    在Web开发领域,C++Builder 以其独特的组件化方法,简化了复杂度高的Web应用程序开发过程。本文将详细介绍如何使用C++Builder 开发Web应用程序,包括Web应用程序的基本原理、开发流程以及实例演示。 #### Web应用...

    发刊论文:面向企业级web应用的前后端分离开发模式及实践

    针对企业级的 web 应用,研究前后端分离技术,提出一种解决多终端性能、组件化开发和打包部署的完整的开发模型,通过Vue实现组件化开发思想。企业级开发应用实践证明了该开发模式及框架的高效性,满足多终端的设计及...

    Java Web应用开发项目教程(附电子教案,程序源代码,习题答案)

    学习Struts的配置文件、Action类、Form Bean以及Interceptor(拦截器)等核心组件,能够快速开发出高效稳定的Web应用。 7. **数据库连接与JDBC**:在Java Web应用中,通常需要与数据库进行交互。掌握数据库的基本...

    优秀的组件化编程.pdf

    #### 一、组件化开发概述 组件化开发是一种现代软件工程方法论,它强调将大型复杂系统分解为独立且可重用的小型模块(组件)。这种方式不仅提高了软件的可维护性和扩展性,还极大地提升了开发效率。 **标准化与组件...

    web定时器组件

    Web定时器组件是Java Web应用中用于执行周期...综上所述,Web定时器组件是Java Web应用不可或缺的一部分,它能有效地提升应用的自动化水平和效率。选择合适的定时器组件并合理实现,将有助于构建稳定、高效的Web系统。

    组件化WEB前端架构设计与实现.pdf

    组件化开发是一种将软件分解为独立、可重用的模块化单元的方法。在前端领域,这种架构允许开发者快速构建复杂的应用,因为它具有以下优点: - 低耦合:每个组件都有清晰的边界,与其他组件的交互最小化,降低了组件...

    糯米组件化实例仓库

    这个项目,"nuomi-component-master",可能是为了演示或教学如何在实际工作中实施组件化开发,特别适用于那些想了解或提升自己JavaScript组件化能力的开发者。 首先,我们要理解什么是组件化。组件化是将复杂的UI...

    开发J2EE Web应用

    这种设计模式有助于模块化开发,使得系统易于维护和扩展。 #### 3. 技术组件 J2EE定义了一系列关键的技术组件,如Servlets、JavaServer Pages (JSP)、Enterprise JavaBeans (EJB)、Java Messaging Service (JMS)、...

    漫谈Web前端的『组件化』@郑海波.pdf

    组件化开发在Web前端中指的是一种将用户界面分解为独立、可复用、自包含模块的技术。每一个模块就是所谓的“组件”。在面向对象的编程中,组件类似于类,但在Web开发中,组件更强调于表现层的独立性。组件的出现与...

    基于Delphi Web 应用开发.pdf

    综上所述,《基于Delphi Web应用开发》这本书为Delphi开发者提供了全面且深入的学习资源,涵盖了Delphi 7.0中用于Web开发的各种核心组件及其应用场景,非常适合想要在Web开发领域提升自己的开发者们阅读。

    《Extjs Web应用程序开发指南》代码(全)

    《Extjs Web应用程序开发指南》是一本专注于使用Extjs框架进行Web应用开发的专业书籍,而提供的压缩包文件包含了书中各个章节的源代码示例。这些示例代码是学习Extjs框架的重要参考资料,可以帮助读者深入理解Extjs...

    web可视化开发工具

    WebBuilder是一款跨平台、数据库和浏览器的可视化Web应用开发平台。WebBuilder使用了多项最新的技术,使Web应用的开发更快捷和简单。 作为一款高效的Web开发工具,WebBuilder的特色是: .基于浏览器的集成开发环境....

Global site tag (gtag.js) - Google Analytics