Angular JS Scaling&性能

时间:2013-07-15 14:15:41

标签: html5 performance angularjs angularjs-scope angularjs-ng-repeat

我们正在为我们正在为银行建立的Angular应用程序冲击性能问题。

不幸的是,显示代码片段是违反合同的行为。无论如何,我可以描述一些正在发生的主要问题,我希望可以推荐最佳实践。

应用程序结构:

  • 基本上是一个巨大的多表格页面。
  • 每个表单都是它自己的部分,嵌套控制器和部分约3层深。
  • 在json对象的集合上重复相同的形式。
  • 每个表单都绑定到重复的对象/模型。
  • 我们应该支持页面上的1-200个表单。

如果你看一下时间表。我们花了很多时间在jQuery解析html方法,jQuery重新计算stye方法,GC事件(垃圾收集)。我想最小化这些应该可以加快速度。它们都是Angular生命周期的一部分,但可能有更好的方法来避免它们。以下是探查器的一些截图:

Recalculate Style GC Event

最终,随着重复表格的数量超过5,应用程序缓慢。每个表单与其他表单相对无关。我们试图不在表格之间观看任何共享属性。

9 个答案:

答案 0 :(得分:21)

您需要创建自定义指令,以便使用angular来抑制性能问题。与ember angular不同的是,所有铃声和口哨都打开了,你可以自己调低音量。以下是我为帮助您而制定的一些指令。并非您的应用中的所有数据都需要双向数据绑定,因此您可以通过在需要的页面中放弃监视表达式来节省宝贵的CPU功率。所有这些指令都会将数据绑定一次而不管它。

https://gist.github.com/btm1/6802599

https://gist.github.com/btm1/6802312

https://gist.github.com/btm1/6746150

上面的答案之一谈到ng-repeat有巨大的性能命中,所以我给你“set-repeat”一次性数据绑定重复指令:)

答案 1 :(得分:8)

如果没有关于您的问题的更多信息,很难提供解决方案,但我最近经历过(和解决)a performance issue可能与您看到的类似,并且与$ digest循环无关。

您将发现的大多数有关angularjs性能的讨论(包括excellent post from Misko)都与脏检查和$ digest循环的性能有关。但这不是您可以使用angularjs遇到的唯一性能问题。第一步应该是确定摘要周期是否是您的问题。为此,您可以使用batarang,或只是查看您的应用程序,并确切地说它是缓慢的。当摘要周期很慢时,基本上与UI的任何交互都会很慢。

OTOH,你可以拥有一个具有快速摘要周期的应用程序,只有在加载,切换视图或以其他方式更改要显示的组件集时才会很慢,这可能会在分析过程中显示大量时间HTML和垃圾收集。在我的情况下,这是通过对html模板进行预先计算来解决的,而不是依赖于ng-repeat,ng-switch,ng-如果无处不在。

我在小部件中使用了ng-repeat ="小部件"包含窗口小部件类型的ng-switch,以显示任意一组窗口小部件(自定义自包含指令)。用代码替换它以生成特定小部件集的角度模板,加速路由从~10s切换到几乎瞬间。

您可以在上方查看google网上论坛,了解我如何解决我的特定问题的更多信息,或者如果您需要一些具体的建议,请提供有关您的应用的更多信息。

答案 2 :(得分:4)

为了提高生产性能,请阅读以下非常好的单线:

引用AngularJS文档:

默认情况下,AngularJS将有关绑定和作用域的信息附加到DOM节点,并将CSS类添加到数据绑定元素:

由于ngBind,ngBindHtml或{{...}}插值,绑定数据和CSS类ng绑定附加到相应的元素。

如果编译器已创建新范围,则范围和ng-scope或ng-isolated-scope CSS类将附加到相应的元素。然后可以通过element.scope()和element.isolateScope()访问这些范围引用。

Protractor和Batarang等工具需要运行此信息,但您可以在生产中禁用此信息,以便在以下方面显着提升性能:

myApp.config(['$compileProvider', function ($compileProvider) {
  $compileProvider.debugInfoEnabled(false);
}]);

您可以阅读更多详情here

答案 3 :(得分:3)

通常,如果有超过2000个数据绑定处于活动状态,AngularJS将表现不佳,即范围中的2000个项目每个$摘要周期都被检查脏。因此,Ng-repeat对性能有很大的影响;每个重复的项目至少设置两个绑定,不包括项目中使用的任何其他数据或指令。

AngularJS背后的开发人员之一给出了脏检查细节的精彩描述,以及它在这个SO答案中的表现:

https://stackoverflow.com/a/9693933/179024

该答案下面的评论帖是值得一读的,我也会在同一页的答案中分享一些关于它的想法:

https://stackoverflow.com/a/18381836/179024

答案 4 :(得分:2)

很抱歉将它作为'答案',因为我还没有足够的分数来发表评论。

我们的AngularJS应用程序遇到了类似的问题。使用'batarang'似乎必须处理大量的范围对象,并且它们相关的$ watch表达式会产生性能打嗝。这让我们想知道是否应该使用另一个框架或类似ReactJS的东西来处理“视图”部分。

答案 5 :(得分:2)

尝试避免以下

  1. 如果您的元素超过50个,请避免使用ng-repeat 一次列表并避免手动手表
  2. 不要盲目使用ng-click,ng-mouseenter,ng-mouseleave等鼠标事件直到它是一个迫切的需要,尝试通过使用$ event对象以及js的事件传播概念来减少它们的数量

  3. 尽可能使用范围。$ digest而不是范围。$ watch,这确保了摘要周期仅在子范围内执行

    1. 尝试嵌套作用域,即一个父控制器中的一个或两个控制器,并将可重用逻辑保留在父控制器中,我在使用Ui-router时在嵌套状态下使用它(以满足需要更改URL而无需刷新页面的请求)
    2. 最重要的!从HTML中删除所有过滤器!

      以上所有内容都会在应用程序的所有范围内触发摘要周期,因此即使视图已经渲染为角度也很有可能再次执行无情的摘要循环

答案 6 :(得分:1)

将DOM操作移动到自定义指令和使用大量$ watch的$ watch问题之间的中间点是使用“bind-once”语义。

这对于数据可用时不可变的数据非常有用。见bindonce

答案 7 :(得分:0)

这只是一个链接!这只是我读这篇文章时的一个想法,我还没有探索过这个想法,但是有人可能这样做了,我等着他的回答我的想法。如何使用共享Web工作程序从ui线程中获取大量繁重的处理? https://github.com/h2non/sharedworkers-angular-poc

我的另一个想法是更简单的想法。您的应用会受益于无限滚动吗?我的意思是这些形式可能不适合在屏幕上,它们没有相互连接,所以为什么不在需要时绘制它们呢?将它们装入内存然后相应地绘制它们。

答案 8 :(得分:0)

就像在任何其他性能优化中一样,了解如何分析应用程序以找到真正的瓶颈非常重要。然后你可以逐个解决它们。我通常按​​以下顺序对抗瓶颈:

  • 我的javascript代码
  • 在每个空闲摘要周期上运行的角度表达式(复杂观察者和过滤器)
  • 角度构造(ng-repeat,复制对象以进行摘要循环)

我已逐步展示了一个有角度的示例,展示了如何识别每个步骤的瓶颈。 http://bahmutov.calepin.co/improving-angular-web-app-performance-example.html