HotupdaterHot Updater
Build Plugins

Expo Plugin

Build plugin for Expo projects. Bundles your Expo app using Expo's native export command.

Installation

npm install @hot-updater/expo --save-dev

Configuration

interface ExpoPluginConfig {
  outDir?: string;      // Output directory (default: "dist")
  sourcemap?: boolean;  // Generate sourcemaps (default: false)
}

Usage

import { expo } from '@hot-updater/expo';
import { defineConfig } from 'hot-updater';

export default defineConfig({
  build: expo({
    sourcemap: false
  }),
  // ... other config
});

Expo Configuration

Add the plugin to your app.json file as shown below:

app.json
{
  "expo": {
    "plugins": [
      [
        "@hot-updater/react-native", 
        { 
          "channel": "production"
        } 
      ] 
    ]
  }
}

Run prebuild to apply the changes:

npx expo prebuild

Run the following command to customize your Babel configuration:

npx expo customize babel.config.js

Add the following to your babel.config.js file:

babel.config.js
module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: [
    'hot-updater/babel-plugin', 
  ],
};

Expo DOM Components (use dom)

Note: This setup is only required for Expo SDK < 55. Expo SDK 55+ includes native overrideUri support (PR #40397).

Expo DOM components are designed for EAS Update. Hot Updater uses overrideUri internally (via Babel plugin) to redirect DOM components to the correct bundle path.

Apply patch

Modify node_modules/expo/src/dom/dom.types.ts:

export interface DOMProps extends Omit<RNWebViewProps, 'source'> {
   /**
    * Whether to resize the native WebView size based on the DOM content size.
    * @default false
    */
   matchContents?: boolean;

   /**
    * Whether to use the `@expo/dom-webview` as the underlying WebView implementation.
    * @default false
    */
   useExpoDOMWebView?: boolean;
+
+  /**
+   * Allows dynamically redirecting a component to a different source, for example a prebuilt version.
+   * @internal
+   */
+  overrideUri?: string;
 }

Modify node_modules/expo/build/dom/dom.types.d.ts:

export interface DOMProps extends Omit<RNWebViewProps, 'source'> {
     /**
      * @default false
      */
     matchContents?: boolean;
     /**
      * Whether to use the `@expo/dom-webview` as the underlying WebView implementation.
      * @default false
      */
     useExpoDOMWebView?: boolean;
+    /**
+     * Allows dynamically redirecting a component to a different source, for example a prebuilt version.
+     * @internal
+     */
+    overrideUri?: string;
 }

Modify node_modules/expo/src/dom/webview-wrapper.tsx:

 const RawWebView = React.forwardRef<object, Props>((props, ref) => {
-  const { children, dom, filePath, ref: _ref, ...marshalProps } = props as Props;
+  const { children, dom: domProps, filePath, ref: _ref, ...marshalProps } = props as Props;
+  const { overrideUri, ...dom } = domProps || {};
   if (__DEV__) {
     if (children !== undefined) {
       throw new Error(
   const webView = resolveWebView(dom?.useExpoDOMWebView ?? false);
   const webviewRef = React.useRef<WebViewRef>(null);
   const domImperativeHandlePropsRef = React.useRef<string[]>([]);
-  const source = { uri: `${getBaseURL()}/${filePath}` };
+  const source = { uri: overrideUri ?? `${getBaseURL()}/${filePath}` };
   const [containerStyle, setContainerStyle] = React.useState<WebViewProps['containerStyle']>(null);

Persist changes

Use patch-package, yarn patch, or pnpm patch to persist these changes across installs.

Using patch-package:

npm install patch-package --save-dev
npx patch-package expo

Add postinstall script:

package.json
{
  "scripts": {
    "postinstall": "patch-package"
  }
}

Using pnpm patch:

pnpm patch expo
# Make the changes above, then:
pnpm patch-commit <path-shown-in-output>

Using yarn patch:

yarn patch expo
# Make the changes above, then follow yarn's instructions

Once configured, the Babel plugin automatically handles overrideUri for all DOM components. No additional code changes required.

Key Features

  • Uses Expo's expo export:embed command
  • Auto-detects Hermes from app.json configuration
  • Supports both managed and bare Expo workflows
  • Compatible with Expo prebuild for native builds
  • Automatically configures bundler based on Expo settings