当前位置: 首页 > news >正文

eBay WebRex: 动态web资源优化工具

作者:Lin Xu



摘要

WebRex是eBay开源的Java项目,集成了很多前端开发的优化技术。与同类项目Wro4j和Jawr提供的静态优化不同,WebRex提供了动态优化。它使用定制tag和相对路径来操作管理web应用程序的静态资源。它为eBay这样的大型网站提供了一种有效的资源聚合模式。在eBay内部,WebRex作为基础平台架构的一部分,为web应用程序开发人员自动处理前端优化工作,在eBay的绝大多数应用程序中被广泛使用。

 

为什么我们需要WebRex

首先,通常静态资源优化器使用一个配置文件来管理整个项目的所有静态资源。开发人员需要

1.        列出很多资源文件名和聚合文件(aggregation)名

2.        在jsp文件里使用聚合文件名。

以wro4j为例,开发人员需要在下面的wro.xml里定义很多聚合(Wro4j <group> ),

然后在jsp里面使用这个聚合。对于大型项目,这种配置文件的维护并不容易。随着时间的推移,项目变得越来越繁杂,配置文件也变得越来越繁杂,维护起来变得非常困难。而且,如果要支持项目本地化,有些应用程序的聚合多达上百万。开发人员不知道哪些文件需要被删除,哪些需要被更新,以及各个聚合的使用情况,由此产生很多页面功能错误以及性能问题。WebRex可以很好的解决上述问题。使用WebRex,开发人员不需要维护复杂的配置文件,也不需要查找记住那些聚合,直接使用资源文件即可。

 

如果一些资源有更新或者不再被使用,这些资源就会被自动在聚合中更新或者从聚合中删除,而且在发送请求响应之前,WebRex会自动删除(Dedup)页面中使用的重复资源,以此来减少page weight,加快页面载入速度。

 

其次,WebRex 实现了resource bundle 功能,这个功能粗略看有点类似静态聚合,但实际上它也是动态的,主要功能包括

        i.             提供了整个站点内(比如ebay.com)所有页面共享资源的功能,利用了浏览器缓存来提高页面加载速度。

       ii.             开发人员只需要在页面上指定目标slot。

      iii.             Resourcebundle 可以被定义在一个单独的被共享的共享库里,这样所有的applications都可以使用它。

      iv.             如果要修改目标slot的资源聚合顺序,开发人员只需要在配置文件里做一次性修改。

再次, WebRex 既支持 http 也支持https,在支持本地化L10N方面也非常灵活。在eBay内部,我们支持很多Locales,如果特定Locale有特定资源,开发人员只需要把这些资源放到Locale对应的文件夹(比如META-INF/resources/de_DE/sample/sample1.js),WebRex做聚合时会自动找到目标Locale的特定资源,用户访问页面时,如果locale是en_US,找到META-INF/resources/sample/sample1.js进行聚合,如果locale 是de_DE,找到META-INF/resources/de_DE/sample/sample1.js进行聚合。

 

另外,WebRex的开发中过程考虑和吸纳了很多前端开发的前沿技术,包括业界知名的Yahoo的网页加速最佳实践(best practices of speeding upwebsites)。

 

当然,WebRex是可扩展的,开发人员可以根据自己的项目需要进行扩展,比如上传聚合资源到资源服务器,对于大型项目,开发人员需要扩展使用资源服务器(我们会在以后的文章中重点阐述这部分)。

主要概念

*  聚合(Aggregation)

聚合多个资源文件到一个单独的文件里,这样可以很大程度地减少下载资源的round-trip 的数目,进而提高页面加载速度。

 

*  本地资源和共享资源(Local Resource and Shared/Library  Resource)

本地资源Local Resource: 所有本地web项目里面的资源文件被归为 local resource.

共享资源Shared(Library) Resource: 所有在共享jar包的META-INF/resources 里的资源文件称为 shared(Library) resource.

 

*  资源根目录(Resource Base)

它指定了WebRex从哪个文件夹开始寻找本地资源,是可配的。

对本地资源,缺省的resource base 是 <webRoot>/resources.

对共享资源,缺省的resource base 是 META-INF/resources

 

WebRex首先从本地resource base开始寻找资源,如果没有找到,就会继续从共享资源的resource base寻找。

 

*  资源路径(Literal  Path)

它指的是相对于资源根目录resource base的相对路径,被用来访问资源。

 

*  占位符(Slot)

占位符用来放置和调整聚合资源在页面上的位置. 开发人员可以定义占位符(使用slot tag res:jsSlot or res:cssSlot) ,用来设置resource tag 的target属性的值。

 

主要功能

*  通过resource tag引用资源

例如,为了使用<webRoot>/resources/css/comp.css,我们需要写如下代码,

    <res:useCssvalue="/css/comp.css" target=”head-css”/>

      <res:useCss> resource tag 指定CSS resource type

       "/css/comp.css" 指定资源路径

       “head-css”是占位符

 

在下图里,资源samples1.js和sample2.js被聚合到”page-js”这个占位符,这两个文件会被作为一个聚合文件通过一个http/https请求下载。


*  通过 JAVA API引用资源

例如,

1)      取得聚合结果的URL

List<IResource>iResources = new ArrayList<IResource>(); 

 

//Createresource

iResources.add(ResourceFactory.createResource("/tests/jsTest_sample3.js"));

iResources.add(ResourceFactory.createResource("/js/test1.js"));

 

//Try toget aggregation resource url with current context

Stringurl = ResourceFactory.createAggregatedResource(iResources)

.getUrl(ResourceRuntimeContext.ctx().getResourceContext());

 

2)      向页面上指定占位符加入资源

// GetSample1 JS

IResourceresource = ResourceFactory.createResource("/Sample1.js");

 

//Register resource in "page-js" slot

ResourceAggregatoraggregator = ResourceRuntimeContext.ctx().getResourceAggregator();

aggregator.registerResource("page-js",resource);

 

*  删除(dedup) Ajax response里面的重复资源

例如,在主页面jsp上,有一页面组件被某个js初始化了,随后一个ajax request又下载了这个js文件,这样初始化的代码会被再次执行,引起页面出错。

为了解决上面的问题,我们需要删除被主页面和ajax request都下载的重复资源,实现步骤主要包括,

1)        在主页面生成一个unique dedup "token"。

2)        把生成的token作为ajax request的参数。

3)        把token放在resource context里面。

 

以上步骤的详细代码放在WebRex Github的 sample 项目里。

 

*  Resource Bundle

例如,开发人员认为JQuery.js 和initialize.js 应该被合并到一个文件里,因为大多数页面同时需要这两个文件,那么开发人员可以编辑/WEB-INF/webrex/resource_bundles.xml 添加以下配置,

<bundles>

    <bundle id="common-js">

        <resourcepath="/js/thirdparty/jquery/JQuery.js" />

        <resourcepath="/js/common/initialize.js" />

    </bundle>

</bundles>

 

panel.jsp file, 引用 bundle common-js.

JSP code:

<body>

...

<res:bundleid="common-js"></res:bundle>

...

</body>

 

页面输出output,

<body>

...

<script src="/ressvr/v/tmj5hmooge5n1b4ioh3igyoymin.js?debug=true&showRaw=true"type="text/javascript"></script>

...

</body>

在上面的output里,Jquery.js 和Initialize.js被聚合到一个slot,这个slot就是在JSP里面<res:bundleid="common-js"></res:bundle>所在的位置。


WebRex主要工作原理

1)        当JSP页面执行时,WebRex 会根据当前页面使用的resource tag构建一个usage model。

2)        WebRex为每个resource tag和slot tag生成一个resource marker 比如 ${MARKER:css}

3)        页面render完成后,resource usage model也构建结束,不同slot的聚合也生成了。

4)        JSP执行后,resource RequestFilter 会处理HTTP response,扫描输出HTML里面所有的marker,同时用最终聚合结果替换marker.

 

支持的资源类型

https://github.com/eBay/WebRex/blob/master/WebRex/src/main/resources/com/ebayopensource/webrex/resource/mimetypes.properties

 

Github 以及更多信息

https://github.com/eBay/WebRex

 

讨论社区Community

https://groups.google.com/forum/#!forum/webrex 

 

 


相关文章:

  • MapOutputBuffer理解的三重境界
  • Druid at Pulsar
  • AngularJS渲染性能分析
  • Ebay开源基于大数据的可视化框架:Pulsar Reporting
  • JavaScript 异步原理
  • 从数据仓库到数据视图
  • Griffin – 模型驱动的数据质量服务平台
  • 细数Kubernetes Service那些事-kubernetes 服务发布以及在eBay的实践
  • TCP BBR拥塞控制算法解析
  • React同构漫谈
  • 基于PWA的异步监控
  • 从dedup说起之JS数组去重
  • java中怎么把一组数字的变量赋值给数组_写给小白看的入门级 Java 基本语法,强烈推荐...
  • 去哪儿网查不到历史订单_前端vue 2.5 去哪儿(慕课网Dell Lee视频教学) 项目实战视频...
  • 一致性分析_一致性哈希算法的分析与实现
  • 2019年如何成为全栈工程师?
  • Android Volley源码解析
  • Apache的基本使用
  • Java 网络编程(2):UDP 的使用
  • Javascript弹出层-初探
  • leetcode-27. Remove Element
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Redux 中间件分析
  • uni-app项目数字滚动
  • Vue小说阅读器(仿追书神器)
  • webpack+react项目初体验——记录我的webpack环境配置
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • WePY 在小程序性能调优上做出的探究
  • 从伪并行的 Python 多线程说起
  • 记一次和乔布斯合作最难忘的经历
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 使用Gradle第一次构建Java程序
  • 阿里云服务器如何修改远程端口?
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #NOIP 2014# day.2 T2 寻找道路
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • $.each()与$(selector).each()
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (转)负载均衡,回话保持,cookie
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET 材料检测系统崩溃分析
  • .net操作Excel出错解决
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • /*在DataTable中更新、删除数据*/
  • @Controller和@RestController的区别?