React Native at

The NetCircle

Tim Wang @timwangdev

Frontend Developer

The Status

  • 15 modules (auth, comments, profile, inbox...)
  • 30+ screens
  • 15000+ lines of TypeScript code
  • Build with react-native, redux, realm
  • Replaced previous native modules with JavaScript implementation

The Good Parts

  • Code Sharing

    • Bustiness Logic: 100%
    • UI Code: Up to 95%
      • Different UI decisions between Android and iOS
      • Wrapper for native modules in JavaScript side
    • Native Code: Only use for infrastructure, and connection with system call or native modules. 
    • Still exploring shareable module with the website but current web tech stack is quite old

Platform Specific Code Example

import { Platform, ActionSheetIOS } from 'react-native';
import BottomSheetAndroid from 'react-native-bottom-sheet';
import trans from '@/core/i18n';

const showSheet = Platform.OS === 'android'
    ? BottomSheetAndroid.showBottomSheetWithOptions
    : ActionSheetIOS.showActionSheetWithOptions;
const options: Array<string> = [
    trans('B_VIEW_PROFILE'),
    trans('B_SEND_NO_THANKS'),
    trans('B_HIDE'),
    trans('B_DELETE'),
    trans('B_CANCEL'),
];

// class ... {

private onButtonPress = () => {
    showSheet({ options }, callbacks);
}
  • React

    • React is still great declarative library for building user interface
  • Native Integration

    • Almost* everything can be bridged to native code, which provides easy binding with platform APIs and native libraries.
  • Performance

    • Works great in most cases
    • Common optimization for React app still valid
    • Bottleneck usually comes from "the bridge"

OSS Community (JavaScript/React)

Source: The State of the Octoverse 2017 (https://octoverse.github.com/)

  • Open Source Community

    • Large community
      • facebook/react-native has the second most contributors on Github in 2017
    • Cross platform libraries
    • Tooling
      • yarn, jest, babel, typescript
    • Third-party support (Microsoft, CircleCI, Bitrise, etc.)
    • Commercial-friendly licenses (MIT)
    • Contribute back to upstream

The "🤔" Parts

JavaScript

  • TypeScript

    • helps us a lot with build time type checking
    • Require additional step to set up
    • Types for third-party module may not being
      accurate
    • Use with self-restriction (`any`)
    • DevTools (source-map) may experience line number shift issues
// Example.ts

let foo = '12'; // Type inference as string
foo = 42; // Error: Type '42' is not assignable to type 'string'.

let bar: any = '12';
bar = 42; // No error
  • The "npm" issue

    • Don't mix `yarn` with `npm`

    • Use `yarn.lock`

    • Lock version for package contains native code

    • Explicit dependencies version (babel@7)
  • Use Linter

    • Avoid using bad language features (`==`)
    • Avoid common mistakes
    • Provide unified code style across the team members
  • Patch/Fork Broken Modules

    • patch-package
    • Self-maintained type definitions
    • Make pull requests when appropriate
  • Use Latest Language Feature

  • React Navigation

    • No official navigation solution from RN
    • Community-driven project
    • Implemented in JavaScript
      • More flexibility
      • No standard native widgets
    • Moving fast but brings lots of breaking changes
    • We maintained a fork to custom some usage for v1, but we'd like to follow the official release for v2.

The Pit 🙁

  • Native Development Experience

    • One repository contains three environments code (And submodule structure didn't work so well)
    • Dose not following native package conventions (CocoaPods/Maven)
    • Lack of documentation
    • Tools always make assumption of project structure
  • Android Build

    • Outdated tooling version (gradle 3.5.+)
    • Outdated JavaScriptCore version
    • Yoga minimal bugs (inconsistent with iOS)
  • Developer Requirement

    • Objective-C/Java knowledge is required to debug native errors
    • Xcode/Android Studio experience
    • Code sign and release process
  • Mix RN and Native Screens

    • Integration with exist apps (brown field)
    • Sync navigation state between native and JavaScript realm is very hard
    • Poor react native bridge performance
  • Debug experience

    • Remote debugger in Chrome is unstable, it's runs on browser environment and V8 engine
    • Use Safari inspect tools
    • Sourcemap is not reliable (TypeScript transformer issue)
    • console.log is still the best way
  • Upgrading React Native

    • Native APIs has no guarantee of backward compatibility
    • Patching core framework is hard
    • Upgrade every two minor release (eg. 0.54.* => 0.56.*)
  • App Size

    • Framework take the size about 12Mb, although JS bundle may only have 2Mb minified
  • Additional Memory Usage

The Future* and Beyond

  • "Rearchitecture" React Native

    • The ​bridge
    • Threading modal
    • Async rendering (Likely land in React 17)
  • Collaboration with the Project

    • Actively track issues/ new fix/ releases
    • Communication with core team
  • Make Native Packages

    • Isolating developer environment
    • Better upgrade path

Universal UI Development

  • JavaScript Environment

    • JS engine is cross-platform fast and lightweight
    • Universal modules (No browser/node required)
    • Single thread and event loop modal is great for client-side applications
    • TypeScript gives the typing check feature but still keeps the flexibility (deno)
  • React Primitive

    • ​Virtual DOM isolating pure render logic
    • react-reconciler
    • React Native async rendering modal
    • Use <View/>, <Text/>, <Image/> everywhere
    • Use "Native" module to access the platform
    • Windows/ macOS/ Web/ SVG/ VR/ AR and more

References

React Native at The NetCircle

By Tim Wang

React Native at The NetCircle

  • 2,116