原文地址:https://medium.com/airbnb-engineering/react-native-at-airbnb-the-technology-dafd0b43838
React Native at Airbnb: The Technology
This is the second in a series of blog posts in which we outline our experience with React Native and what is next for mobile at Airbnb.
React Native itself is a relatively new and fast-moving platform in the cross-section of Android, iOS, web, and cross-platform frameworks. After two years, we can safely say that React Native is revolutionary in many ways. It is a paradigm shift for mobile and we were able to reap the benefits of many of its goals. However, its benefits didn’t come without significant pain points.
这是一系列博文中的第二篇,我们在这篇博文中概述了我们在React Native方面的经验,以及Airbnb在移动方面的下一步经验。
React Native本身是Android,iOS,Web和跨平台框架的一个相对较新且快速移动的平台。 两年后,我们可以放心地说,React Native在很多方面都是革命性的。 这是移动设备的典范转变,我们能够从众多目标中获得收益。 然而,它的好处并非没有重大的痛点。
What Worked Well
好的方面
cross-platform
The primary benefit of React Native is the fact that code you write runs natively on Android and iOS. Most features that used React Native were able to achieve 95–100% shared code and 0.2% of files were platform-specific (.android.js/.ios.js).
跨平台
React Native的主要优点是您编写的代码可以在Android和iOS的设备上原生的运行。 大多数使用React Native的功能都能够实现95-100%的共享代码,0.2%的文件是特定于平台的(* .android.js / *。ios.js)。
Unified Design Language System (DLS)
We developed a cross-platform design language called DLS. We have Android, iOS, React Native, and web versions of every component. Having a unified design language was amenable to writing cross-platform features because it meant that designs, component names, and screens were consistent across platforms. However, we were still able to make platform-appropriate decisions where applicable. For example, we use the native Toolbar on Android and UINavigationBar on iOS and we chose to hide disclosure indicators on Android because they don’t adhere to the Android platform design guidelines.
统一设计语言系统(DLS)
我们开发了一种名为DLS的跨平台设计语言。 我们拥有Android,iOS,React Native和每个组件的Web版本。 拥有统一的设计语言可以编写跨平台功能,因为这意味着设计,组件名称和屏幕跨平台保持一致。 但是,我们仍然能够在适用的情况下做出适合平台的决策。 例如,我们在Android上使用原生工具栏,在iOS上使用UINavigationBar,我们选择在Android上隐藏显示出来的指示器(discosure indicators),因为它们不符合Android平台设计指南。
We opted to rewrite components instead of wrapping native ones because it was more reliable to make platform-appropriate APIs individually for each platform and reduced the maintenance overhead for Android and iOS engineers who may not know how to properly test changes in React Native. However, it did cause fragmentation between the platforms in which native and React Native versions of the same component would get out of sync.
我们选择重写组件,而不是包装本地组件,因为为每个平台分别制作适合平台的API更加可靠,并减少了可能不知道如何正确测试React Native中的更改的Android和iOS工程师的维护开销。 但是,它确实会导致同一组件的naitve和React Native版本不同步的平台之间出现碎片。(我的理解是RN的支持比如是iOS 10,但此时iOS11出来后废弃了一些东西,又添加了一些东西,那这些未适配的东西,就会使得代码变的碎片化)。
React
There is a reason that React is the most-loved web framework. It is simple yet powerful and scales well to large codebases. Some of the things we particularly like are:
- Components:React Components enforce separation of concerns with well-defined props and state. This is a major contributor to React’s scalability.
- Simplified Lifecycles: Android and, to a slightly lesser extent, iOS lifecycles are notoriously complex. Functional reactive React components fundamentally solve this problem and made learning React Native dramatically simpler than learning Android or iOS.
- Declarative: The declarative nature of React helped keep our UI in sync with the underlying state.
React
React是最受欢迎的Web框架是有原因的。 它非常简单但功能强大,适用于大型代码库。 我们特别喜欢的一些东西是:
组件: React组件通过明确定义的props和state强来强制分离关注点(解耦??)。 这是React可扩展性的主要方面。
简化的生命周期: Android和iOS,并且在一定程度上,iOS生命周期非常复杂。 函数反应式的React组件从根本上解决了这个问题,使学习React Native比学习Android或iOS更简单。
陈述: React的声明性特性帮助我们的UI与基础状态保持同步。
Iteration Speed
While developing in React Native, we were able to reliably use hot reloadingto test our changes on Android and iOS in just a second or two. Even though build performance is a top priority for our native apps, it has never come close to the iteration speed we achieved with React Native. At best, native compilation times are 15 seconds but can be as high as 20 minutes for full builds.
迭代速度
在使用React Native进行开发时,我们能够可靠地使用热重新加载,在短短一两秒内测试Android和iOS上的更改。尽管构建性能是我们本机应用的首要任务,但它从来没有接近我们通过React Native实现的迭代速度。充其量,本地编译时间为15秒,但对于完整版本可高达20分钟。
Investing in Infrastructure
We developed extensive integrations into our native infrastructure. All core pieces such as networking, i18n, experimentation, shared element transitions, device info, account info, and many others were wrapped in a single React Native API. These bridges were some of the more complex pieces because we wanted to wrap the existing Android and iOS APIs into something that was consistent and canonical for React. While keeping these bridges up to date with the rapid iteration and development of new infrastructure was a constant game of catch up, the investment by the infrastructure team made product work much easier.
Without this heavy investment in infrastructure, React Native would have led to a subpar developer and user experiences. As a result, we don’t believe React Native can be simply tacked on to an existing app without a significant and continuous investment.
投资于基础设施
我们开发了广泛的集成到我们的原生基础设诸如网络,i18n,实验,共享元素转换,设备信息,帐户信息等许多核心组件都包装在一个React Native API中。这些桥梁是一些更复杂的部分,因为我们想要将现有的Android和iOS API包装成对React一致且规范的东西。尽管通过快速迭代和新基础架构的开发来保持这些桥梁是最新的,但基础架构团队的投资使产品工作变得更加容易。
如果没有对基础架构进行大量投资,React Native会导致降低开发人员的开发体验和用户体验。 因此,我们不相信React Native可以在没有重大和持续投资的情况下直接应用到现有的应用程序中。
Performance
One of the largest concerns around React Native was its performance. However, in practice, this was rarely a problem. Most of our React Native screens feel as fluid as our native ones. Performance is often thought of in a single dimension. We frequently saw mobile engineers look at JS and think “slower than Java”. However, moving business logic and layout off of the main thread actually improves render performance in many cases.
When we did see performance issues, they were usually caused by excessive rendering and were mitigated by effectively using shouldComponentUpdate, removeClippedSubviews, and better use of Redux.
However, the initialization and first-render time (outlined below) made React Native perform poorly for launch screens, deeplinks, and increased the TTI time while navigating between screens. In addition, screens that dropped frames were difficult to debug because Yoga translates between React Native components and native views.
性能
React Native最大的问题之一就是它的表现。 但是,在实践中,这很少是一个问题。 我们的大多数React Native屏幕都像我们的本地屏幕一样流畅。 绩效往往被认为是单一维度。 我们经常看到移动工程师看JS,认为“比Java慢”。 但是,在很多情况下,移动主线程的业务逻辑和布局实际上可以提高渲染性能。
当我们看到性能问题时,他们通常是由过度渲染引起的,并通过有效地使用shouldComponentUpdate,removeClippedSubviews和更好地使用Redux来缓解。
然而,初始化和第一渲染时间((下面概述))使得React Native在启动屏幕,深度链接时表现不佳,并且在屏幕之间导航时增加了TTI时间。 另外,因为Yoga(一个布局框架)在React Native组件和本地视图之间转换,因此丢失帧的屏幕很难调试。
Redux
We used Redux for state management which we found effective and prevented the UI from ever getting out of sync with state and enabled easy data sharing across screens. However, Redux is notorious for its boilerplate and has a relatively difficult learning curve. We provided generators for some common templates but it was still one of the most challenging pieces and source of confusion while working with React Native. It is worth noting that these challenges were not React Native specific.
Redux
我们使用Redux进行状态管理,我们发现这种状态管理非常有效,并且防止了UI与状态不同步,并且可以轻松跨屏幕共享数据。 但是,Redux以其样板而闻名,并且学习曲线相对较为困难。 我们为一些常见模板提供了生成器,但它仍然是使用React Native时最具挑战性的部分和混淆之一。 值得注意的是,这些挑战不是React Native特有的。
Backed by Native
Because everything in React Native can be bridged by native code, we were ultimately able to build many things we weren’t sure were possible at the beginning such as:
- Shared element transitions: We built a <SharedElement> component that is backed by native shared element code on Android and iOS. This even works between native and React Native screens.
- Lottie: We were able to get Lottie working in React Native by wrapping the existing libraries on Android and iOS.
- Native networking stack: React Native uses our existing native networking stack and cache on both platforms.
- Other core infra: Just like networking, we wrapped the rest of our existing native infrastructure such as i18n, experimentation, etc. so that it worked seamlessly in React Native.
原生支持
由于React Native中的所有内容都可以通过原生代码进行桥接,因此我们最终能够在开始时构建许多我们不确定的事情,例如:
共享元素转换:我们构建了一个由Android和iOS上的本机共享元素代码支持的<SharedElement>组件。 这甚至适用于本机和React Native屏幕。
Lottie:通过在Android和iOS上包装现有的库,我们能够让Lottie在React Native中工作。
本地网络堆栈:React Native在两个平台上使用我们现有的本地网络堆栈和缓存。
其他核心内容:就像网络一样,我们将其他现有的本地基础架构(如i18n,实验等)封装起来,以便在React Native中无缝地工作。
Static Analysis
We have a strong history of using eslint on web which we were able to leverage. However, we were the first platform at Airbnb to pioneer prettier. We found it to be effective at reducing nits and bikeshedding on PRs. Prettier is now being actively investigated by our web infrastructure team.
We also used analytics to measure render times and performance to figure out which screens were the top priority to investigate for performance issues.
Because React Native was smaller and newer than our web infrastructure, it proved to be a good testbed for new ideas. Many of the tools and ideas we created for React Native are being adopted by web now.
静态分析
我们在网络上使用eslint的历史非常悠久,我们可以利用它。 不过,我们是Airbnb开创更漂亮的第一个平台。 我们发现它可以有效减少PRs上的麻烦和麻烦(这里翻译的有点理解不到位)。 现在,我们的网络基础架构团队正在积极调查漂亮的东西。
我们还使用分析来衡量渲染时间和性能,以确定哪些屏幕是性能问题调查的首要任务。
由于React Native比我们的网络基础设施更小更新,因此它被证明是新想法的良好测试平台。 我们为React Native创建的许多工具和想法现在都被web采用。
Animations
Thanks to the React Native Animated library, we were able to achieve jank-free animations and even interaction-driven animations such as scrolling parallax.
动画
得益于React Native Animated库,我们能够实现无干扰的动画,甚至是交互驱动的动画,例如滚动视差。
JS/React Open Source
Because React Native truly runs React and javascript, we were able to leverage the extremely vast array of javascript projects such as redux, reselect, jest, etc.
JS / React开源
由于React Native真正运行React和JavaScript,因此我们能够利用极大量的javascript项目,例如redux,reselect,jest等。
Flexbox
React Native handles layout with Yoga, a cross-platform C library that handles layout calculations via the flexbox API. Early on, we were hit with Yoga limitations such as the lack of aspect ratios but they have been added in subsequent updates. Plus, fun tutorials such as flexbox froggy made onboarding more enjoyable.
Flexbox的
React Native使用Yoga处理布局,瑜伽是一个跨平台的C库,可通过Flexbox API处理布局计算。 早些时候,我们遇到了Yoga限制,例如缺乏长宽比,但在后续更新中添加了它们。 此外,有趣的教程,如flexbox froggy使上手更愉快。
Collaboration with Web
Late in the React Native exploration, we began building for web, iOS, and Android at once. Given that web also uses Redux, we found large swaths of code that could be shared across web and native platforms with no alterations.
与Web协作
在React Native探索的后期,我们开始一次为web,iOS和Android构建。 鉴于Web还使用Redux,我们发现大量代码可以在Web和本机平台上共享,而无需任何更改。
What didn't work well
不好的方面
React Native Immaturity
React Native is less mature than Android or iOS. It is newer, highly ambitious, and moving extremely quickly. While React Native works well in most situations, there are instances in which its immaturity shows through and makes something that would be trivial in native very difficult. Unfortunately, these instances are hard to predict and can take anywhere from hours to many days to work around.
react-native 并不成熟
React Native比Android或iOS更不成熟(或者说是稳定?)。 它更新,更有野心,并且更新速度非常快。 虽然React Native在大多数情况下都能很好地工作,但有些情况下,它的不稳定可能会显示出来,并且会使原生开发中的一些微不足道的事情变得非常困难。 不幸的是,这些情况很难预测,可能需要几小时到几天的时间才能解决。(深有体会,译者注)
Maintaining a Fork of React Native
Due to React Native’s immaturity, there were times in which we needed to patch the React Native source. In addition to contributing back to React Native, we had to maintain a fork in which we could quickly merge changes and bump our version. Over the two years, we had to add roughly 50 commits on top of React Native. This makes the process of upgrading React Native extremely painful.
自行维护RN分支
由于React Native的不成熟,我们有时需要修正React Native源码。 除了向React Native做出贡献之外,我们还必须维护一个分支,以便我们能够快速合并更改并使版本崩溃。 在过去两年中,我们不得不在React Native之上添加大约50次提交。 这使得升级React Native的过程非常痛苦。
JavaScript Tooling
JavaScript is an untyped language. The lack of type safety was both difficult to scale and became a point of contention for mobile engineers used to typed languages who may have otherwise been interested in learning React Native. We explored adopting flow but cryptic error messages led to a frustrating developer experience. We also explored TypeScript but integrating it into our existing infrastructure such as babel and metro bundler proved to be problematic. However, we are continuing to actively investigate TypeScript on web.
JavaScript工具
JavaScript是一种无类型的语言。 缺乏类型安全性难以扩展,并成为移动工程师争用的焦点,这些工程师习惯于键入可能对学习React Native感兴趣的语言。 我们探讨了采用流程,但隐晦的错误消息导致了令人沮丧的开发者体验。 我们还探讨了TypeScript,但将其整合到我们现有的基础设施中,例如babel和metro bundler,证明是有问题的。 但是,我们正在继续积极调查Web上的TypeScript。
Refactoring
A side-effect of JavaScript being untyped is that refactoring was extremely difficult and error-prone. Renaming props, especially props with a common name like onClick or props that are passed through multiple components were a nightmare to refactor accurately. To make matters worse, the refactors broke in production instead of at compile time and were hard to add proper static analysis for.
重构
JavaScript被忽略的副作用是重构非常困难且容易出错。 重命名props,特别是带有通常名称的props,如通过多个组件传递的onClick或props,是准确重构的噩梦。 更糟糕的是,重构在生产中而不是在编译时崩溃,很难为其添加适当的静态分析。
JavaScriptCore inconsistencies
One subtle and tricky aspect of React Native is due to the fact that it is executed on a JavaScriptCore environment. The following are consequences we encountered as a result:
- iOS ships with its own JavaScriptCore out of the box. This meant that iOS was mostly consistent and not problematic for us.
- Android doesn’t ship its own JavaScriptCore so React Native bundles its own. However, the one you get by default is ancient. As a result, we had to go out of our way to bundle a newer one.
- While debugging, React Native attaches to a Chrome Developer Tools instance. This is great because it is a powerful debugger. However, once the debugger is attached, all JavaScript runs within Chrome’s V8 engine. This is fine 99.9% of the time. However, in one instance, we got bit when toLocaleString worked on iOS and but only worked on Android while debugging. It turns out that the Android JSC doesn’t include it and it was silently failing unless you were debugging in which case it was using V8 which does. Without knowing technical details like this, it can lead to days of painful debugging for product engineers.
JavaScriptCore不一致
React Native的一个微妙和棘手的方面是由于它是在JavaScriptCore环境中执行的。以下是我们遇到的结果:
iOS自带的JavaScriptCore开箱即用。这意味着iOS大部分是一致的,对我们来说没有问题。
Android并没有发布自己的JavaScriptCore,所以React Native捆绑了自己的JavaScriptCore。然而,你默认的那个是古老的。因此,我们不得不用我们的方式捆绑一个新的。
在调试时,React Native会附加到Chrome开发人员工具实例。这很好,因为它是一个强大的调试器。但是,一旦连接了调试器,所有JavaScript都将在Chrome的V8引擎中运行。这是99.9%的时间。但是,在一个实例中,我们在iOS上使用toLocaleString时只有一点点时间,但在调试时只能在Android上工作。事实证明,Android JSC不包括它,它是默默地失败,除非你正在调试,在这种情况下,它使用的是V8。在不知道这些技术细节的情况下,可能会导致产品工程师进行数日痛苦的调试。
React Native Open Source Libraries
Learning a platform is difficult and time-consuming. Most people only know one or two platforms well. React Native libraries that have native bridges such as maps, video, etc. requires equal knowledge of all three platforms to be successful. We found that most React Native Open source projects were written by people who had experience with only one or two. This led to inconsistencies or unexpected bugs on Android or iOS.
On Android, many React Native libraries also require you to use a relative path to node_modules rather than publishing maven artifacts which are inconsistent with what is expected by the community.
react-native开放源代码库
学习平台既困难又耗时。 大多数人只能很好地了解一个或两个平台。 React具有原生通信的bridge(如地图,视频等)的本机库需要对所有三个平台都有相同的认识才能取得成功。 我们发现大多数React Native开源项目都是由有一两次经验的人撰写的。 这导致了Android或iOS上的不一致或意外的错误。
在Android上,许多React Native库也要求您使用node_modules的相对路径,而不是发布与社区所期望的不一致的maven工件。
Parallel Infrastructure and Feature Work
We have accumulated many years of native infrastructure on Android and iOS. However, in React Native, we started with a blank slate and had to write or create bridges of all existing infrastructure. This meant that there were times in which a product engineer needed some functionality that didn’t yet exist. At that point, they either had to work in a platform they were unfamiliar with and outside the scope of their project to build it or be blocked until it could be created.
并行基础架构和特性工作
我们在Android和iOS上积累了多年的本地基础架构。 但是,在React Native中,我们从空白的石板开始,不得不编写或创建所有现有基础架构的桥梁。 这意味着有时产品工程师需要一些尚不存在的功能。 那时,他们必须在他们不熟悉的平台上工作,并且不在他们项目的范围之内来构建它,或者在被创建之前被阻止。
Crash Monitoring
We use Bugsnag for crash reporting on Android and iOS. While we were able to get Bugsnag generally working on both platforms, it was less reliable and required more work than it did on our other platforms. Because React Native is relatively new and rare in the industry, we had to build a significant amount of infrastructure such as uploading source maps in-house and had to work with Bugsnag to be able to do things like filter crashes by just those that occurred in React Native.
Due to the amount of custom infrastructure around React Native, we would occasionally have serious issues in which crashes weren’t reported or source maps weren’t properly uploaded.
Finally, debugging React Native crashes were often more challenging if the issue spanned React Native and native code since stack traces don’t jump between React Native and native.
崩溃监控
我们使用Bugsnag在Android和iOS上进行崩溃报告。 虽然我们能够让Bugsnag通常在两个平台上工作,但它不太可靠,并且需要比在其他平台上做更多的工作。 由于React Native在行业中相对较新且稀少,因此我们必须构建大量基础设施,例如内部上传源地图,并且必须与Bugsnag合作才能执行诸如过滤器崩溃等事件 反应原生。
由于React Native周围的自定义基础架构数量众多,偶尔会出现严重问题,其中未报告崩溃或源地图未正确上传。
最后,如果问题跨越React Native和本机代码,调试React Native崩溃往往更具挑战性,因为堆栈跟踪不会在React Native和本机之间跳转。
Native Bridge
React Native has a bridge API to communicate between native and React Native. While it works as expected, it is extremely cumbersome to write. Firstly, it requires all three development environments to be properly set up. We also experienced many issues in which the types coming from JavaScript were unexpected. For example, integers were often wrapped by strings, an issue that isn’t realized until it is passed over a bridge. To make matters worse, sometimes iOS will fail silently while Android will crash. We began to investigate automatically generating bridge code from TypeScript definitions towards the end of 2017 but it was too little too late.
与原生通信
React Native有一个桥接API来在本机和React Native之间进行通信。 虽然它按预期工作,但编写起来非常麻烦。 首先,它要求所有三种开发环境都要正确设置。 我们也遇到了很多来自JavaScript的类型出乎意料的问题。 例如,整数通常是由字符串包裹的,这个问题直到它通过桥接才会实现。 更糟糕的是,有时候iOS会在Android崩溃时失败。 我们开始调查自动生成从TypeScript定义到2017年底的桥代码,但这太迟了。
Initialization Time
Before React Native can render for the first time, you must initialize its runtime. Unfortunately, this takes several seconds for an app of our size, even on a high-end device. This made using React Native for launch screens nearly impossible. We minimized the first-render time for React Native by initializing it at app-launch.
初始化时间
在React Native首次可以渲染之前,您必须初始化其运行时。 不幸的是,即使在高端设备上,我们的尺寸也需要几秒钟的时间。 这使得使用React Native进行启动屏幕几乎是不可能的。 我们通过在应用程序启动时初始化React Native来缩短第一次渲染时间。
Initial Render Time
Unlike with native screens, rendering React Native requires at least one full main thread -> js -> yoga layout thread -> main thread round trip before there is enough information to render a screen for the first time. We saw an average initial p90 render of 280ms on iOS and 440ms on Android. On Android, we used the postponeEnterTransition API which is normally used for shared element transitions to delay showing the screen until it has rendered. On iOS, we had issues setting the navbar configuration from React Native fast enough. As a result, we added an artificial delay of 50ms to all React Native screen transitions to prevent the navbar from flickering once the configuration was loaded.
初始渲染时间
与原生屏幕不同,渲染React Native需要至少一个完整的主线程 - > js - >Yoga布局线程 - >主线程往返行程,然后才有足够的信息来第一次渲染屏幕。 我们看到iOS平均初始p90呈现280ms,Android平均440ms。 在Android上,我们使用通常用于共享元素转换的postponeEnterTransition API来延迟显示屏幕直到它被渲染。 在iOS上,我们遇到了问题,从React Native快速设置导航栏配置。 因此,我们为所有React Native屏幕过渡添加了50ms的仿真延迟,以防止配置加载后导航栏闪烁。
App Size
React Native also has a non-negligible impact on app size. On Android, the total size of React Native (Java + JS + native libraries such as Yoga + Javascript Runtime) was 8mb per ABI. With both x86 and arm (32 bit only) in one APK, it would have been closer to 12mb.
应用尺寸
React Native对应用程序大小也有不可忽视的影响。 在Android上,React Native(Java + JS +本地库,例如Yoga + Javascript Runtime)的总大小为每个ABI 8mb。 在一个APK中使用x86和arm(仅32位),它将接近12mb。
64-bit
We still can’t ship a 64-bit APK on Android because of this issue.
64位
由于此问题,我们仍然无法在Android上发布64位APK。
Gestures
We avoided using React Native for screens that involved complex gestures because the touch subsystem for Android and iOS are different enough that coming up with a unified API has been challenging for the entire React Native community. However, work is continuing to progress and react-native-gesture-handler just hit 1.0.
手势
我们避免在涉及复杂手势的屏幕上使用React Native,因为Android和iOS的触摸子系统足够不同,以至于提出统一的API对整个React Native社区来说都具有挑战性。 然而,工作正在继续进行,并且react-native-gesture-handler刚刚达到1.0。
Long Lists
React Native has made some progress in this area with libraries like FlatList. However, they are nowhere near the maturity and flexibility of RecyclerViewon Android or UICollectionView on iOS. Many of the limitations are difficult to overcome because of the threading. Adapter data can’t be accessed synchronously so it is possible to see views flash in as they get asynchronously rendered while scrolling quickly. Text also can’t be measured synchronously so iOS can’t make certain optimizations with pre-computed cell heights.
长名单
React Native在像FlatList这样的第三方组件这方面取得了一些进展。 但是,它们远不及Android上的RecyclerView或iOS上的UICollectionView的成熟度和灵活性。 由于线程原因,许多限制难以克服。 适配器数据无法同步访问,因此可以看到视图闪烁,因为它们在快速滚动时异步呈现。 文本也无法同步测量,因此iOS无法使用预先计算的单元高度进行某些优化。(这个坑体会至深,如跗骨之蛆)
Upgrading React Native
Although most React Native upgrades were trivial, there were a few that wound up being painful. In particular, it was nearly impossible to use React Native 0.43 (April 2017) to 0.49 (October 2017) because it used React 16 alpha and beta. This was hugely problematic because most React libraries that are designed for web use don’t support pre-release React versions. The process of wrangling the proper dependencies for this upgrade was a major detriment to other React Native infrastructure work in mid-2017.
升级React Native
尽管大多数React Native升级都很微不足道,但有一些令人痛苦。 尤其是,使用React Native 0.43(2017年4月)至0.49(2017年10月)几乎是不可能的,因为它使用了React 16 alpha和beta。 这非常成问题,因为大多数专为Web使用而设计的React库不支持预发布React版本。 争夺此次升级的适当依赖关系的过程对2017年中期其他React Native基础架构工作造成重大损害。
Accessibility
In 2017, we did a major accessibility overhaul in which we invested significant efforts to ensure that people with disabilities can use Airbnb to book a listing that can accommodate their needs. However, there were many holes in the React Native accessibility APIs. In order to meet even a minimum acceptable accessibility bar, we had to maintain our own fork of React Native where we could merge fixes. For these case, a one-line fix on Android or iOS wound up taking days of figuring out how to add it to React Native, cherry picking it, then filing an issue on React Native core and following up on it over the coming weeks.
无障碍
在2017年,我们进行了重大无障碍检修,我们投入了大量精力,确保残疾人士可以使用Airbnb预订符合其需求的清单。 但是,React Native 无障碍 API中有很多漏洞。 为了满足最低可接受的可无障碍性能,我们必须维护我们自己的React Native分支,我们可以在其中合并修补程序。 对于这些情况,Android或iOS上的一行修复需要数天时间才能确定如何将其添加到React Native,然后选择它,然后在React Native核心上提交问题并在接下来的几周内对其进行跟踪。
Troublesome Crashes
We have had to deal with a few very bizarre crashes that are hard to fix. For example, we are currently experiencing this crash on the @ReactPropannotation and have been unable to reproduce it on any device, even those with identical hardware and software to ones that are crashing in the wild.
麻烦的崩溃
我们不得不面对一些难以解决的非常奇怪的崩溃。 例如,我们目前在@ReactProp注释中遇到了这种崩溃,并且无法在任何设备上重现它,即使那些具有相同硬件和软件的硬件和软件与那些正在崩溃的硬件和软件相同。
SavedInstanceState Across Processes on Android
Android frequently cleans up background processes but gives them a chance to synchronously save their state in a bundle. However, on React Native, all state is only accessible in the js thread so this can’t be done synchronously. Even if this weren’t the case, redux as a state store is not compatible with this approach because it contains a mix of serializable and non-serializable data and may contain more data than can fit within the savedInstanceState bundle which would lead to crashes in production.
SavedInstanceState跨Android上的进程
Android经常清理后台进程,但让他们有机会同步保存它们的状态。 但是,在React Native上,所有状态只能在js线程中访问,因此不能同步完成。 即使情况并非如此,作为状态存储的redux与此方法不兼容,因为它包含可序列化和不可序列化数据的混合,并且可能包含比saveInstanceState包中可能容纳的更多数据,这会导致崩溃产生。
This is part two in a series of blog posts highlighting our experiences with React Native and what’s next for mobile at Airbnb.
这是一系列博客文章的第二部分,重点介绍了我们在React Native方面的经验以及Airbnb的移动应用程序。
如有侵权,请即刻告知。