Last week at Chain React we announced Hermes, an open
source JavaScript engine we’ve been working on at
Facebook. It’s a small and lightweight JavaScript engine
optimized for running React Native on Android.
Check it out!
Hermes improves React Native performance by decreasing
memory utilization, reducing download size, and
decreasing the time it takes for the app to become
usable or “time to interactive” (TTI).
“As we analyzed performance data, we noticed that the
JavaScript engine itself was a significant factor in
startup performance and download size. With this data
in hand, we knew we had to optimize JavaScript
performance in the more constrained environments of a
mobile phone compared with a desktop or laptop. After
exploring other options, we built a new JavaScript
engine we call Hermes. It is designed to improve app
performance, focusing on our React Native apps, even
on mass-market devices with limited memory, slow
storage, and reduced computing power.” —Hermes: An open source JavaScript engine optimized
for mobile apps, starting with React Native
Ryan TurnerCore Maintainer & React Native Developer
After months of hard work from hundreds of contributors,
the React Native Core team is proud to announce the
release of version 0.60. This release handles
significant migrations for both Android and iOS
platforms, and many issues are resolved too. This blog
post covers the highlights of the release. As always
though, refer to the changelog for more detailed
information. Finally, thank you contributors for helping
us to make this milestone!
React Native's start screen has been updated! Thank you
to the many contributors who helped create the new UI.
This new "Hello World" will welcome users to
the ecosystem in a more friendly, engaging way.
AndroidX Support
AndroidX
is a major step forward in the Android ecosystem, and
the old support library artifacts are being deprecated.
For 0.60, React Native has been migrated over to
AndroidX. This is a breaking change, and
your native code and dependencies will need to be
migrated
as well.
With this change, React Native apps will need to begin
using AndroidX themselves. They cannot be used
side-by-side in one app, so all of the app code and
dependency code needs to be using one or the other.
While your own native code will need to be migrated by
you,
@mikehardy,
@cawfree, and
@m4tt72 built a
clever tool named "jetifier"
to patch your node_modules. Library
maintainers will need to upgrade, but this tool provide
you with a temporary solution while giving them time to
release an AndroidX version. So if you find errors
related to AndroidX migration, give this a shot.
CocoaPods by Default
CocoaPods are now part of React Native's iOS
project. If you weren't already, be sure to open iOS platform
code using the xcworkspace file from now on
(protip: try xed ios from the root project
directory). Also, the podspecs for the
internal packages have changed to make them compatible
with the Xcode projects, which will help with
troubleshooting and debugging. Expect to make
some straightforward changes
to your Podfile as part of the upgrade to
0.60 to bring this exciting support. Note that we are
aware of a compatability issue with
use_frameworks!, and we're tracking an
issue
with workarounds and a future patch.
Lean Core Removals
WebView and
NetInfo were previously extracted into
separate repositories, and in 0.60 we’ve finished
migrating them out of the React Native repository.
Additionally, in response to community feedback about
new App Store policy, Geolocation has
been extracted. If you haven’t already, complete your
migration by adding dependencies to
react-native-webview,
@react-native-community/netinfo, and
@react-native-community/geolocation. If you'd like an automated solution, consider using
rn-upgrade-deprecated-modules. Maintainers have made more than 100 commits to these
repositories since extraction and we’re excited to see
the community’s support!
Native Modules are now Autolinked
The team working on the
React Native CLI
has introduced major improvements to native module
linking called
autolinking! Most scenarios will not require the use of
react-native link anymore. At the same
time, the team overhauled the linking process in
general. Be sure to react-native unlink any
preexisting dependencies as mentioned in the docs above.
Upgrade Helper
@lucasbento,
@pvinis,
@kelset, and
@watadarkstar
have built a great tool called
Upgrade Helper
to make the upgrade process simpler. It helps React
Native users with brownfield apps or complex
customizations to see what's changed between versions.
Take a look at the
updated upgrading docs
and try it out today for your upgrade path!
A Note to Library Maintainers
Changes for AndroidX will almost certainly require
updates to your library, so be sure to include support
soon. If you're not able to upgrade yet, consider
checking your library against the jetifier to confirm
that users are able to patch your library at build time.
Review the
autolinking
docs to update your configs and readme. Depending on how
your library was previously integrated, you may also
need to make some additional changes. Check the
dependencies
guide from the CLI for information on how to define your
dependency interface.
Thanks
While these are the highlights that we noted, there are
many others to be excited about. To see all the updates,
take a look at the
changelog. As always, stay tuned for more news. Enjoy 0.60 in
the meantime!
In the past six months, a total of 2800 commits were
made to React Native by more than 550 contributors. 400
contributors from the community created more than
1,150 Pull Requests, of which
820 Pull Requests
were merged.
The average number of Pull Requests per day throughout
the past six months has increased from three to about
six, even though we split the website, CLI and many
modules out of React Native via the Lean Core effort.
The average amount of open pull requests is now below 25
and we usually reply with suggestions and reviews within
hours or days.
Meaningful Community Contributions
We’d like to highlight a number of recent contributions
which we thought were awesome:
Accessibility: React Native 0.60 will
ship with many improvements to accessibility APIs both
on Android and iOS. All of the new features are
directly using APIs provided by the underlying
platform so they’ll integrate with native assistance
technologies both on Android and iOS. We’d like to
thank
Marc Mulcahy,
Alan Kenyon,
Estevão Lucas,
Sam Mathias Weggersen
and
Janic Duplessis
for their contributions:
Android keyboard accessibility improvements. Added a clickable prop and an
onClick callback for invoking actions
via keyboard navigation
(note: this will soon be renamed to
focusable).
New App Screen: The community came up
with a
design for the new app screen
that is implemented in 0.60. This screen is what most
people see when they are first using React Native. It
now links first time users to the documentation and
the look fits with our upcoming website redesign 🌟.
Huge thanks to
Orta,
Adam Shurson,
Glauber Castro,
Karan Singh,
Eli Perkins,
Lucas Bento
and
Eric Lewis
for all their work and collaboration!
Check out the new app screen on the “*React Native Show“ *video series.
TurboModule Types: The new
TurboModules system
requires
types for all native modules
to guarantee type safe operations in native. In just
over two weeks, the community sent ~40 Pull Requests
to complete this work for flow typed native modules.
Aside from the people already mentioned above, we’d
like to thank
Michał Chudziak,
Michał Pierzchała,
Wojtek Szafraniec, and
Jean Regisser
and everyone else who sent one or more Pull Requests.
Haste: Since 2015 React Native used
the
“haste” module system
that allows importing modules just via a global id
instead of a relative path which is convenient but not
well supported by many tools.
James Ide
proposed removing haste, similar to how React removed
haste many years ago. He planned all the work through
an
umbrella task
and he sent 18 Pull Requests to make it happen! Check
out
his Twitter thread
to learn more.
The primary motivation of
Lean Core
has been to split modules out of React Native into
separate repositories so they can receive better
maintenance. In just a six months repositories like
WebView,
NetInfo,
AsyncStorage, the
website
and the
CLI
received more than 800 Pull Requests combined. Besides
better maintenance, these projects can also be
independently released more often than React Native
itself.
We have also taken the opportunity to remove obsolete
polyfills and legacy components from React Native
itself. Polyfills were necessary in the past to support
language features like
Map
and
Set
in older versions of JavaScriptCore (JSC). Now that
React Native ships with a new version, these polyfills
were removed.
This work is still in progress and many more things
still need to be split out or removed both on the native
and JavaScript side but there are early signs that we
managed to reverse the trend of increasing the surface
area and app size: When looking at the JavaScript bundle
for example, about a year ago in version 0.54 the React
Native JavaScript bundle size was 530kb and grew to
607kb (+77kb) by version 0.57 in just 6 months. Now we
are seeing a bundle size reduction of 28kb down to 579kb
on master, a delta of more than 100kb!
As we conclude the first iteration of the Lean Core
effort, we will make an effort to be more intentional
about new APIs added to React Native and we will
continuously evaluate ways to make React Native smaller
and faster, as well as finding ways to empower the
community to take ownership of various components.
Upgrading: The React Native community
rallied around with multiple improvements to the
upgrading experience:
autolinking, a better upgrading command via
rn-diff-purge, an upgrade helper website (coming soon). We’ll also
make sure to communicate breaking changes and exciting
new features by publishing blog posts for each major
release. Many of these improvements will make future
upgrades beyond the 0.60 release significantly easier.
Support / Uncertainty: Many people
were frustrated with the lack of activity on Pull
Requests and general uncertainty about Facebook's
investment in React Native. As we've shown above, we
can confidently say that we are ready for many more
Pull Requests and we are eagerly looking forward to
your proposals and contributions!
Performance: React Native 0.59
shipped with a new and much faster version of
JavaScriptCore (JSC). Separately, we have been working
on making it easier to enable
inline-requires
by default and we have more exciting updates for you
in the next couple of months.
Hot Reloading: The React team is
building a
new hot reloading system
that will soon be integrated into React Native.
Unfortunately we weren’t able to improve everything just
yet:
Debugging: We fixed many inconvenient
bugs and issues people that we have been running into
every day, but unfortunately we haven't made as much
progress on this as we would like. We recognize that
debugging with React Native isn't great and we'll
prioritize improving this in the future.
Metro symlinks: Unfortunately we
haven't been able to implement a simple and
straightforward solution for this yet. However, React
Native users
shared various workarounds
that may work for you.
Given the large amount of changes in the past six
months, we'd like to ask you the same question again. If
you are using the latest version of React Native and you
have things you'd like to give feedback on, please
comment on our new edition of
“What do you dislike about React Native?”
Continuous Integration
Facebook merges all Pull Requests and internal changes
directly into Facebook’s repository first and then syncs
all commits back to GitHub. Facebook’s infrastructure is
different from common continuous integration services
and not all open source tests were run inside of
Facebook. This means that commits that sync out to
GitHub frequently break tests in open source which take
a lot of time to fix.
Héctor Ramos
from the React Native team spent the past two months
improving React Native's continuous integration systems
both at Facebook and on GitHub. Most of the open source
tests are now run before changes are committed to React
Native at Facebook which will keep CI stable on GitHub
when commits are being synchronized.
Next
Make sure to check out our talks about the future of
React Native! In the next couple of months, members of
the React Native team at Facebook will speak at
Chain React
and at
React Native EU.
Also, watch out for our next release, 0.60, which is
right around the corner.
It's going to be exciting ✨
This week,
Eli White
gave a talk at
F8 2019
about React Native in Facebook's Android and iOS
applications. We are excited to share what we've been up
to for the past two years and what we're doing next.
We spent 2017 and 2018 focused on React Native's
largest product, Facebook's Marketplace. We
collaborated with the Marketplace team to improve
quality and add delight to the product. At this point,
Marketplace is one of the highest quality products in
the Facebook app both on Android and iOS.
Marketplace's performance was a big challenge as well,
especially on mid-end Android devices. We cut startup
time by more than 50% over the last year with more
improvements on the way! The biggest improvements are
being built into React Native and will be coming to
the community later this year.
We have the confidence that we can build the high
quality and performant apps that Facebook needs with
React Native. This confidence has let us invest in
bigger bets, like
rethinking the core of React Native.
Microsoft supports and uses React Native for Windows,
enabling people to use their expertise and codebase to
render to Microsofts's Universal Windows Platform.
Check out Microsoft Build next week to
hear them talk about that more.
We talked about how the React Native team at Facebook
thinks about open source and how we are building a
sustainable community that scales for a project of
React Native's
size.
We are on track to remove multiple modules as part of
the
Lean Core
effort. Many modules like WebView and the React Native
CLI have received more than 100 Pull Requests since
they were extracted.
Next, we'll be focusing on overhauling the React
Native website and documentation. Stay tuned!
You'll find the episode in your favorite podcasting app
soon or you can listen to the recording right here:
Ryan TurnerCore Maintainer & React Native Developer
Welcome to the 0.59 release of React Native! This is
another big release with 644 commits by 88 contributors.
Contributions also come in other forms, so
thank you for maintaining issues, fostering
communities, and teaching people about React Native.
This month brings a number of highly anticipated
changes, and we hope you enjoy them.
🎣 Hooks are here
React Hooks are part of this release, which let you
reuse stateful logic across components. There is a lot
of buzz about hooks, but if you haven't heard, take a
look at some of the wonderful resources below:
useHooks.com
showcases community-maintained Hooks recipes and
demos.
Be sure to give this a try in your apps. We hope that
you find the reuse as exciting as we do.
📱 Updated JSC means performance gains and 64-bit
support on Android
React Native uses JSC (JavaScriptCore) to power your application. JSC on Android was a few
years old, which meant that a lot of modern JavaScript
features weren't supported. Even worse, it performed
poorly compared iOS's modern JSC. With this release,
that all changes.
Thanks to some awesome work by
@DanielZlotin,
@dulmandakh,
@gengjiawen,
@kmagiera, and
@kudo JSC has
caught up with the past few years. This brings with it
64-bit support, modern JavaScript support, and
big performance improvements. Kudos for also making this a maintainable process now
so that we can take advantage of future WebKit
improvements without so much legwork, and thank you
Software Mansion and Expo for making this work possible.
💨 Faster app launches with inline requires
We want to help people have performant React Native apps
by default and are working to bring Facebook's
optimizations to the community. Applications load
resources as needed rather than slowing down launch.
This feature is called "inline requires", as
it lets Metro identify components to be lazy loaded.
Apps with a deep and varied component architecture will
see the most improvement.
We need the community to let us know how it works before
we turn it on by default. When you upgrade to 0.59,
there will be a new metro.config.js file;
flip the options to true and give us
your feedback! Read more about inline requires
in the performance docs
to benchmark your app.
🚅 Lean core is underway
React Native is a large and complex project with a
complicated repository. This makes the codebase less
approachable to contributors, difficult to test, and
bloated as a dev dependency.
Lean Core
is our effort to address these issues by migrating code
to separate libraries for better management. The past
few releases have seen the first steps of this, but
let's get serious.
You may notice that additional components are now
officially deprecated. This is great news, as there are
now owners for these features actively maintaining them.
Heed the warning messages and migrate to the new
libraries for these features, because they will be
removed in a future release. Below is a table indicating
the component, its status, and where you may migrate
your use to.
Over the coming months, there will be many more
components following this path to a leaner core. We're
looking for help with this — head over to the
lean core umbrella
to pitch in.
👩🏽💻 CLI improvements
React Native's command line tools are developer's entry
point to the ecosystem, but they had long-standing
issues and lacked official support. The CLI tools have
been moved to a
new repository, and a
dedicated group of maintainers
have already made some exciting improvements.
Logs are formatted much better now. Commands now run
nearly instantly — you'll immediately notice a
difference:
🚀 Upgrading to 0.59
We heard your feedback regarding the
React Native upgrade process
and we are taking steps to improve the experience in
future releases. To upgrade to 0.59, we recommend using
rn-diff-purge
to determine what has changed between your current React
Native version and 0.59, then applying those changes
manually. Once you've upgraded your project to 0.59, you
will be able to use the newly improved
react-native upgrade command (based on
rn-diff-purge!) to upgrade to 0.60 and
beyond as newer releases become available.
🔨 Breaking Changes
Android support in 0.59 has been cleaned up following
Google's latest recommendations, which may result in
potential breakage of existing apps. This issue might
present as a runtime crash and a message, "You need
to use a Theme.AppCompat theme (or descendant) with this
activity". We recommend updating your project's
AndroidManifest.xml file, making sure that
the android:theme value is an
AppCompat theme (such as
@style/Theme.AppCompat.Light.NoActionBar).
The react-native-git-upgrade command has
been removed in 0.59, in favor of the newly improved
react-native upgrade command.
While these are the highlights that we noted, there are
many others to be excited about. To see all of the
updates, take a look at the
changelog. 0.59 is a huge release – we can't wait for you to try
it out.
We have even more improvements coming throughout the
rest of the year. Stay tuned!
We announced our
React Native Open Source roadmap
in Q4 2018 after deciding to invest more in the React
Native open source community.
For our first milestone, we focused on identifying and
improving the most visible aspects of our community. Our
goals were to reduce outstanding pull requests, reduce
the project's surface area, identify leading user
problems, and establish guidelines for community
management.
In the past two months, we made more progress than we
expected. Read on for more details:
Pull Requests
In order to build a healthy community, we must respond
quickly to code contributions. In past years, we
de-prioritized reviewing community contributions and
accumulated 280 pull requests (December 2018). In the
first milestone, we reduced the number of open pull
requests to ~65. Simultaneously, the average number of
pull requests opened per day increased from 3.5 to 7
which means we have handled about
600 pull requests
in the last three months.
We merged
almost two-thirds
and closed one-third of the pull requests. They were
closed without being merged if they are obsolete or low
quality, or if they unnecessarily increase the project's
surface area. Most of the merged pull requests fixed
bugs, improved cross-platform parity, or introduced new
features. Notable contributions include improving type
safety and the ongoing work to support AndroidX.
At Facebook, we run React Native from master, so we test
all changes first before they make it into a React
Native Release. Out of all the merged pull requests,
only six caused issues: four only affected internal
development and two were caught in the release candidate
state.
One of the more visible community contributions was
the updated “RedBox” screen. It's a good example of how the community is making
the developer experience friendlier.
Lean Core
React Native currently has a very wide surface area with
many unmaintained abstractions that we do not use a lot
at Facebook. We are working on reducing the surface area
in order to make React Native smaller and allow the
community to take better care of abstractions that are
mostly unused at Facebook.
What we are most excited about is that maintainers have
jumped in fixing long standing issues, adding tests, and
supporting long requested features. These modules are
getting more support than they ever did within React
Native, showing that this is a great step for the
community. Examples of such projects are
WebView
that has
received many pull requests
since their extraction and the CLI that is now
maintained by members of the community
and received much needed improvements and fixes.
Leading User Problems
In December, we asked the community what they
disliked about React Native. We aggregated the responses and
replied to each and every problem. Fortunately, many of the issues that our community
faces are also problems at Facebook. In our next
milestone, we plan to address some of the main problems.
One of the highest voted problems was the developer
experience of upgrading to newer versions of React
Native. Unfortunately, this is not something that we
experience ourselves because we run React Native from
master. Thankfully, members from the community already
stepped up to address this problem:
We plan on recommending CocoaPods by default for
iOS projects
which will reduce churn in project files when
upgrading React Native. This will make it easier for
people to install and link third-party modules which
is even more important in the context of Lean Core as
we expect projects to link more modules by default.
0.59 Release
Without the help of the React Native community,
especially
Mike Grabowski
and
Lorenzo Sciandra, we would not be able to ship releases. We want to
improve the release management process and plan to be
more involved from now on:
We will work with community members to create a blog
post for each major release.
We will show breaking changes directly in the CLI when
people upgrade to new versions.
We will reduce the time it takes to make a release. We
are exploring ways to increase automated testing and
also creating an improved manual test plan.
Many of these plans will be incorporated in the upcoming
React Native 0.59 release. 0.59 will ship with React Hooks, a new 64-bit version
of JavaScriptCore for Android, and many performance and
functionality improvements. It is currently published as
a release candidate and is expected to be stable within
the next two weeks.
Next Steps
For the next two months, we will continue managing pull
requests
to stay on track
while also starting to reduce the number of outstanding
GitHub issues. We will continue reducing the surface
area of React Native through the Lean Core project. We
plan to address 5 of the top community problems. As we
finalize the community guidelines, we will turn
attention to our website and documentation.
We are very excited to host over ten contributors from
our community at Facebook London in March to help drive
several of these efforts. We are glad that you are using
React Native and hope that you'll see and feel the
improvements we are working on in 2019. We'll be back
with another update in a few months and
will be merging your pull requests in the
meantime!
⚛️✌️
In 2018 the React Native Community made a number of
changes to the way we develop and communicate about
React Native. We believe that a few years from now we
will look back and see that this shift was a turning
point for React Native.
A lot of people are excited about the rewrite of React
Native's architecture, widely known as
Fabric. Among other things, this will fix fundamental
limitations in React Native's architecture and will set
up React Native for success in the future together with
JSI and TurboModules.
The biggest shift in 2018 was to empower the React
Native Community. From the beginning, Facebook
encouraged developers from all around the world to
participate in React Native's open source project. Since
then, a number of core contributors emerged to handle,
among other things, the release process.
These members took a few substantial steps towards
making the whole community more empowered to shape the
future of this project with the following resources:
This repository, created in January, serves the dual
purpose of allowing everyone to keep up the new releases
in a more collaborative manner and opened the
conversation of what would be part of a certain release
to whomever wanted to suggest a cherry-pick (like for
0.57.8
and all its previous versions).
This has been the driving force behind moving away from
a monthly release cycle, and the "long term
support" approach currently used for version
0.57.x.
Half of the credit for reaching these decisions goes to
the other repository created this year:
This repository, created in July, expanded on the idea
of a more open environment for conversations on React
Native. Previously, this need was handled by issues
labelled
For Discussion
in the main repository, but we wanted to expand this
strategy to an RFC approach that other libraries have
(e.g. React).
This experiment immediately found its role in the React
Native lifecycle. The Facebook team is now using the
community RFC process to discuss what could
be improved in React Native, and coordinate the efforts around the
Lean Core project
- among other interesting discussions.
We are aware that our approach to communicate these
efforts has not been as effective as we would have
liked, and in an attempt to give you all an easier time
keeping up with everything going on in the React Native
Community (from releases to active discussions) we
created a new twitter account that you can rely on
@ReactNativeComm.
If you are not on that social network, remember that you
can always watch repositories via GitHub; this feature
improved these past few months with the possibility of
being notified only for releases, so you should consider
using it anyway.
What awaits ahead 🎓
Over the past 7-8 months, core contributors enhanced the
React Native Community GitHub organization
to take more ownership over the development of React
Native, and enhance collaboration with Facebook. But
this always lacked the formal structure that similar
projects may have in place.
This organization can set the example for everyone in
the larger developer community by enforcing a set of
standards for all the packages/repos hosted in it,
providing a single place for maintainers to help each
other and contribute quality code that conforms to
community-agreed standards.
In early 2019, we will have this new set of guidelines
in place. Let us know what you think in the
dedicated discussion.
We are confident that with these changes, the community
will become more collaborative so that when we reach
1.0, we will all continue to write (even more) awesome
apps by leveraging this joint effort 🤗
I hope you are as excited as we are about the future of
this community. We're excited to see all of you involved
either in the conversations happening in the
repositories listed above or via the awesome code you’ll
produce.
This year, the React Native team has focused on a large
scale
re-architecture of React Native. As Sophie mentioned in her
State of React Native post,
we've sketched out a plan to better support the thriving
population of React Native users and collaborators
outside of Facebook. It's now time to share more details
about what we've been working on. Before I do so, I'd
like to lay out our long-term vision for React Native in
open source.
Our vision for React Native is...
A healthy GitHub repository. Issues
and pull requests get handled within a reasonable
period of time.
Increased test coverage.
Commits that sync out from the Facebook code
repository should not break open source tests.
A higher scale of meaningful community
contributions.
Stable APIs, making it easier to
interface with open source dependencies.
Facebook uses the same public API as open source
React Native releases that follow semantic
versioning.
A vibrant eco-system. High quality
ViewManagers, native modules, and multiple platform
support maintained by the community.
Excellent documentation. Focus on
helping users create high quality experiences, and
up-to-date API reference docs.
We have identified the following focus areas to help us
achieve this vision.
✂️ Lean Core
Our goal is to
reduce the surface area of React Native
by removing non-core and unused components. We'll
transfer non-core components to the community to allow
it to move faster. The reduced surface area will make it
easier to manage contributions to React Native.
WebView
is an example of a component that we transferred to the
community. We are working on a workflow that will allow
internal teams to continue using these components after
we remove them from the repository. We have identified
dozens more components
that we'll give ownership of to the community.
🎁 Open Sourcing Internals and 🛠Updated Tooling
The React Native development experience for product
teams at Facebook can be quite different from open
source. Tools that may be popular in the open source
community are not used at Facebook. There may be an
internal tool that achieves the same purpose. In some
cases, Facebook teams have become used to tools that do
not exist outside of Facebook. These disparities can
pose challenges when we open source our upcoming
architecture work.
We'll work on releasing some of these internal tools.
We'll also improve support for tools popular with the
open source community. Here's a non-exhaustive list of
projects we'll tackle:
Open source JSI and enable the community to bring
their own JavaScript VMs, replacing the existing
JavaScriptCore from RN's initial release. We'll be
covering what JSI is in a future post, in the meantime
you can learn more about JSI from
Parashuram's talk at React Conf.
Support 64-bit libraries on Android.
Enable debugging under the new architecture.
Improve support for CocoaPods, Gradle, Maven, and new
Xcode build system.
✅ Testing Infrastructure
When Facebook engineers publish code, it's considered
safe to land if it passes all tests. These tests
identify whether a change might break one of our own
React Native surfaces. Yet, there are differences in how
Facebook uses React Native. This has allowed us to
unknowingly break React Native in open source.
We'll shore up our internal tests to ensure they run in
an environment that is as close as possible to open
source. This will help prevent code that breaks these
tests from making it to open source. We will also work
on infrastructure to enable better testing of the core
repo on GitHub, enabling future pull requests to easily
include tests.
Combined with the reduced surface area, this will allow
contributors to merge pull requests quicker, with
confidence.
📜 Public API
Facebook will consume React Native via the public API,
the same way open source does, to reduce unintentional
breaking changes. We have started converting internal
call sites to address this. Our goal is to converge on a
stable, public API, leading to the adoption of semantic
versioning in version 1.0.
📣 Communication
React Native is one of the
top open source projects on GitHub
by contributor count. That makes us really happy, and
we'd like to keep it going. We'll continue working on
initiatives that lead to involved contributors, such as
increased transparency and open discussion. The
documentation is one of the first things someone new to
React Native will encounter, yet it has not been a
priority. We'd like to fix that, starting with bringing
back auto-generated API reference docs, creating
additional content focused on creating
quality user experiences, and improving our
release notes.
Timeline
We're planning to land these projects throughout the
next year or so. Some of these efforts are already
ongoing, such as
JSI which has already landed in open source. Others will take a bit longer to complete, such as
reducing the surface area. We'll do our best to keep the
community up to date with our progress. Please join us
in the
Discussions and Proposals
repository, a initiative from the React Native community
that has led to the creation of several of the
initiatives discussed in this roadmap.
For a long time now, Apple has discouraged using
UIWebViews in favor of WKWebView. In iOS 12, which will
be released in the upcoming months,
UIWebViews will be formally deprecated. React Native's iOS WebView implementation relies
heavily on the UIWebView class. Therefore, in light of
these developments, we've built a new native iOS backend
to the WebView React Native component that uses
WKWebView.
The tail end of these changes were landed in
this commit, and will become available in the 0.57 release.
To opt into this new implementation, please use the
useWebKit
prop:
UIWebView had no legitimate way to
facilitate communication between the JavaScript running
in the WebView, and React Native. When messages were
sent from the WebView, we relied on a hack to deliver
them to React Native. Succinctly, we encoded the message
data into a url with a special scheme, and navigated the
WebView to it. On the native side, we intercepted and
cancelled this navigation, parsed the data from the url,
and finally called into React Native. This
implementation was error prone and insecure. I'm glad to
announce that we've leveraged
WKWebView features to completely replace
it.
Other benefits of WKWebView over UIWebView include
faster JavaScript execution, and a multi-process
architecture. Please see this
2014 WWDC
for more details.
Caveats
If your components use the following props, then you may
experience problems when switching to WKWebView. For the
time being, we suggest that you avoid using these props:
Inconsistent behavior:
automaticallyAdjustContentInsets and
contentInsets (commit)
When you add contentInsets to a WKWebView,
it doesn't change the WKWebView's viewport.
The viewport remains the same size as the frame. With
UIWebView, the viewport size actually
changes (gets smaller, if the content insets are
positive).
With the new iOS implementation of WebView, there's a
chance that your background color will flicker into view
if you use this property. Furthermore,
WKWebView renders transparent backgrounds
differently from UIWebview. Please look at
the commit description for more details.
As technology advances and mobile apps become
increasingly important to everyday life, the necessity
of creating accessible applications has likewise grown
in importance.
React Native's limited Accessibility API has always been
a huge pain point for developers, so we've made a few
updates to the Accessibility API to make it easier to
create inclusive mobile applications.
Problems With the Existing API
Problem One: Two Completely Different Yet Similar Props
- accessibilityComponentType (Android) and
accessibilityTraits (iOS)
accessibilityComponentType and
accessibilityTraits are two properties that
are used to tell TalkBack on Android and VoiceOver on
iOS what kind of UI element the user is interacting
with. The two biggest problems with these properties are
that:
They are two different properties with different
usage methods, yet have the same purpose.
In the previous API, these are two separate properties
(one for each platform), which was not only
inconvenient, but also confusing to many developers.
accessibilityTraits on iOS allows 17
different values while
accessibilityComponentType on Android
allows only 4 values. Furthermore, the values for the
most part had no overlap. Even the input types for
these two properties are different.
accessibilityTraits allows either an
array of traits to be passed in or a single trait,
while accessibilityComponentType allows
only a single value.
There is very limited functionality on
Android.
With the old property, the only UI elements that
Talkback were able to recognize were “button,”
“radiobutton_checked,” and “radiobutton_unchecked.”
Problem Two: Non-existent Accessibility Hints:
Accessibility Hints help users using TalkBack or
VoiceOver understand what will happen when they perform
an action on an accessibility element that is not
apparent by only the accessibility label. These hints
can be turned on and off in the settings panel.
Previously, React Native's API did not support
accessibility hints at all.
Problem Three: Ignoring Inverted Colors:
Some users with vision loss use inverted colors on their
mobile phones to have greater screen contrast. Apple
provided an API for iOS which allows developers to
ignore certain views. This way, images and videos aren't
distorted when a user has the inverted colors setting
on. This API is currently unsupported by React Native.
Design of the New API
Solution One: Combining accessibilityComponentType
(Android) and accessibilityTraits (iOS)
In order to solve the confusion between
accessibilityComponentType and
accessibilityTraits, we decided to merge
them into a single property. This made sense because
they technically had the same intended functionality and
by merging them, developers no longer had to worry about
platform specific intricacies when building
accessibility features.
Background
On iOS, UIAccessibilityTraits is a property
that can be set on any NSObject. Each of the 17 traits
passed in through the javascript property to native is
mapped to a UIAccessibilityTraits element
in Objective-C. Traits are each represented by a long
int, and every trait that is set is ORed together.
On Android however,
AccessibilityComponentType is a concept
that was made up by React Native, and doesn't directly
map to any properties in Android. Accessibility is
handled by an accessibility delegate. Each view has a
default accessibility delegate. If you want to customize
any accessibility actions, you have to create a new
accessibility delegate, override specific methods you
want to customize, and then set the accessibility
delegate of the view you are handling to be associated
with the new delegate. When a developer set
AccessibilityComponentType, the native code
created a new delegate based off of the component that
was passed in, and set the view to have that
accessibility delegate.
Changes Made
For our new property, we wanted to create a superset of
the two properties. We decided to keep the new property
modeled mostly after the existing property
accessibilityTraits, since
accessibilityTraits has significantly more
values. The functionality of Android for these traits
would be polyfilled in by modifying the Accessibility
Delegate.
There are 17 values of UIAccessibilityTraits that
accessibilityTraits on iOS can be set to.
However, we didn't include all of them as possible
values to our new property. This is because the effect
of setting some of these traits is actually not very
well known, and many of these values are virtually never
used.
The values UIAccessibilityTraits were set to generally
took on one of two purposes. They either described a
role that UI element had, or they described the state a
UI element was in. Most uses of the previous properties
we observed usually used one value that represented a
role and combined it with either “state selected,”
“state disabled,” or both. Therefore, we decided to
create two new accessibility properties:
accessibilityRole and
accessibilityState.
accessibilityRole
The new property, accessibilityRole, is
used to tell Talkback or Voiceover the role of a UI
Element. This new property can take on one of the
following values:
none
button
link
search
image
keyboardkey
text
adjustable
header
summary
imagebutton
This property only allows one value to be passed in
because UI elements generally don't logically take on
more than one of these. The exception is image and
button, so we've added a role imagebutton that is a
combination of both.
accessibilityStates
The new property, accessibilityStates, is
used to tell Talkback or Voiceover the state a UI
Element is in. This property takes on an Array
containing one or both of the following values:
selected
disabled
Solution Two: Adding Accessibility Hints
For this, we added a new property,
accessibilityHint. Setting this property
will allow Talkback or Voiceover to recite the hint to
users.
accessibilityHint
This property takes in the accessibility hint to be read
in the form of a String.
On iOS, setting this property will set the corresponding
native property AccessibilityHint on the view. The hint
will then be read by Voiceover if Accessibility Hints
are turned on in the iPhone.
On Android, setting this property appends the value of
the hint to the end of the accessibility label. The
upside to this implementation is that it mimics the
behavior of hints on iOS, but the downside to this
implementation is that these hints cannot be turned off
in the settings on Android the way they can be on iOS.
The reason we made this decision on Android is because
normally, accessibility hints correspond with a specific
action (e.g. click), and we wanted to keep behaviors
consistent across platforms.
Solution to Problem Three
accessibilityIgnoresInvertColors
We exposed Apple's api AccessibilityIgnoresInvertColors
to JavaScript, so now when you have a view where you
don't want colors to be inverted (e.g image), you can
set this property to true, and it won't be inverted.
New Usage
These new properties will become available in the React
Native 0.57 release.
How to Upgrade
If you are currently using
accessibilityComponentType and
accessibilityTraits, here are the steps you
can take to upgrade to the new properties.
1. Using jscodeshift
The most simple use cases can be replaced by running a
jscodeshift script.
This script also removes instances of
AccessibilityComponentType (assuming
everywhere you set
AccessibilityComponentType, you would also
set AccessibilityTraits).
2. Using a manual codemod
For the cases that used
AccessibilityTraits that don't have a
corresponding value for AccessibilityRole,
and the cases where multiple traits were passed into
AccessibilityTraits, a manual codemod would
have to be done.
These properties are already being used in Facebook's
codebase. The codemod for Facebook was surprisingly
simple. The jscodeshift script fixed about half of our
instances, and the other half was fixed manually.
Overall, the entire process took less than a few hours.
Hopefully you will find the updated API useful! And
please continue making apps accessible! #inclusion