如何提高单页应用程序的性能?

5

介绍
我有一个使用BackboneJS构建,具有Rails后端的(大多数情况下)单页面应用程序

由于大部分交互发生在Web应用程序的一个页面上,因此当用户首次访问页面时,我基本上必须从数据库中提取大量信息,进行一次大型深度连接查询。

这导致该页面的加载时间非常长。

load times

新垣曲线似乎告诉我,大部分问题都是由457个单独的快速方法调用引起的。

fast methid calls

现在我已经完成了所有我能做的预加载(我使用了Bullet gem进行了检查),但我仍然有一个问题。 这些方法调用很可能发生在我的Rabl序列化器中,我用它来序列化一堆JSON以嵌入到页面中以初始化Backbone。你不需要完全理解这一点,但可以说它可能会增加457个方法调用。
object @search
attributes :id, :name, :subscription_limit

# NOTE: Include a list of the members of this search.
child :searchers => :searchers do
  attributes :id, :name, :gravatar_icon
end

# Each search has many concepts (there could be over 100 of them).
child :concepts do |search|
  attributes :id, :title, :search_id, :created_at

  # The person who suggested each concept.
  child :suggester => :suggester do
    attributes :id, :name, :gravatar_icon
  end

  # Each concept has many suggestions (approx. 4 each).
  node :suggestions do |concept|
    # Here I'm scoping suggestions to only ones which meet certain conditions.
    partial "suggestions/show", object: concept.active_suggestions
  end

  # Add a boolean flag to tell if the concept is a favourite or not.
  node :favourite_id do |concept|
    # Another method call which occurs for each concept.
    concept.favourite_id_for(current_user)
  end
end

# Each search has subscriptions to certain services (approx. 4). 
child :service_subscriptions do
  # This contains a few attributes and 2 fairly innocuous method calls.
  extends "service_subscriptions/show"
end

看起来我需要采取一些措施,但我不确定应该采取什么方法。以下是我可能有的一些想法:
性能改进思路
简化界面 也许我可以想出一些向用户呈现信息的方法,而不需要实际数据存在。但我不明白为什么一定要这样做,其他单页应用程序(如 Trello)具有非常复杂的界面。
概念分页 如果我对概念进行分页,每次从数据库中提取的数据量将减少。但会产生较差的用户界面。
缓存 目前,刷新页面只会重新从数据库中提取整个搜索。也许我可以缓存应用程序的某些部分,以减少对数据库的访问。但这似乎很混乱,因为我处理的大部分数据都不是静态的。
多个请求 在不将 JSON 嵌入页面的情况下提供页面技术上是不好的,但也许如果我先加载未填充的页面,然后再获取数据,用户会感觉事情发生得更快。

索引
我应该确保所有外键都有索引。我还应该考虑在哪些地方添加索引会有帮助(比如收藏夹?)。

将方法调用移入数据库
也许我可以将视图层中迭代结果的一些缓存放入数据库中,然后只需提取它们而不是计算它们。或者我可以在写入时同步而不是在读取时同步。

问题
有人有关于我应该花时间做什么的建议吗?

2个回答

1
我建议将您的JS代码库分成模块,使用像RequireJS这样的资产加载器进行动态加载。这样,您在加载时不会有太多的XHRs触发。
当需要特定模块时,它可以在适当的时间加载和初始化,而不是每次页面加载时都加载。
如果您使代码稍微复杂一些,每个模块应该能够启动和停止。因此,如果您有任何轮询或执行复杂代码,则可以停止模块以提高性能并减少网络负载。

虽然我同意优化资源传递是提高性能的重要步骤,但我认为这不是我在这里遇到的主要问题。虽然应用程序中有很多JS代码,但它已经被压缩和最小化,并且以约100kb的大小到达。它还应该在客户端缓存,因此对于重复访问者来说,加载成本是最小化的。 - David Tuite

1
这是一个很难回答的问题,因为没有看到实际的用户界面,但我会专注于仅加载所需的初始界面数据。例如,如果用户必须深入挖掘以查看您呈现的某些数据,则可以按需加载该数据,而不是将其作为初始有效负载的一部分加载。您提到搜索可能有多达100个“概念”,也许您不需要最初获取所有这些概念?
总之,听起来您的问题并不真正在客户端上 - 听起来您的服务器端代码正在减慢事情,因此我会探索您可以做些什么来获取更少的数据或推迟复杂查询直到它们绝对需要的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接