云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

网站空间_腾讯云TCE_限量秒杀

小七 141 0

开源CloudFlare的UI框架

去年底,CloudFlare UI团队做出了一个巨大的决定:将JavaScript框架从骨干网和木偶网改为React&Redux。我们曾经是互联网上最大的主干+木偶应用之一,我们的决定并没有被轻视。在我们的团队中,我们有一个前木偶团队的核心成员(我自己),以及几个流行的主干项目的作者:Backgrid和骨干Paginator。本着开放网络的精神,我们想分享更多关于我们正在做的事情。这首先要开放我们花了几个月时间构建的UI框架。介绍cf ui在迁移到React时,我们采用了现有的主干UI框架,并在React的基础上从头开始重新构建了它。这包括50多个包,其中包括几十个组件、实用程序、测试助手等。示例:https://cloudflare.github.io/cf-uigithub:https://github.com/cloudflare/cf-ui我们并不是开源的cfui,因为我们认为我们的按钮比其他任何人的按钮都好,而是因为这是一个分享我们在构建大型React应用程序时做出的一些技术决策的机会。希望这将是一个可怕的技术资源,许多其他开发人员。我们在cfui中做了一些有趣的设计决策,我们想从多包回购结构开始讨论更多。利用Lerna改善开发体验CloudFlare正在开发几个不同的应用程序:我们的主要仪表板是大多数客户都熟悉的,但也有一些内部和外部应用程序需要我们构建。对于我们来说,能够在存储库之间共享代码是必须的。我们可以将所有共享代码转储到一个存储库中,但我们的应用程序开发速度不同,我们希望能够使用semver对共享代码进行版本设置。所以我们使用npm来构建大量的独立包。然而,在所有存储库中维护几十个包是一个开发噩梦。跨包进行更改是一个困难的工作流,而且很难跨所有包测试更改。使用Lerna,我们能够将所有的包放入一个存储库中,并拥有理想的工作流,同时还可以独立地对包进行版本控制。这里的基本思想是,我们的cf ui存储库如下所示:包装/cf构建卡/cf构建器窗体/...cf util路由处理程序/cf util文本/勒纳.json包.json那么packages/中的每个目录如下所示:包装/cf构建卡/src公司/试验/包.json自述文件.md每一个都被构建到一个单独的npm包中,并在它们发生更改时发布。Lerna的另一个有趣之处在于,它"链接"同一个repo中的交叉依赖项,以便您可以跨所有包测试一个包中所做的更改例如,cf util http poll依赖于cf util http。如果我对cf util http进行了更改,我希望能够测试它是否没有中断cf util http poll,如果更改了,我希望确保两个包都得到正确的更新和版本控制。勒纳允许我们这样做。使用这种多包样式的存储库还有很多好处,这就是为什么许多其他项目选择使用类似的结构。像Babel,React,Ember,Angular,Jest,Meteor,PockDB等项目都做同样的事情。在Lerna网站上阅读更多。生成器组件当我们最初构建UI框架时,我们构建了每个组件包,以公开您组合在一起的多个组件,如下所示:从"React"导入React;进口{表,桌面,桌面单元,桌体,表格行,表格单元}来自"cf组件表";导出默认类MyTableComponent扩展反应组分{渲染(){返回(名称值{此.props.data.map(行=>{行名称}{行值}});}}这显然是一个重复的过程,所以我们需要一些"工厂"组件来为我们设置它。比如:常数数据=[{id:1,名称:'Foo',值:'Foo'},{id:2,名称:"Bar",值:"Bar"}];{返回{id:项目编号,数据:项}}}列={[{label:'名称',手机:(数据)=>{return{数据.名称}}}, {label:'值',手机:(数据)=>{return{数据.值}}}]}/>除此之外,Redux中基础组件的一个令人沮丧的事情就是一直将它们挂接到状态树中。为每个事件设置处理程序以分派操作并使其进入状态是一个令人厌烦的过程。相反,我们定义了这些"构建器"组件可以直接绑定到Redux,并且有它们自己的reducer和action。您所要做的就是在使用builder组件之前设置减速器。从'redux'导入{combineReducers,applyMiddleware,createStore};从'redux thunk'导入thunk;从"cf builder table"导入{tableReducer};const reducer=组合减速器({表格:表格减速器});conststore=createStore(reducer,{},applyMiddleware(thunk));然后您可以像使用其他组件一样使用构建器组件。他们每个人只需要一个唯一的ID,你可以把它存储在组件名称.js常量文件。您还可以分派对构建器执行各种操作的操作。从"cf builder table"导入{tableActions};// ...调度(tableActions.flashRow(ComponentNames.EXAMPLE_表,'罗维德',"成功"));集成测试工具cfui还包括许多与Mocha、Sinon和Redux集成的测试实用程序,以防止编写测试时出现各种错误。例如,使用sinon,您可以在测试中截取一个方法:it('should stub a method',()=>{信噪比(obj,'methodName');// ...});但是如果您忘记恢复存根,或者一个错误导致存根在剩下的测试中一直存在,那么您可能会遇到一些问题。相反,有一个cf test stub包,其中包含一个stubMethod()util,它会在测试之间自动进行沙盒和重置,防止您出错,并使其更易于使用。还有一些其他有用的测试实用工具可以做类似的事情。为了它包装API如果您正在浏览cf ui包,您可能会注意到有一些包,如cf util logger,它将外部api包装成这样:const debug=require('debug');函数createLogger(名称){const logger=调试(名称);返回函数(消息){记录器(消息);};}模块.导出=createLogger;这看起来似乎没有必要,但是它迫使我们公开一个最小的API表面积,这样我们就可以自信地对它们进行更改,甚至可以在不更新应用程序代码的情况下交换底层模块。例如,如果我们决定停止使用marked For卓越或其他一些降价引擎,我们可以在一个代码库中的一个pull请求中这样做。提高组件的可访问性从头开始重写我们的所有组件是一个很好的机会来评估我们是否遵循了可访问性最佳实践。当我们重写组件时,我们发现了一些可以改进的地方,我们花了一些时间来确保组件尽可能容易访问。例如,我们极大地改进了所有组件的键盘导航,甚至开放了一些我们为此而构建的库:react-modal2、a11y focus store、a11y focus scope。最后,我们真的很高兴今天能公开我们的UI框架。我们做了大量的工作,最终能把它展示出来真是太好了,所以请在GitHub上给我们一颗星星(我们爱星星)。另外,如果你对这项工作感兴趣,那么你应该加入我们的团队!