Expo Desktop

Prebuild

Generating the native projects from the app config

Expo Desktop fully implements Expo Prebuild for macOS and Windows (in addition to Android and iOS), allowing you to generate the Xcode and MSBuild projects (i.e. the macos and windows folders) based on the contents of your app.json and adopt Continuous Native Generation (CNG).

Running the prebuild

Run the command from your app's root directory to prebuild all platforms:

node --run prebuild

This generates the android, ios, macos, and windows folders, as supported (some prebuild operations require native build toolchains, so, for example, you can't prebuild for iOS or macOS on Windows. If an incompatible target is requested, it will be skipped).

Specifying platforms (--platform)

You can prebuild just a subset of the platforms if preferred, though:

# Individual platforms
node --run prebuild -- --platform android
node --run prebuild -- --platform ios
node --run prebuild -- --platform macos
node --run prebuild -- --platform windows

# macOS and Windows
node --run prebuild -- --platform desktop

# iOS and Android
node --run prebuild -- --platform mobile

# All platforms configured in app.json
node --run prebuild

# All platforms, unconditionally
node --run prebuild -- --platform all

Clean prebuilds (--clean)

A "clean" prebuild is when the native folder (e.g. macos, windows, etc.) is deleted and the config plugins are run upon a "clean" template, rather than reusing the existing "dirty" template.

node --run prebuild -- --clean

Skipping installs (--no-install)

Skip the install of npm packages and CocoaPods pods. This is mainly useful when developing your own custom config plugin, to avoid an unnecessary wait for the results of the prebuild.

node --run prebuild -- --no-install

Installing with a specific package manager (--npm, --yarn, --bun, --pnpm)

Running a prebuild may sometimes result in node modules being installed. This flag lets you specify which package manager to use:

node --run prebuild -- --bun

By default, it chooses the appropriate package manager based on an existing lockfile (e.g. it will choose Bun if it finds a bun.lock), though. So this flag is only really relevant in the unusual case that no lockfile is present.

Specifying a prebuild template (--template <template>)

By default, Expo Desktop prebuilds from expo-desktop-template-bare-minimum (hence why we add it to devDependencies in our blank-typescript app template - the Expo Desktop CLI pulls it out of node_modules), but you can specify a custom template if preferred.

# Specify a custom template…

# …via URL:
node --run prebuild -- --template https://github.com/shirakaba/expo-desktop/tree/main/templates/bare-minimum

# …via npm:
node --run prebuild -- --template expo-desktop-template-bare-minimum@latest

# …via file system:
node --run prebuild -- --template ./expo-desktop-template-bare-minimum-55.83.1.tgz

I recommend my talk Expo Prebuild, Demystified to understand how it all works! Slides here.

Skipping dependency updates (--skip-dependency-update)

Running a prebuild may update your package.json to ensure that any dependencies listed by your prebuild template are added into your project. You can skip this if you'd prefer to override those dependencies.

node --run prebuild -- --skip-dependency-update