当前位置: 首页 > 科技观察

同构JavaScript:Web应用程序的未来

时间:2023-03-16 22:00:03 科技观察

在Airbnb,我们在过去几年中学到了很多关于构建富应用程序的知识。从2011年开始,我们开始通过我们网站的移动版本研究单页应用,特别是在我们正式推出WishLists和我们重新设计的搜索页面之后。它们大多是大型的JavaScript项目,这意味着大部分代码需要在浏览器中运行,这也适合更现代的交互体验。如今,这种方法非常普遍,一些知名的框架(Backbone.js、Ember.js、Angular.js)让开发者可以轻松构建一些丰富的应用程序。我们发现这些应用程序无论如何都存在一些局限性,要了解原因,让我们看一下Web应用程序的历史。JavaScriptGroupUp自从Web出现以来,浏览器就是这样工作的:浏览器会请求一个特定的页面(例如:请求http://www.geocities.com)让服务器响应并生成一个HTML页面并发送itbackoverInternet,这种工作方式在当时已经很不错了,因为当时浏览器还不是很强大,大多数HTML页面都是独立的静态文件。JavaScript的出现可以使网页比仅仅图像幻灯片和日期控件更具动态性。在个人电脑飞速发展的今天,一些牛逼的程序员已经摆脱了Web的限制,浏览器也在不断的进化。现在,Web是一个成熟而强大的应用程序平台,包括快速的JavaScript执行,以及对HTML5标准的支持,供开发人员创建功能强大且丰富的应用程序。在此之前,它只是一个普通的原生平台。单页应用程序很快,开发人员利用了这些新功能并开始使用JavaScript构建整个网站。这些经典的单页应用程序(如Gmail)可以快速响应用户操作,而不是仅仅为了呈现页面而往返于服务器。一些成熟的框架如:Backbone.js、Ember.js、Angular.js通常被讨论为“MVC或MVVM模式”框架,这种经典的MVC模式看起来是这样的:大部分逻辑都在客户端,(视图,模板、控件、数据处理、国际化等)为数据提供处理接口,服务器端可以用任何语言编写,如Ruby、Python、Java等,大部分是提供一个空的HTML页面。下载JavaScript文件后,它们将在客户端执行和初始化,从中获取数据并直接呈现HTML页面。这对用户体验来说非常好,因为一旦应用程序初始化和加载,它可以在页面之间快速切换而无需刷新页面,最好的情况下,它甚至可以启用离线操作功能。这对开发者来说也是非常好的,因为它可以清晰的在“客户端”/“服务”之间划清界限,从而方便整个开发过程,并且可以有效的防止两种语言实现逻辑的重复,因为前端和后端通常是用不同的语言开发的。天堂的麻烦其实无论如何都是有缺陷的,但是我们可以通过一些案例来正确地避免它。SEO一个应用程序如果只运行在客户端,是无法通过HTML“抓取”到它的,所以默认情况下是不能进行SEO(搜索引擎优化)的。通常,我们的爬虫会向服务器创建请求,然后解析结果;但是如果服务器返回一个空页面,那是没有意义的。但这并非没有解决方案。性能是一样的,如果服务器不能直接渲染整个HTML页面,而是通过JavaScript来做这些事情,用户会看到几秒钟的空白页面或者在整个页面加载完成之前一直加载控件。有许多研究表明,用户对访问速度慢的网站反应强烈。亚马逊声称“页面加载速度每增加100毫秒,收入就会增加1%”Twitter40位工程师花了1年时间进行重构,他们的网站(在服务器端呈现页面,而不是在客户端)声称加载时间提高了5倍。可维护性理想情况下,我们希望创建一个层次清晰、低耦合的应用程序,避免前后端有少量应用逻辑代码重复(通常前后端使用不同语言开发)。常见示例,例如日期/货币格式自定义、表单验证、流程逻辑。可维护性一直是设计程序所必需和困难的,尤其是对于复杂的应用程序。一些开发人员,包括我们自己,一直被这些问题所困扰——往往只有真正在单页应用上下功夫,才能了解它的缺陷在哪里。对***的一种混合方式,我们想要一个全面的解决方案:我们想要从服务器端获取整个HTML(高性能,SEO)但是我们也想要让客户端代码运行的快速和灵活。为此,我们尝试在Airbnb构建“同构JavaScript”。这是一个可以同时运行客户端和服务器端的JavaScript应用程序。一个“同构”应用程序看起来像这样,这里称为“客户端-服务器MVC”。在这个世界里,你的应用程序和视图层逻辑可以运行在前后端,这反过来又解决了上面所有的问题——性能优化、良好的可维护性、SEO,以及更多有状态的Web应用程序。有了Node.js,一个在服务器上运行的快速、稳定的JavaScript,我们现在可以梦想它了。通过创建适当的抽象,我们可以在服务器和客户端上运行我们的逻辑代码——这是“同构JavaScript”的定义。野外同构JavaScript并不是一个新想法,Nodejitsu早在2011年就已经对同构JavaScript进行了很好的描述——但它现在才被采用。那里已经有很多同构的JavaScript框架。Mojito是第一个开源的同构JavaScript框架,你可以随心所欲地获取它。它是一个完全用Node.js编写的框架。但是自从他们在2012年4月开源以来,它并没有在JavaScript社区中广泛流行。问题是它依赖于YUI和Yahoo特殊模式。Meteor可能是最同构的项目。Meteor原生支持实时应用程序,团队正在围绕包管理器和开发工具构建一个完整的堆栈。与Mojito一样,它是一个大型的原生Node.js框架,在JavaScript社区中也运行良好,1.0发布版本即将发布。Meteor作为一个项目一直受到密切关注——它拥有一支全明星团队,以及来自安德森基金会的1120万资金——从未听说过哪家公司如此关心开源产品。Asana,是一个任务管理应用程序。有趣的是,它是由Facebook的创始人之一DustinMoskovitz创建的。Moskovitz的身份是世界上最年轻的亿万富翁,Asana花费多年时间开发了他们的闭源项目Luna,这是同构JavaScript***的例子之一。Luna,在Node.js构建于v8cgi之前,它允许每个单独的用户会话复制一个完整的应用程序以在服务器上运行。它为每个用户创建了一个独立的进程,运行在客户端也是服务端的代码,从而实现了整个类的高级优化,比如离线支持即时更新。早些时候我们推出了一个名为Rendrlibrary的同构库,它允许您使用Backbone.js+Handlebars.js构建单页应用程序,也可以在服务器端完全渲染。Rendr是我们正在打造的一款产品,旨在让Airbnb移动网络的响应速度更快。高可用性和响应能力对用户来说尤为重要。Rendr力求成为一个库而不是框架,因此与Mojito或Metetor相比,它解决的问题相对较少,但易于修改和扩展。抽象,抽象,抽象这对于一些大型项目来说往往是非常困难的。客户端和服务端是完全不同的运行环境,所以我们需要做一系列的抽象,把底层的解耦应用逻辑抽取出来,这样我们就可以把一些单独的API暴露给开发者。路由我们想从URI模式路由处理程序中获取一组路由。我们的路由处理程序需要访问HTTP标头、cookie、URI信息和特殊重定向(不是通过window.location或Node.jsreqres)。获取和持久化数据如果我们要描述一个资源,我们需要渲染一个指定的页面,或者通过抓取一个组件。此资源描述符可以是指向JSON数据或更大应用程序的简单URI。通过模型、集合、特定模型类或主键KEY来封装资源很有用。通常这些都是在一些各种各样的解析成一个URI。视图渲染无论我们选择直接操作DOM,还是使用HTML模板,或者操作封装DOM的抽象UI组件生成HTML标记,我们也可以在前后端渲染任何页面,这取决于是否您的应用程序需要了。到目前为止,构建和打包只是成功的一半,在启动和运行应用程序的工作流程中,Grunt和Browserify等工具是不可或缺的。以下是构建的几个步骤:编译模板,包括一些客户端依赖项、应用程序混淆、压缩等。这个简单的示例将所有应用程序代码、视图和模板组合成一个包,但对于大型应用程序来说可能需要几百KB的下载量。最好的方法之一是创建一个动态包并使用延迟加载,无论如何它非常复杂。像Esprima这样的静态统计工具可以让一些有上进心的程序员尝试进一步优化并使用元编程(metaprogramming)来减少代码。ComposingTogetherSmallModules进入市场的同构框架意味着你必须一次解决所有问题,但这将导致一个庞大而笨重的框架,难以推广和集成到现有的应用程序中。既然很多开发者已经解决了这个问题,我们就构建一个轻量级、可重用、可继承的同构程序。事实证明,大多数JavaScript模块无需太多修改就可以实现同构,例如:像Underscore、Backbone这样的流行库。为了演示这一点,我构建了一个简单的应用程序“isomorphic-tutorial”,您可以在Github上下载它。通过组合几个模块,每个模块都是同构的,很容易创建一个只有几百行代码的简单同构应用程序,它使用Diretor为服务器和浏览器提供路由,Superagent提供HTTP请求并使用Handlebars。js作为页面模板。所有这些都是基于Express.js框架构建的。当然,构建一个应用程序是非常复杂的,必须引入更多的抽象层次,但我们希望更多的开发者多尝试,他们会有新的库和新的标准诞生。TheViewFromHere更多的组织已经在他们的产品中使用Node.js,并且不可避免地会有更多的应用程序开始在前端和后端之间共享代码。最重要的是要记住“同构JavaScript”是一个作用域——它从仅共享模板开始,然后管理整个项目的视图层,并继续到大多数应用程序的业务逻辑层。JavaScript代码在前端和后端共享这一事实取决于您的程序设计及其独特的约束。NicholasC.Zakas有一篇很好的文章“HowtomovetheUIlayerfromclienttotheserver”来提高性能和可维护性。应用程序不需要使用Node.js来替换整个后端。这就好比“倒洗澡水把孩子扔出去”。相反,你想创建一个好的API和一个RESTful资源(这里推荐阮一峰的一篇文章,简单介绍什么是RESTful资源)程序。传统后台可以结合Node.js搭建。在Airbnb,我们已经开始使用Grunt和Browerify(一些底层Node.js库)重构我们的客户端。我们的核心Rails应用程序可能永远不会使用Node.js作为替代品,但使用这些工具,我们可以轻松地与JavaScript和模板共享相同的环境。如果您是第一次听说,几年后一些高级Web应用程序将在服务器端运行JavaScript。了解更多如果这个想法让你兴奋,那么你可以来我们的IsomorphicJavaScript工作室看看。11月12日星期三或11月21日星期四在旧金山,我将教您如何在DevBeat上组装同构JavaScript,并告诉您编写同构程序是多么容易。原文链接:http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/翻译链接:http://blog.jobbole.com/51786/