在几毫秒内渲染一个复杂的 Web 应用程序需要什么
dev.to主页上有很多事情要做,特别是当您登录时。我们会加载热门社区帖子、与您关注的标签和用户相关的热门帖子、每个帖子的反应和评论数量、有关热门标签的信息、您关注的标签、您的个人资料图片,当然还有与您可能采取的操作相关的所有应用程序代码。
而且我们做得非常快。
我们相信,网络对于所有用户来说,都能够实现几乎即时的体验。起初,我的想法是“我们只是提供博客文章服务,当然可以做到即时”。但随着平台的不断发展,我们需要投入更多创造力,才能真正实现即时体验。
那么呈现即时主页需要什么呢?
为了将请求尽快渲染到全球各个角落,HTML 请求直接由 Fastly CDN 节点处理。因此,如果您位于纽约市,您的页面将从纽约市获取;如果您位于东京,请求将到达东京服务器。如果您位于埃及,您的请求将来自迪拜。运营和优化全球 CDN 超出了我的专业范围,因此我通常从 CDN 提供的抽象角度来思考。
这种方法的一个问题是我们需要保持缓存内容的高命中率,但我们不知道您在初始请求时是谁。我们使用标头来了解您是否登录,这有助于我们为您组织初始页面并简化一些逻辑;但当然,缓存每个唯一登录用户是不合理的。因此,我们会发出二次 ajax 请求以提供自定义数据。当您在页面上看到与您相关的个人资料图片或信息时,它是在初始页面加载后加载的。有时这会带来延迟,我们一直在努力解决这个问题,但典型的体验是稳定的。
为了尽可能优化您的体验,我们会在可用时将您的部分信息存储在本地。因此,您在导航栏和主页上的个人资料图片、您关注的标签以及其他一些信息都会存储在您的浏览器中,因此无论网络状况如何,这些信息几乎都能立即呈现。我们仍然会每次向源服务器发出请求,以再次检查并确保信息的新鲜度。与不采用此方法相比,这种方法可以使典型请求的速度大大加快。
正如我之前所写,消除渲染延迟的一大关键在于内联样式并使所有 JavaScript 异步化。这对于提供卓越的体验至关重要。这个决定是不久前做出的,效果非常好。
我们过去在每个页面上都采用这种方法,但后来我们改进了我们的方法。
内部导航
虽然内联样式对于确保传入流量获得良好体验是一个不错的选择,但每次内部导航时都发送这些数据并非最佳选择。我们使用一种基于 XHR 的内部导航形式,类似于Turbolinks,但规模更小,且更加定制化。这提供了极致性能的单页应用体验,但大部分逻辑都保留在服务器上,我认为这在保持代码简洁易维护方面是一个很大的优势。
因此,我们只在非内部导航触发的请求中内联样式。更进一步,我们还停止了发送导航栏或页脚。这样您就只能看到页面的核心内容。然而,后端开发人员无需为此感到压力。他们只需知道,我们不能在不同的页面上使用不同版本的导航栏(除非在客户端调用特殊代码来实现)。这意味着内部页面请求的大小通常在 4-8kb 左右。这里也有一些例外情况,例如包含大量评论的页面,但我们也会解决这个问题。
渐进式 Web 应用
接下来的工作重点是集成一些更新的 API,以进一步改进这些方面。我们的缓存优先架构已做好准备,充分利用这些功能,我对此感到非常兴奋。我们最初的努力是提升所有浏览器的性能,无论浏览器功能如何,这为我们充分利用这些前沿 API 奠定了良好的基础,这些 API 在浏览器覆盖率不断增长,整体上也日趋成熟。
综上所述
我尝试运行了一些渲染测试,比较了dev.to和twitter.com,结果 Twitter 的渲染速度始终没有停止。我等了七分钟,测试却迟迟没有停止。如果这篇文章能说明什么的话,那就是我实在没有耐心等下去了。所以我现在就直接发布吧。我不得不根据我现有的证据进行推断,假设我们的网站速度要快得多。
当然,我知道 Twitter 的产品要复杂得多,他们承载的流量也比我们多得多。所以我并不是想吹嘘他们的工程水平,但对于任何单个用户来说,他们承载的流量总量并不重要。个人用户仍然会根据实际情况来衡量用户体验。用户体验至关重要,而性能是浏览器用户体验中最重要的因素。
快乐编码 ✌ï¸
文章来源:https://dev.to/ben/what-it-takes-to-render-a-complex-webapp-in-milliseconds