|
| 1 | +--- |
| 2 | +title: Install Expo modules |
| 3 | +sidebar_position: 2 |
| 4 | +--- |
| 5 | + |
| 6 | +:::info |
| 7 | +macOS support for Expo modules is currently experimental. |
| 8 | +::: |
| 9 | + |
| 10 | +To use Expo modules in your app, you will need to install and configure the `expo` package. |
| 11 | + |
| 12 | +The `expo` package has a small footprint; it includes only a minimal set of packages that are needed in nearly every app and the module and autolinking infrastructure that other Expo SDK packages are built with. Once the `expo` package is installed and configured in your project, you can use `npx expo install` to add any other Expo module from the SDK. |
| 13 | + |
| 14 | +The following instructions apply to installing the latest version of Expo modules. For previous versions, check the |
| 15 | +Expo docs for compatibility for which [Expo SDK version depends on a React Native version](https://docs.expo.dev/versions/latest/#each-expo-sdk-version-depends-on-a-react-native-version). |
| 16 | + |
| 17 | +```shell |
| 18 | +npm install expo |
| 19 | +``` |
| 20 | + |
| 21 | +Once installation is complete, apply the changes from the following diffs to configure Expo modules in your project. This is expected to take about five minutes, and you may need to adapt it slightly depending on how customized your project is. |
| 22 | + |
| 23 | + |
| 24 | +### Configuration for macOS |
| 25 | + |
| 26 | +To configure your macOS project to use Expo modules, you'll need to make changes to the `Podfile` and your `AppDelegate`. |
| 27 | + |
| 28 | +Start by modifying your `Podfile` to use the `use_expo_modules!` directive. This will enable autolinking for Expo modules in your project. |
| 29 | + |
| 30 | +```diff macos/Podfile |
| 31 | ++require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking") |
| 32 | +require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' |
| 33 | + |
| 34 | + target 'myapp' do |
| 35 | +- config = use_native_modules! |
| 36 | ++ use_expo_modules! |
| 37 | ++ |
| 38 | ++ config_command = [ |
| 39 | ++ 'npx', |
| 40 | ++ 'expo-modules-autolinking', |
| 41 | ++ 'react-native-config', |
| 42 | ++ '--json', |
| 43 | ++ '--platform', |
| 44 | ++ 'ios' |
| 45 | ++ ] |
| 46 | ++ config = use_native_modules!(config_command) |
| 47 | + |
| 48 | + use_react_native!( |
| 49 | +- :path => '../node_modules/react-native-macos', |
| 50 | ++ :path => "#{config[:reactNativePath]}-macos", |
| 51 | +``` |
| 52 | + |
| 53 | +Optionally, you can also add additional delegate methods to your **AppDelegate.swift**. Some libraries may require them, so unless you have a good reason to leave them out, it is recommended to add them. [See delegate methods in AppDelegate.swift](https://github.com/expo/expo/blob/sdk-53/templates/expo-template-bare-minimum/ios/HelloWorld/AppDelegate.swift#L24-L42). |
| 54 | + |
| 55 | +The last step is to install the project's CocoaPods again to pull in Expo modules that are detected by `use_expo_modules!` directive that we added to the **Podfile**: |
| 56 | + |
| 57 | +```shell |
| 58 | +# Install pods |
| 59 | +npx pod-install |
| 60 | +``` |
| 61 | + |
| 62 | +### Configure Expo CLI for bundling on macOS |
| 63 | + |
| 64 | +We recommend using Expo CLI and related tooling configurations to bundle your app JavaScript code and assets. This adds support for using the `"main"` field in **package.json**. Not using Expo CLI for bundling may result in unexpected behavior. [Learn more about Expo CLI](https://docs.expo.dev/bare/using-expo-cli/). |
| 65 | + |
| 66 | +#### Use babel-preset-expo in your babel.config.js |
| 67 | +```diff babel.config.js |
| 68 | +- presets: ['module:@react-native/babel-preset'], |
| 69 | ++ presets: ['babel-preset-expo'], |
| 70 | +``` |
| 71 | + |
| 72 | +#### Extend expo/metro-config in your metro.config.js |
| 73 | + |
| 74 | +```diff metro.config.js |
| 75 | +-const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); |
| 76 | ++const { getDefaultConfig } = require('expo/metro-config'); |
| 77 | ++const { mergeConfig } = require('@react-native/metro-config'); |
| 78 | + |
| 79 | + /** |
| 80 | + * Metro configuration |
| 81 | +``` |
| 82 | + |
| 83 | +#### Configure macOS project to bundle with Expo CLI |
| 84 | + |
| 85 | +Replace the shell script under **Build Phases** > **Bundle React Native code and images** in Xcode with the following: |
| 86 | + |
| 87 | +```sh /bin/sh |
| 88 | +if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then |
| 89 | + source "$PODS_ROOT/../.xcode.env" |
| 90 | +fi |
| 91 | +if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then |
| 92 | + source "$PODS_ROOT/../.xcode.env.local" |
| 93 | +fi |
| 94 | + |
| 95 | +# The project root by default is one level up from the ios directory |
| 96 | +export PROJECT_ROOT="$PROJECT_DIR"/.. |
| 97 | + |
| 98 | +if [[ "$CONFIGURATION" = *Debug* ]]; then |
| 99 | + export SKIP_BUNDLING=1 |
| 100 | +fi |
| 101 | +if [[ -z "$ENTRY_FILE" ]]; then |
| 102 | + # Set the entry JS file using the bundler's entry resolution. |
| 103 | + export ENTRY_FILE="$("$NODE_BINARY" -e "require('expo/scripts/resolveAppEntry')" "$PROJECT_ROOT" ios relative | tail -n 1)" |
| 104 | +fi |
| 105 | + |
| 106 | +if [[ -z "$CLI_PATH" ]]; then |
| 107 | + # Use Expo CLI |
| 108 | + export CLI_PATH="$("$NODE_BINARY" --print "require.resolve('@expo/cli')")" |
| 109 | +fi |
| 110 | +if [[ -z "$BUNDLE_COMMAND" ]]; then |
| 111 | + # Default Expo CLI command for bundling |
| 112 | + export BUNDLE_COMMAND="export:embed" |
| 113 | +fi |
| 114 | + |
| 115 | +`"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"` |
| 116 | +``` |
| 117 | + |
| 118 | +And add support the `"main"` field in **package.json** by making the following change to **AppDelegate.swift**: |
| 119 | + |
| 120 | +```diff AppDelegate.swift |
| 121 | + override func bundleURL() -> URL? { |
| 122 | + #if DEBUG |
| 123 | +- RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") |
| 124 | ++ RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry") |
| 125 | + #else |
| 126 | + Bundle.main.url(forResource: "main", withExtension: "jsbundle") |
| 127 | + #endif |
| 128 | +``` |
| 129 | + |
| 130 | + |
| 131 | +## Usage |
| 132 | + |
| 133 | +### Verifying installation |
| 134 | + |
| 135 | +You can verify that the installation was successful by logging a value from [`expo-constants`](https://docs.expo.dev/versions/latest/sdk/constants). |
| 136 | + |
| 137 | +- Run `npx expo install expo-constants` |
| 138 | +- Then, run `npx expo run` and modify your app JavaScript code to add the following: |
| 139 | + |
| 140 | +```js |
| 141 | +import Constants from 'expo-constants'; |
| 142 | +console.log(Constants.systemFonts); |
| 143 | +``` |
| 144 | + |
| 145 | +### Using Expo SDK packages |
| 146 | + |
| 147 | +Once the `expo` package is installed and configured in your project, you can use `npx expo install` to add any other Expo module from the SDK. See [Using Expo Libraries](https://docs.expo.dev/workflow/using-libraries/) for more information. |
| 148 | + |
| 149 | +### Expo modules included in the `expo` package |
| 150 | + |
| 151 | +The following Expo modules are brought in as dependencies of the `expo` package: |
| 152 | + |
| 153 | +- [`expo-asset`](https://docs.expo.dev/versions/latest/sdk/asset) - A JavaScript-only package that builds around `expo-file-system` and provides a common foundation for assets across all Expo modules. |
| 154 | +- [`expo-constants`](https://docs.expo.dev/versions/latest/sdk/constants) - Provides access to the manifest. |
| 155 | +- [`expo-file-system`](https://docs.expo.dev/versions/latest/sdk/filesystem) - Interact with the device file system. Used by `expo-asset` and many other Expo modules. Commonly used directly by developers in application code. |
| 156 | +- [`expo-font`](https://docs.expo.dev/versions/latest/sdk/font) - Load fonts at runtime. This module is optional and can be safely removed, however; it is recommended if you use `expo-dev-client` for development and it is required by `@expo/vector-icons`. |
| 157 | +- [`expo-keep-awake`](https://docs.expo.dev/versions/latest/sdk/keep-awake) - Prevents your device from going to sleep while developing your app. This module is optional and can be safely removed. |
| 158 | + |
| 159 | +To exclude any of these modules, refer to the following guide on [excluding modules from autolinking](#excluding-specific-modules-from-autolinking). |
| 160 | + |
| 161 | +### Excluding specific modules from autolinking |
| 162 | + |
| 163 | +If you need to exclude native code from Expo modules you are not using, but were installed by other dependencies, you can use the [`expo.autolinking.exclude`](https://docs.expo.dev/modules/autolinking/#exclude) property in **package.json**: |
| 164 | + |
| 165 | +```json package.json |
| 166 | +{ |
| 167 | + "name": "...", |
| 168 | + "dependencies": {}, |
| 169 | + "expo": { |
| 170 | + "autolinking": { |
| 171 | + "exclude": ["expo-keep-awake"] |
| 172 | + } |
| 173 | + } |
| 174 | +} |
| 175 | +``` |
0 commit comments