From 23e3503dde5f914f3e642ef214f508d0a699851d Mon Sep 17 00:00:00 2001 From: James Ide Date: Tue, 12 Mar 2019 20:29:31 -0700 Subject: [PATCH] Default to lazy requires for all public RN exports (#362) Summary: **Summary** This commit changes `metro-react-native-babel-preset` to emit lazy `require` calls for all of RN's public exports. This is so that we can move RN to use ES import/export, which syntactically have no lazy version, while preserving the lazy behavior we have today by default. If the developer specifies `lazyImportExportTransform: true`, all imports/exports will be lazy including RN's public exports, so they will remain lazy. (Also, this PR allows developers to specify non-boolean values for `lazyImportExportTransform` e.g. an array of whitelisted paths.) Note: this commit must land and be published before RN can use ESM since the iOS E2E tests depend on the current lazy `require` calls. See the draft PR for RN here: https://github.com/facebook/react-native/pull/23591 **Test plan** Used this module inside of the RN E2E iOS tests and loaded the bundle successfully. Also used it in RNTester. Pull Request resolved: https://github.com/facebook/metro/pull/362 Differential Revision: D14434999 Pulled By: cpojer fbshipit-source-id: d280a8216c6e1c6604e8fea508f5a48f4c1c071b --- .../src/configs/lazy-imports.js | 115 ++++++++++++++++++ .../src/configs/main.js | 7 +- 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 packages/metro-react-native-babel-preset/src/configs/lazy-imports.js diff --git a/packages/metro-react-native-babel-preset/src/configs/lazy-imports.js b/packages/metro-react-native-babel-preset/src/configs/lazy-imports.js new file mode 100644 index 0000000000..6cbdf119f2 --- /dev/null +++ b/packages/metro-react-native-babel-preset/src/configs/lazy-imports.js @@ -0,0 +1,115 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * This is the set of modules that React Native publicly exports and that we + * want to require lazily. Keep this list in sync with + * Libraries/react-native/react-native-implementation.js (though having extra + * entries here is fairly harmless). + + * @format + */ +'use strict'; + +module.exports = new Set([ + 'AccessibilityInfo', + 'ActivityIndicator', + 'ReactNativeART', + 'Button', + 'CheckBox', + 'DatePickerIOS', + 'DrawerLayoutAndroid', + 'FlatList', + 'Image', + 'ImageBackground', + 'ImageEditor', + 'ImageStore', + 'InputAccessoryView', + 'KeyboardAvoidingView', + 'ListView', + 'MaskedViewIOS', + 'Modal', + 'Picker', + 'PickerIOS', + 'ProgressBarAndroid', + 'ProgressViewIOS', + 'SafeAreaView', + 'ScrollView', + 'SectionList', + 'SegmentedControlIOS', + 'Slider', + 'Switch', + 'RefreshControl', + 'StatusBar', + 'SwipeableFlatList', + 'SwipeableListView', + 'Text', + 'TextInput', + 'ToolbarAndroid', + 'Touchable', + 'TouchableHighlight', + 'TouchableNativeFeedback', + 'TouchableOpacity', + 'TouchableWithoutFeedback', + 'View', + 'ViewPagerAndroid', + 'VirtualizedList', + 'WebView', + + // APIs + 'ActionSheetIOS', + 'Alert', + 'Animated', + 'AppRegistry', + 'AppState', + 'AsyncStorage', + 'BackHandler', + 'CameraRoll', + 'Clipboard', + 'DatePickerAndroid', + 'DeviceInfo', + 'Dimensions', + 'Easing', + 'ReactNative', + 'I18nManager', + 'ImagePickerIOS', + 'InteractionManager', + 'Keyboard', + 'LayoutAnimation', + 'Linking', + 'NativeEventEmitter', + 'NetInfo', + 'PanResponder', + 'PermissionsAndroid', + 'PixelRatio', + 'PushNotificationIOS', + 'Settings', + 'Share', + 'StatusBarIOS', + 'StyleSheet', + 'Systrace', + 'TimePickerAndroid', + 'ToastAndroid', + 'TVEventHandler', + 'UIManager', + 'ReactNative', + 'UTFSequence', + 'Vibration', + 'YellowBox', + + // Plugins + 'RCTDeviceEventEmitter', + 'RCTNativeAppEventEmitter', + 'NativeModules', + 'Platform', + 'processColor', + 'requireNativeComponent', + + // Prop Types + 'DeprecatedColorPropType', + 'DeprecatedEdgeInsetsPropType', + 'DeprecatedPointPropType', + 'DeprecatedViewPropTypes', +]); diff --git a/packages/metro-react-native-babel-preset/src/configs/main.js b/packages/metro-react-native-babel-preset/src/configs/main.js index b1d3beebdf..8600a756aa 100644 --- a/packages/metro-react-native-babel-preset/src/configs/main.js +++ b/packages/metro-react-native-babel-preset/src/configs/main.js @@ -9,6 +9,8 @@ 'use strict'; +const lazyImports = require('./lazy-imports'); + function isTypeScriptSource(fileName) { return !!fileName && fileName.endsWith('.ts'); } @@ -93,7 +95,10 @@ const getPreset = (src, options) => { { strict: false, strictMode: false, // prevent "use strict" injections - lazy: !!(options && options.lazyImportExportTransform), + lazy: + options && options.lazyImportExportTransform != null + ? options.lazyImportExportTransform + : importSpecifier => lazyImports.has(importSpecifier), allowTopLevelThis: true, // dont rewrite global `this` -> `undefined` }, ],