译注:原来的标题是:“我们为啥不用AngularJS:…”,后来作者觉得不妥就改掉了,因为AngularJS是通常适用于单页面程序框架(SPA) 很多人理解为对AngularJS的抨击,但这并不是他的本意。
几个月前,当我们打开Sourcegraph网站的时候,它是一个富AngularJS应用,服务器只要把原始HTML和JSON endpoints返回,剩下的就交给Angular来搞定了。我们就这样懵懵懂懂地做出了最初版本的Sourcegraph。
但是单页(single-page) JavaScript框架并不适用于每一个站点。Sourcegraph就是一个内容为主的站点,我们渐渐发现这个富js应用的开发还是弊大于利;下面是我们在探知这条路上遇到的沟沟坎坎,希望对有雷同遭遇的开发人员一些帮助。
下周,我们来讨论更多地关于我们是如何从AngularJS迁移server-side GO templates
客户端JS框架的5个弊端
我们早就知道这会有很多的困难,但是不知道到底有多难
1. 搜索排名和Twitter/Facebook预览
搜索引擎爬虫和社交网站的预览抓取器不能加载纯Javascript站点,而如果提供替换版本又慢又复杂
有两种方法可以允许爬虫阅读你得站点。你可以在服务器端运行一个浏览器实例用以执行你的应用里的Javascript,然后返回HTML结果(PlantomJS或者WebLoop)。 或者你可以为你的站点专门建立一个HTML版本为爬虫服务
***个方法需要你为每一次页面加载建立一个headless浏览器(或者tab),比起直接产出HTML,这样会花费很多的时间和系统资源。基于你用的框架,会花费很多的工作来决定什么时候已经准备好的页面将被渲染。 你可以缓存页面,但是如果页面经常改变,不但优化甚微而且会增大复杂度。
这样做还会降低你的页面加载速度好几秒,对搜索引擎排名也不利。(PlantomJS需要Xvfb和WebKit)
第二个方法(做一个服务器端站点)对简单地站点有效,但是如果页面很多,那用这个方法就形同噩梦。
如果Google认为你的服务器版本站点跟你的主站版本有很大的不同,那他就会狠狠的惩罚你,到时候你连怎么死的都不知道
2. 不可靠的统计和监控
很多分析工具需要易于出错,人工集成来使用HTML5 history API(pushState)用于导航。因为他们很难自动检测到你的应用使用pushState导航到了新的页面。即使可以做到,他们仍然需要等待你应用里的信号来收集新页面的信息
如何解决这个问题呢?取决于你的客户端用什么导航和你想集成什么分析工具。用Google分析+Backbone.js?尝试一下backbone.analytics。用Heap(顺便说一下,太酷了)和UI-Router?设置你自己的$stateChangeSuccess并调用heap.track
还没完事呢!你想追踪起始页面加载?也许你在双向跟踪他?你会跟踪失败的页面记载吗?如果你使用replaceState代替pushState呢?如果你错误的配置了分析挂钩或者属于检查导致依赖升级搞坏了事情。当你发现的售后,很难去恢复你错过的分析数据(或者消除重复数据)
3. 又慢又复杂的构建工具
前-后端JavaScript构建工具,比如Grunt,需要复杂的配置而且很慢。还好我们有像ng-boilerplate这样的project来帮我们做配置,但是如果你想添加一个自定义的步骤还是逃不出又慢有复杂的怪圈(我为什么说Grunt复杂,看看这个配置文件就知道了)
一旦你配置好了你的应用,你仍然要忍受漫长的JavaScript构建时间。你可以把dev和production构建通道分开来提高开发速度,但是始终免不了走这么一遭,用AngularJS尤其如此,他需要在丑陋的代码前使用ngmin(如果你用了这个功能)。其实,Sourcegraph因为这些丑陋的JavaScript表现代码几度被毁
还好,Gulp已经有了极大的提高
4. 慢,不可靠的测试
测试JavaScript-only的站点需要使用基于浏览器的测试框架,比如Selenium,PhantomJS,或者WebLoop。安装这些(除了PhantomJS)通常意味着安装WebKit和Java依赖,配置Xvfb(机关新的PhantomJS移除了这些先决条件),或者运行一个本地的VNC客户端和服务器来测试。***,你还需要在持续集成的服务器上设定所有东东
相反,测试服务器端产生的页面通常只需要类库来或者URLs并解析HTML,安装和配置起来简单许多
一旦你开始写浏览器测试,你必须处理异步加载。你不能在页面还没有加载的时候就测试页面上的元素,但是如果在一个特定时间端里没有加载,你的测试就会失败。浏览器测试类库提供了很好地功能来处理这种情况,他们只能在负载的页面里使用这些功能
如果你想联合重量级浏览器来进行(Selenium,加上Firefox或者Webkit)很复杂的测试(因为浏览器的异步特质)?你的测试需要很多配置,很长的时间来执行,而且很不可靠
5. 慢,可以缓解,但没有解决
在富JavaScript应用中,页面转化几乎是瞬间发生,然后所有的特定元素异步加载。在server-side应用中,完全相反:页面在服务器端加载完成前不会发送到客户端
听起来似乎是client-side应用胜利了,但是也许会是个坑也不一定
当用户点击一个链接,client-side应用会立刻加载页面并呈现。如果用户用sidebar导航到一个需要5秒钟才可以加载的页面。***次感觉很快,但是如果一个用户需要的信息在sidebar里,对用户来说就感觉很难受。即使你需要的特定内容立即呈现,你仍需要忍受加载指示器和页面填充后的抖动
我们来考虑如果开发人员想在那个页面添加新功能。是很难让她的功能必须快速加载的-因为都是异步的,所以谁会在意页面底部过了几秒才加载呢?如此反复几次,整个站点让人感觉滞后很抖动
在server-side 应用中,如果一个API调用很慢,整个页面就会停滞直到彻底完成。这个不容忽视的server-side慢节奏很容易被测量并会公平地影响每一个人。但是在client-side应用中很容易被忽略
你可以说,一个好的开发团队应该避免这些错误,并且client-side JS 框架不是罪魁祸首。是的,client-side JS框架提高了速度。这一点改变鼓励了任何开发团队
下一步?
上面说得都不是大问题。我们已经做了很多来减轻上述情况。
总而言之,上述种种以为这client-side JS 框架加大了我们开发的负担。
而且要记住,每一个站点都是不同的。Sourcegraph是一个内容站点,他得页面在加载后不会有太多的变化(相较于富JS应用),我们依然爱着浙西技术,但是他们不一定是构建主站点的正确工具。
原文链接: Sourcegraph 翻译: 伯乐在线 - 蔡蔡