Use lazy getters to reduce `require('react-native')` overhead

Summary:
public

In the open source React Native implementation, the recommended approach for importing modules is by importing a the `ReactNative` object, which includes all available modules.

This is rather inefficient because it ends up initializing all the JS modules, even if you don't use them.

This diff switches the properties of the `ReactNative ` object to lazy getter functions, which defers the `require` until the module is actually requested.

This doesn't prevent unused modules from being included in the JS bundle, but it will prevent them from being initialized unless/until they are used.

Reviewed By: vjeux

Differential Revision: D2722993

fb-gh-sync-id: 0e9a2beb3aa6cd087a0592bd59a8f9242040be0c
This commit is contained in:
Nick Lockwood 2015-12-07 16:54:18 -08:00 коммит произвёл facebook-github-bot-5
Родитель 0f98dedefe
Коммит f9b744d501
1 изменённых файлов: 89 добавлений и 85 удалений

174
Libraries/react-native/react-native.js поставляемый
Просмотреть файл

@ -6,110 +6,114 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @noflow - get/set properties not yet supported by flow. also `...require(x)` is broken #6560135
*/
'use strict';
// Export React, plus some native additions.
//
// The use of Object.create/assign is to work around a Flow bug (#6560135).
// Once that is fixed, change this back to
//
// var ReactNative = {...require('React'), /* additions */}
//
var ReactNative = Object.assign(Object.create(require('React')), {
var ReactNative = {
// Components
ActivityIndicatorIOS: require('ActivityIndicatorIOS'),
ART: require('ReactNativeART'),
DatePickerIOS: require('DatePickerIOS'),
DrawerLayoutAndroid: require('DrawerLayoutAndroid'),
Image: require('Image'),
ListView: require('ListView'),
MapView: require('MapView'),
Modal: require('Modal'),
Navigator: require('Navigator'),
NavigatorIOS: require('NavigatorIOS'),
PickerIOS: require('PickerIOS'),
ProgressBarAndroid: require('ProgressBarAndroid'),
ProgressViewIOS: require('ProgressViewIOS'),
ScrollView: require('ScrollView'),
SegmentedControlIOS: require('SegmentedControlIOS'),
SliderIOS: require('SliderIOS'),
SnapshotViewIOS: require('SnapshotViewIOS'),
Switch: require('Switch'),
PullToRefreshViewAndroid: require('PullToRefreshViewAndroid'),
SwitchAndroid: require('SwitchAndroid'),
SwitchIOS: require('SwitchIOS'),
TabBarIOS: require('TabBarIOS'),
Text: require('Text'),
TextInput: require('TextInput'),
ToastAndroid: require('ToastAndroid'),
ToolbarAndroid: require('ToolbarAndroid'),
Touchable: require('Touchable'),
TouchableHighlight: require('TouchableHighlight'),
TouchableNativeFeedback: require('TouchableNativeFeedback'),
TouchableOpacity: require('TouchableOpacity'),
TouchableWithoutFeedback: require('TouchableWithoutFeedback'),
View: require('View'),
ViewPagerAndroid: require('ViewPagerAndroid'),
WebView: require('WebView'),
get ActivityIndicatorIOS() { return require('ActivityIndicatorIOS'); },
get ART() { return require('ReactNativeART'); },
get DatePickerIOS() { return require('DatePickerIOS'); },
get DrawerLayoutAndroid() { return require('DrawerLayoutAndroid'); },
get Image() { return require('Image'); },
get ListView() { return require('ListView'); },
get MapView() { return require('MapView'); },
get Modal() { return require('Modal'); },
get Navigator() { return require('Navigator'); },
get NavigatorIOS() { return require('NavigatorIOS'); },
get PickerIOS() { return require('PickerIOS'); },
get ProgressBarAndroid() { return require('ProgressBarAndroid'); },
get ProgressViewIOS() { return require('ProgressViewIOS'); },
get ScrollView() { return require('ScrollView'); },
get SegmentedControlIOS() { return require('SegmentedControlIOS'); },
get SliderIOS() { return require('SliderIOS'); },
get SnapshotViewIOS() { return require('SnapshotViewIOS'); },
get Switch() { return require('Switch'); },
get PullToRefreshViewAndroid() { return require('PullToRefreshViewAndroid'); },
get SwitchAndroid() { return require('SwitchAndroid'); },
get SwitchIOS() { return require('SwitchIOS'); },
get TabBarIOS() { return require('TabBarIOS'); },
get Text() { return require('Text'); },
get TextInput() { return require('TextInput'); },
get ToastAndroid() { return require('ToastAndroid'); },
get ToolbarAndroid() { return require('ToolbarAndroid'); },
get Touchable() { return require('Touchable'); },
get TouchableHighlight() { return require('TouchableHighlight'); },
get TouchableNativeFeedback() { return require('TouchableNativeFeedback'); },
get TouchableOpacity() { return require('TouchableOpacity'); },
get TouchableWithoutFeedback() { return require('TouchableWithoutFeedback'); },
get View() { return require('View'); },
get ViewPagerAndroid() { return require('ViewPagerAndroid'); },
get WebView() { return require('WebView'); },
// APIs
ActionSheetIOS: require('ActionSheetIOS'),
AdSupportIOS: require('AdSupportIOS'),
AlertIOS: require('AlertIOS'),
Animated: require('Animated'),
AppRegistry: require('AppRegistry'),
AppStateIOS: require('AppStateIOS'),
AsyncStorage: require('AsyncStorage'),
BackAndroid: require('BackAndroid'),
CameraRoll: require('CameraRoll'),
Dimensions: require('Dimensions'),
Easing: require('Easing'),
ImagePickerIOS: require('ImagePickerIOS'),
IntentAndroid: require('IntentAndroid'),
InteractionManager: require('InteractionManager'),
LayoutAnimation: require('LayoutAnimation'),
LinkingIOS: require('LinkingIOS'),
NetInfo: require('NetInfo'),
PanResponder: require('PanResponder'),
PixelRatio: require('PixelRatio'),
PushNotificationIOS: require('PushNotificationIOS'),
Settings: require('Settings'),
StatusBarIOS: require('StatusBarIOS'),
StyleSheet: require('StyleSheet'),
UIManager: require('UIManager'),
VibrationIOS: require('VibrationIOS'),
get ActionSheetIOS() { return require('ActionSheetIOS'); },
get AdSupportIOS() { return require('AdSupportIOS'); },
get AlertIOS() { return require('AlertIOS'); },
get Animated() { return require('Animated'); },
get AppRegistry() { return require('AppRegistry'); },
get AppStateIOS() { return require('AppStateIOS'); },
get AsyncStorage() { return require('AsyncStorage'); },
get BackAndroid() { return require('BackAndroid'); },
get CameraRoll() { return require('CameraRoll'); },
get Dimensions() { return require('Dimensions'); },
get Easing() { return require('Easing'); },
get ImagePickerIOS() { return require('ImagePickerIOS'); },
get IntentAndroid() { return require('IntentAndroid'); },
get InteractionManager() { return require('InteractionManager'); },
get LayoutAnimation() { return require('LayoutAnimation'); },
get LinkingIOS() { return require('LinkingIOS'); },
get NetInfo() { return require('NetInfo'); },
get PanResponder() { return require('PanResponder'); },
get PixelRatio() { return require('PixelRatio'); },
get PushNotificationIOS() { return require('PushNotificationIOS'); },
get Settings() { return require('Settings'); },
get StatusBarIOS() { return require('StatusBarIOS'); },
get StyleSheet() { return require('StyleSheet'); },
get UIManager() { return require('UIManager'); },
get VibrationIOS() { return require('VibrationIOS'); },
// Plugins
DeviceEventEmitter: require('RCTDeviceEventEmitter'),
NativeAppEventEmitter: require('RCTNativeAppEventEmitter'),
NativeModules: require('NativeModules'),
Platform: require('Platform'),
processColor: require('processColor'),
requireNativeComponent: require('requireNativeComponent'),
get DeviceEventEmitter() { return require('RCTDeviceEventEmitter'); },
get NativeAppEventEmitter() { return require('RCTNativeAppEventEmitter'); },
get NativeModules() { return require('NativeModules'); },
get Platform() { return require('Platform'); },
get processColor() { return require('processColor'); },
get requireNativeComponent() { return require('requireNativeComponent'); },
// Prop Types
EdgeInsetsPropType: require('EdgeInsetsPropType'),
PointPropType: require('PointPropType'),
get EdgeInsetsPropType() { return require('EdgeInsetsPropType'); },
get PointPropType() { return require('PointPropType'); },
// See http://facebook.github.io/react/docs/addons.html
addons: {
LinkedStateMixin: require('LinkedStateMixin'),
get LinkedStateMixin() { return require('LinkedStateMixin'); },
Perf: undefined,
PureRenderMixin: require('ReactComponentWithPureRenderMixin'),
TestModule: require('NativeModules').TestModule,
get PureRenderMixin() { return require('ReactComponentWithPureRenderMixin'); },
get TestModule() { return require('NativeModules').TestModule; },
TestUtils: undefined,
batchedUpdates: require('ReactUpdates').batchedUpdates,
cloneWithProps: require('cloneWithProps'),
createFragment: require('ReactFragment').create,
update: require('update'),
get batchedUpdates() { return require('ReactUpdates').batchedUpdates; },
get cloneWithProps() { return require('cloneWithProps'); },
get createFragment() { return require('ReactFragment').create; },
get update() { return require('update'); },
},
});
// Note: this must be placed last to prevent eager
// evaluation of the getter-wrapped submodules above
...require('React'),
};
if (__DEV__) {
ReactNative.addons.Perf = require('ReactDefaultPerf');
ReactNative.addons.TestUtils = require('ReactTestUtils');
Object.defineProperty(ReactNative.addons, 'Perf', {
enumerable: true,
get: () => require('ReactDefaultPerf'),
});
Object.defineProperty(ReactNative.addons, 'TestUtils', {
enumerable: true,
get: () => require('ReactTestUtils'),
});
}
module.exports = ReactNative;