PR
Expo bareExpo RouterReact Navigation

Expo Router・TypeScriptで開発環境を作る〜Expo bare〜

expo-router-eye-catch Expo bare

この記事は Expo SDK 49 時点の記録です(2026 年 7 月 追記)

Expo Router でファイルベースルーティングを組む、という流れは今も同じです。ただし本文で設定している項目のうち 3 つが、現在は不要になっています。そのまま書くと警告が出るものもあるので、先にまとめます。

1. babel.config.js の expo-router/babel は削除してください

本文では次のように追加していますが、SDK 50 でこのプラグインは babel-preset-expo に統合されました。

plugins: ['expo-router/babel'],   // ← SDK 50 以降は不要

残しておくと、次のようなメッセージが出ます。

[BABEL]: expo-router/babel is deprecated in favor of babel-preset-expo in SDK 50.
To fix this issue, remove "expo-router/babel" from "plugins" in your babel.config.js file

さらに言えば、ほかにカスタム設定がなければ babel.config.js というファイル自体が不要です。公式ドキュメントでも、必要なければ削除してよいと案内されています。プリセットは babel-preset-expo が既定で使われます。

なお、Babel の設定を変えたときは Metro のキャッシュを消して再起動してください。変更が反映されずに悩むことがあります。

2. experiments.tsconfigPaths も不要です

本文では app.json に次を書いています。

"experiments": {"tsconfigPaths": true}   // ← SDK 50 以降は不要

SDK 49 では「実験的機能」としてオプトインが必要でしたが、SDK 50 からは既定で有効です。書かなくても tsconfig.json の paths が効きます。

3. path alias は接頭辞を付ける形が案内されています

本文では次のように、すべてのインポートを src 配下に向けています。

"paths": {"*": ["src/*"]}

これでも動きますが、現在の公式ドキュメントでは接頭辞を付けた書き方が案内されています。

{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true,
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"]
}

接頭辞があると、自分のコードなのか外部パッケージなのかが一目で分かります* をそのまま割り当てる形だと、パッケージ名と同じ名前のディレクトリを src 配下に作ったときに解決先が紛らわしくなります。これから書くなら @/ 形式をおすすめします。

include.expo/typesexpo-env.d.ts が入っている点にもご注意ください。Expo が自動生成する型定義を拾うために必要です。

4. Bare workflow という前提について

本文は android/ios/ を手元に置く構成(Bare)を前提にしています。現在の Expo は CNG(Continuous Native Generation)、つまりネイティブのディレクトリを設定ファイルから生成する方式が中心です。

CNG を使う場合、android/ios/ は生成物なので、直接編集しても次の生成で消えます。設定は app.json と config plugin 側で行います。どちらの構成で進めるかを最初に決めておくと、後で混乱しません。

※ 上記は 2026 年 7 月時点の Expo 公式ドキュメントの記述に基づく整理であり、当方の環境での再検証は行っていません。

スポンサーリンク

開発環境 (Expo Bare Workflow)

※ 全体参照:https://reactnative.dev/docs/environment-setup

下記のような開発環境で行います!(w/ VSCode)

try🐶everything myproject$ npx expo-env-info

  expo-env-info 1.0.5 environment info:
    System:
      OS: macOS 13.5.2
      Shell: 5.9 - /bin/zsh
    Binaries:
      Node: 20.7.0 - ~/.anyenv/envs/nodenv/versions/20.7.0/bin/node
      Yarn: 1.22.19 - ~/.anyenv/envs/nodenv/versions/20.7.0/bin/yarn
      npm: 10.1.0 - ~/.anyenv/envs/nodenv/versions/20.7.0/bin/npm
      Watchman: 2023.09.04.00 - /opt/homebrew/bin/watchman
    Managers:
      CocoaPods: 1.12.1 - /Users/xxxxx/.anyenv/envs/rbenv/shims/pod
    SDKs:
      iOS SDK:
        Platforms: DriverKit 23.0, iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0
      Android SDK:
        API Levels: 29, 30, 31, 32, 33
        Build Tools: 29.0.2, 30.0.2, 30.0.3, 31.0.0, 32.0.0, 33.0.0
        System Images: android-29 | Google APIs ARM 64 v8a, android-29 | Google APIs Intel x86 Atom, android-30 | Intel x86 Atom_64, android-30 | Google APIs Intel x86 Atom, android-31 | Google APIs ARM 64 v8a, android-32 | Google APIs ARM 64 v8a, android-33 | Google APIs ARM 64 v8a
    IDEs:
      Android Studio: 2022.3 AI-223.8836.35.2231.10671973
      Xcode: 15.0/15A240d - /usr/bin/xcodebuild
    npmPackages:
      expo: ~49.0.11 => 49.0.11 
      react: 18.2.0 => 18.2.0 
      react-native: 0.72.4 => 0.72.4 
    Expo Workflow: bare

try🐶everything myproject$ 

それでは、Expo bare 環境を作成 > TypeScript 環境に変更 順に進めて行きます。

新しいプロジェクトを作成する

※ 全体参照:https://docs.expo.dev/routing/installation/

try🐶everything ReactNative$ npx create-expo-app --template
Need to install the following packages:
  create-expo-app@2.1.1
Ok to proceed? (y) y
? Choose a template: › - Use arrow-keys. Return to submit.
    Blank
    Blank (TypeScript)
    Navigation (TypeScript)
❯   Blank (Bare) - blank app with the native code exposed (expo prebuild)    // <- Blank (Bare) を選択する

✔ Choose a template: › Blank (Bare)
✔ What is your app named? … casablanca     // <-- 適宜入力する(casablanca)
✔ Downloaded and extracted project files.
> npm install
...
Installing CocoaPods     // <-- ☕️ 初めての設置であれば時間がかかル!
...
- cd casablanca
- npm run android
- npm run ios- npm run web
...
try🐶everything casablanca$ yarn ios  // <-- OR, yarn android
try🐶everything casablanca2$ yarn start

プロジェクトを TypeScript 環境に変更する

※ 全体参照:https://github.com/expo/examples/tree/master/with-typescript#adding-typescript-to-existing-projects

try🐶everything ReactNative$ cd casablanca
try🐶everything casablanca$ touch tsconfig.json
try🐶everything casablanca$ yarn start   // <--実行すると必要なdependenciesをチェックしてくれます
yarn run v1.22.19
$ expo start --dev-client
Starting project at /Users/jacepark/ReactNative/casablanca
Starting Metro Bundler
✔ It looks like you're trying to use TypeScript but don't have the required dependencies installed. Would you like to install typescript@^5.1.3,
@types/react@~18.2.14? … yes   // <-- yes? dependenciesへ設置、 no? devDependenciesへ手動設置可能!

› Installing 2 SDK 49.0.0 compatible native modules using npm
> npm install
...

try🐶everything casablanca$ yarn add -D typescript @types/react  // <-- devDependenciesに設置する

タイプチェックを設定する

※ 全体参照:https://docs.expo.dev/guides/typescript/

package.json の script 部分に下記のように追加するとプロジェクト全体のファイルのタイプチェックができるので設定しておけば便利です。

{
  "scripts": {
    "ts:check": "tsc"
    ... 
  }
}

yarn tscコマンドを実行すると、下記のようにプロジェクトファイルのタイプチェックができます。

try🐶everything casablanca$ yarn tsc
yarn run v1.22.19
$ tsc
app/textRecognition.tsx:18:40 - error TS2552: Cannot find name 'TextRecognitionResult'. Did you mean 'SpeechRecognitionResult'?

18   const [result, setResult] = useState<TextRecognitionResult>();
                                          ~~~~~~~~~~~~~~~~~~~~~
...

Path aliases を設定する

※ 全体参照:https://docs.expo.dev/guides/typescript/#path-aliases

src ディレクトリを⬇︎のように作成します。

try🐶everything casablanca$ tree src
src
├── common
│   ├── assets
│   │   ├── fonts
│   │   │   └── SpaceMono-Regular.ttf
│   │   └── images
│   │       ├── adaptive-icon.png
│   │       ├── favicon.png
│   │       ├── icon.png
│   │       └── splash.png
│   └── constants
│       ├── colors.ts
│       └── index.ts
└── components
    ├── EditScreenInfo.tsx
    ├── StyledText.tsx
    └── Themed.tsx

6 directories, 11 files
try🐶everything casablanca$ 

tsconfig.jsonファイルに"paths": {"": ["src/"]}のように追加します。

// tsconfig.json

{
  "compilerOptions": {
    "strict": true,
    "baseUrl": ".",
    "paths": {"*": ["src/*"]}
  },
  "extends": "expo/tsconfig.base"
}

$ npx expo start コマンドでメトロサーバを再起動します。

以降、Line5、6 のような使い方ができます。

import React from 'react';
import {StatusBar} from 'expo-status-bar';
import {Platform, StyleSheet} from 'react-native';
import EditScreenInfo from 'components/EditScreenInfo';   // 👍 'src/components/EditScreenInfo' --> 'components/EditScreenInfo'
import {Text, View} from 'components/Themed';
...

Expo Router v2 を設定する

※ 全体参照:https://docs.expo.dev/routing/installation/#quick-start

expo-router-enabled-with-memo
まだ、appディレクトリが作成されていない場合
expo-router-first-page
expo-routerの設定&初期ページを作成した場合

Expo Router 設置

try🐶everything casablanca$ npx expo install expo-router react-native-safe-area-context react-native-screens expo-linking expo-constants expo-status-bar react-native-gesture-handler
try🐶everything casablanca$ npx pod-install
try🐶everything casablanca$ yarn ios  // <-- OR, yarn android

Entry point を設定する

// package.json

{
  "name": "casablanca",
  "version": "1.0.0",
  "main": "expo-router/entry",  // <-- 編集
...

Enty Point を変更すると、既存の App.js index.js ファイルは不要になるので削除しても構いません。最初のクライアントファイルは app/_layout.ts に変わります。

プロジェクト設定を変更する

// app.json

{
  "expo": {
    "name": "casablanca",
    "slug": "casablanca",
    "version": "1.0.0",
    "assetBundlePatterns": ["**/*"],
    "plugins": ["expo-router"],
    "scheme": "csblanca",  // <--追加する
    "experiments": {"tsconfigPaths": true}
  }
}
...

babel.config.jsファイルを変更する

module.exports = function (api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: ['expo-router/babel'],   // <-- 追加
   ;
};

ページを作成する

※ ページとは:https://docs.expo.dev/routing/create-pages/#pages

app ディレクトリを⬇︎のように作成します。

try🐶everything casablanca$ tree app
app
├── (tabs)
│   ├── _layout.tsx
│   ├── index.tsx
│   └── two.tsx
├── [...missing].tsx
├── _layout.tsx
└── modal.tsx

1 directory, 6 files
try🐶everything casablanca$ 

iOS シミュレーター・Androidエミュレーターなどで動作を確認します。

あとがき

今までは、Expo & React Native アプリのルーティングとナビゲーションは React Navigation を使用していましたが、設定項目が多い・設定ファイル数が多いなど煩わしさを感じていたところでした。

一方、Expo Router は同じく Expo チームの React Navigation に基づいて構築されていてファイルベース (file-base) のルーターなのでその設定のシンプルさやナビゲーションのスピードなどに期待できるかと。

Expo Router は React Navigation の進化版であって欲しいですね。

※ ちなみに、src や app ディレクトリ下のファイルは npx create-expo-app --template > Navigation (TypeScript) コマンドを実行し作成したプロジェクトのファイルを再利用しています!(⬇︎)

try🐶everything ReactNative$ npx create-expo-app --template
? Choose a template: › - Use arrow-keys. Return to submit.
    Blank
    Blank (TypeScript)
❯   Navigation (TypeScript) - File-based routing with TypeScript enabled  // <-- 選択
    Blank (Bare)

スポンサーリンク

コメント

タイトルとURLをコピーしました