我们决定如何优化图像-在此过程中,我们重新设计了网站,管理面板和界面方法

Meduza技术总监Boris Goryachev报告。



我们的主要产品-网站-不断获得新功能,但是正因为如此,它逐渐变得越来越困难和笨拙。因此,我们的技术部门会不时忙于使其变得越来越方便。







影响几乎所有网站(尤其是媒体网站)加载速度的主要因素之一是图像。Meduza上有很多图片,这是编辑者讲故事的一种宝贵方法。我们的摄影服务要求可以表述为:



  • 图片必须尽快上传到CMS(我们称为“监视器”)
  • 图片必须保持美丽并在所有平台上看起来都不错
  • 读者不必等待该图像加载




第一种方法



当我们在2014年推出时,处理加载到Monitor中的图像的过程看起来像这样:使用Paperclip和Imagemagick将文件加载到Rails应用程序中,它清除了元数据,并以选定的质量进行压缩(对于JPEG约为75),并且分为三种尺寸:手机尺寸较小,平板电脑和大屏幕手机尺寸较大,计算机尺寸较大。切片的文件与原始文件一起放置在AWS云存储中。它们不是直接从AWS提供(和提供)的,而是通过我们的CDN(将其缓存在其边缘服务器上)提供的。



然后,为网站和应用程序生成JSON的API,除了简单的属性(例如材料的标题)外,还提供了大量的HTML代码,这些代码已插入材料的“内容”部分,并以CSS样式进行了加权。这样,所有客户端的API本身都是相同的:站点,应用程序和支持服务,例如RSS和搜索。







我们立即清楚地知道,这种方法不能经受时间的考验,但是有必要快速启动,检验大量的假设,进行实验并生存下来。我们有意识地-至少我们相信它-选择了“拐杖”,而不是代码和解决方案的美。时间流逝,我们的观众和我们的产品不断增长。随之而来的是,编辑的胃口也增加了。编辑们希望在他们的资料中有越来越多的技巧和“技巧”。同时,设计当然也发生了变化。



技术部门必须修改图片的样式,显示图片的方法,尺寸-图片随着网站设计和新元素的变化而变化。我们添加并支持了越来越多的奇怪解决方案。



这是其中之一




随着时间的流逝,Monitor越来越激怒了遇到它的每个人:编辑人员遭受了bug的困扰,因为修复这些bug花费了很多时间,开发人员非常生气,而且发明架构的局限性不适合老板-我们无法快速开发产品。



我们开始重新制作Monitor。我们重写了CMS的主要部分,该部分负责处理材料大约一年,通常会因旧版本中的错误而分心。然后,一个内部模因出现在“ Meduza”中:“它将出现在新的Monitor中。” 这是我们回答大多数编辑人员要求的方式,尽管当然,我们在旧的和新的CMS中同时进行了一些操作:现在是不好的版本,以后是好的版本。



我很快将在我们的博客中写一篇单独的文章详细介绍“监视器”的更改



重新开始



重新启动并重建整个Meduza之后,API的格式保持不变,但不再由CMS本身形成,而是由单独的服务处理。最后,我们决定将API分为几种-针对不同的客户端。



我们决定从移动应用程序开始。到那时,他们已经对设计,用户体验和工作速度提出了疑问,因此我们整理了应用程序,并按照iOS和Android开发人员的要求制作了API。



在分离API之前,我们通过WebView显示了资料的内容部分,因此我们不能仅在应用程序中或网站上显示某些内容-所有内容都可以在任何地方显示。现在,我们有机会更灵活地管理内容:仅将所需内容发送到移动应用程序,以不同的方式显示重元素(例如YouTube视频插入),最后创建“延迟加载”,这使您可以将重元素逐渐加载到素材中-图片和嵌入。



在分离了应用程序之后,我们集中于该站点。至此,已经决定不对现有站点的代码进行更改,而是从头开始编写所有内容(是的,我们参与了一个持续了一年多的项目)。同时,我们的技术总监被替换,在我的新职位上,我不得不审核项目,决定可以关闭的项目,并与上级进行协调。尽管遇到了种种困难,团队还是决定完成新站点。但是在那之前,我决定我们需要另一个项目。



这就是美杜莎的UI套件的出现方式



为了灵活地传递内容,必须采用最适合转换的形式。内容单元的语义边界-图片,文本段落,标题-应该很好地对齐。内容不应太简单或太复杂。如果它很复杂,则很可能具有多个含义。如果它太简单,很可能在使用它时,您将不得不使其复杂的逻辑负担,而当您需要重用这种单元时,则必须将其复制到项目代码的不同部分。



美杜莎的游戏为例...它们使您可以通过有趣的方式讲出大量故事。它们可以专门针对日程安排,也可以应广告客户的要求制作。或者可以根据所谓的“机制”(即反复使用的格式(例如,这些是测试))制作游戏。



Meduza上的游戏:我们如何设计,制作和重复使用

这些游戏的代码并不位于网站的代码中。它们每个都是作为单独的微服务创建的,通过iframe嵌入到网站中,并通过postMessage与网站本身进行通信。而且该网站并不真正在乎游戏将在哪里展示。此外,游戏本身应在视觉上与现场不可分割:版式和界面元素应相同。







刚开始制作游戏时,我们复制了样式,按钮和其他内容,当然它很快,在外观上还不错,但在内部却很糟糕。



团队决定应对此进行更改。我们暂停了网站的通信,并开始制作自己的UI工具包-一个包含所有重复元素和样式的库。我们尽量不要错过长远的眼光:网站,游戏和机制-一切都必须开始使用相同的库。



网上的所有Meduza项目都是用React编写的,UI-kit是一个npm模块,可以插入我们现在开发的几乎所有内容。当开发人员需要渲染某些东西时,他会编写如下内容:render blocks。







它有什么作用?



  1. 前端开发人员不会完全考虑如何渲染某些内容。
  2. 设计部门已经审查了所有内容。
  3. : UI-kit, , , . , «», .
  4. — - UI-kit ( ) .


UI-kit



有两部分组件:内容和前端。后者是非常简单的React组件,例如按钮和图标。











内容组件稍微复杂一点,但是仍然非常简单,React组件的样式代表一个内容单元。例如,这就是段落组件的样子:







一个“捕捉”简单块







的组件这是一个呈现图片的组件:







站点从中获取数据API,每种材料内部都包含一个最终通过UI-kit“呈现”的组件数组。 ... 在游戏中,一切工作原理相同,只是将数据转到其API版本。



万岁,我们已经重新启动!



下图显示了平均页面加载时间。这是一个非常不精确的指标-考虑了所有设备上的所有页面-但即使它也给出了趋势的想法。







该图显示了站点速度在整个Meduza存在中如何变化。当我们在2014年首次推出一个非常简单的网站时,速度非常快。但是,当我们开始添加新功能时,下载速度下降了。



这是相同的时间表,只是最近两年。它显示了站点重新启动后页面加载时间如何减少。







然后是时候拍照了。



图片



然后是处理图像的方案。图片通过API传递,其地址类似于/images/attachments/.../random.jpg文件本身是通过我们的CDN从AWS云存储中提供的。







我们对新系统的要求如下:



  • 该解决方案应使我们能够快速更改所发送图像的大小和质量
  • 不一定要贵
  • 它必须能够处理很多流量


我们正在努力的方案就是这样。后端将生成一个URL,该URL将由客户端-浏览器或应用程序选择。该URL将包含有关所需图像,图像质量和大小的信息。



如果此URL上的图片已经在边缘服务器上,则将立即将其提供给客户端。否则,边缘服务器将“敲响”下一个已经将请求传递给服务的服务器。接收到图像URL的该服务将对其解码,并确定原始图像的地址以及对其进行操作的列表。之后,该服务将为转换后的图像提供服务,以便将其存储在CDN中并根据请求提供服务。







Meduza已经有类似的解决方案。例如,我们类似地在社交网络上为我们的素材和游戏片段制作图片-在此服务中,我们通过Headless Chrome拍摄HTML页面的屏幕截图。



这项新服务原本应该能够处理图像,应用简单的效果,快速而灵活。由于我们喜欢自己编写所有内容,因此最初计划以Elixir语言编写这样的服务。但是团队中没有人有足够的时间,当然也没有人渴望进入jpg,png和gif的奇妙世界。



我们仍然需要找到一个可以压缩图像的库。我们已经经历过的Imagemagick并不是最快的解决方案,但至少我们知道如何烹饪。其他所有内容都是新的,还有很多需要检查的地方。



我们还需要支持webp图像格式。



随着时间的流逝,我们在精神上做好了自己的准备,以沉浸在这个项目中。但是随后,我们的一位程序员阅读了有关imgproxy库的信息,该库Evil Martians的人上传到Open Source的 根据描述,这是一个不错的选择:Go,Libvps(一个现成的Docker映像),通过Env进行配置。在同一天,我们将库部署在笔记本电脑上,并要求DevOps也使用它。他的任务是提出服务并尝试终止该服务-因此我们将了解它可以承受服务器上的负载。在这段时间里,后端团队继续在他们的计算机上玩这个项目:我们编写了Ruby脚本并掌握了可用的功能。







当DevOps返回该库可以用于生产的结论时,我们收集了通过imgproxy传递的大量图像-我们主要对webp感兴趣-并采用了其照片指令。技术部门的员工无法自行决定这种质量是否适合我们。照片编辑人员向我们发送了他们的评论,我们进行了一些调整,确保图像不会太大,然后编写了后端代码。



在这里,一切都变得非常简单:由于在该站点的API版本中,图像已经被组件与其他组件分隔开了,因此我们只需扩展其JSON并添加不同大小和格式的其他地址。











更新后的版本立即投入生产,因为我们没有进行任何更改,只是添加了内容-前端人员可以在相同版本的API中开发所有功能。他们在功能方面扩展了图像组件,添加了不同大小的图像集,并为Safari提供了特殊的“拐杖”。我们几次更改了尺寸表,并通过编辑部的眼睛检查了结果-为此,我们为她提供了该网站的当前版本以及一个带有新图像的副本以供审核。



当评论停止出现时,我们终于进行了部署,删除了缓存并开始投入生产。



输出量



我们变更的实质可以概括如下:我们将以哪种形式给出决定的决策位置转移到更好地考虑上下文并且易于实施和支持的位置。



现在,您在Meduza上看到的几乎所有图片都是imgproxy的作品的结果,并且在每种情况下,它们的大小和质量有时都不同。这由响应API服务知道的上下文(内容是在Web,移动应用还是AMP上打开)确定。



All Articles