◉RORK LABEN
●EXPO — EAS Observe がネイティブクラッシュも記録(10/07)。SDK 57 は 57.0.21 以降で確認できます●SDK 58 — SDK 58 Beta は 9/15 公開。stable の日付はまだ未確認です●RN 0.88 — React Native 0.88.x の正式リリース予定は 10/12、残り3日●Q&A — expo-widgets が本番ビルドだけ真っ黒になる、という問いが出ています●RORK — 09-29 に GPT-6.1 Sol を追加。Pro・Max プランで利用できます●NEW — クライアントのアプリを作る前に決める、公開アカウントの持ち主●EXPO — EAS Observe がネイティブクラッシュも記録(10/07)。SDK 57 は 57.0.21 以降で確認できます●SDK 58 — SDK 58 Beta は 9/15 公開。stable の日付はまだ未確認です●RN 0.88 — React Native 0.88.x の正式リリース予定は 10/12、残り3日●Q&A — expo-widgets が本番ビルドだけ真っ黒になる、という問いが出ています●RORK — 09-29 に GPT-6.1 Sol を追加。Pro・Max プランで利用できます●NEW — クライアントのアプリを作る前に決める、公開アカウントの持ち主
記事一覧/開発ツール
⬡ 開発ツール/2026-07-08中級

SVGアイコンがExpo Goでは出るのにビルドで消える — Rork製アプリでSVGを確実に表示する

Rork や Expo のアプリで .svg ファイルを import してもアイコンが表示されない、色が反映されないという問題を、metro.config.js と react-native-svg-transformer の設定、currentColor によるテーマ追従まで実際のコードで解決します。

トラブルシューティング81SVGExpo213React Native238アイコン

個人開発で運用している壁紙アプリのタブアイコンを、線の細いオリジナルのSVGに差し替えたときのことです。Expo Go で開くと綺麗に表示されていたので安心して開発ビルドを作ったところ、同じ画面でアイコンだけがぽっかりと消えていました。エラーは出ません。ただ、そこにあるはずの図形が透明になっている。原因にたどり着くまで小一時間かかりましたので、同じところで立ち止まる方のために整理して共有します。

症状

SVGアイコンが絡むと、次のいずれかの形でつまずきます。

  • Expo Go では表示されるのに、開発ビルドや本番ビルドでは何も描かれない
  • Unable to resolve module ./icon.svg という赤い画面が出る
  • 表示はされるが、ダークモードにしても色が黒いまま変わらない
  • iOS では出るのに Android だけ表示されない(またはその逆)

厄介なのは、多くの場合エラーが出ずに「透明な図形」として静かに失敗する点です。レイアウト上の場所は確保されているのに中身が見えないため、CSSの問題だと勘違いして遠回りしがちでした。

再現条件

Rork が生成したコード、あるいは自分で追加したコードで、SVGファイルをこう読み込んでいるケースです。

import TabIcon from "../assets/icons/home.svg";
 
export function HomeTab() {
  return <TabIcon width={24} height={24} />;
}

一見なんの問題もありません。しかし React Native / Expo の Metro バンドラーは、初期状態では .svg を「画像アセット」として扱います。つまり <TabIcon /> はコンポーネントではなく画像ソースのオブジェクトになり、コンポーネントとして描画しようとしても中身が生まれません。

Expo Go でたまたま表示されるのは、キャッシュや古いバンドル、あるいは別経路で読み込まれていたなど環境依存の偶然であることが多く、これに頼ると本番で崩れます。

なぜ表示されないのか

原因は大きく2つに分かれます。

ひとつ目は、.svg をコンポーネントとして import する仕組みが入っていないこと。React Native には Web の <img src="...svg"> のような仕組みがなく、SVGを描くには react-native-svg が必要です。さらに .svg ファイルをそのまま JSX コンポーネントとして扱うには react-native-svg-transformer を Metro に組み込む必要があります。これが無いと Metro は SVG を静的アセット扱いにしてしまいます。

ふたつ目は、色がSVGファイル内に固定で焼き込まれていること。デザインツールが書き出す SVG は fill="#111111" のように具体的な色を持っていることが多く、これだとアプリ側でテーマに応じて色を変えられません。ダークモードで黒いまま消えたように見えるのはこのパターンです。

解決策1: react-native-svg-transformer で .svg を import できるようにする

まず必要なパッケージを入れます。Expo 管理下では npx expo install を使うと SDK に合ったバージョンが入ります。

npx expo install react-native-svg
npm install --save-dev react-native-svg-transformer

次にプロジェクト直下の metro.config.js を編集します。Expo の場合は getDefaultConfig を土台にするのが安全です。ファイルが無ければ新規作成します。

// metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
 
const config = getDefaultConfig(__dirname);
 
// SVG を JSX コンポーネントとして扱えるようにする
config.transformer.babelTransformerPath = require.resolve(
  "react-native-svg-transformer"
);
 
// .svg を「アセット」から外し、「ソースコード」として解決させる
config.resolver.assetExts = config.resolver.assetExts.filter(
  (ext) => ext !== "svg"
);
config.resolver.sourceExts = [...config.resolver.sourceExts, "svg"];
 
module.exports = config;

ポイントは assetExts から svg を除外し、sourceExts に加えるところです。この2行を忘れると transformer を入れても Metro は依然として SVG を画像として扱い続けます。

TypeScript を使っている場合は、.svg を import する型が無いと赤線が出ますので、declarations.d.ts のような型定義ファイルを1枚用意します。

// declarations.d.ts
declare module "*.svg" {
  import type { SvgProps } from "react-native-svg";
  const content: React.FC<SvgProps>;
  export default content;
}

最後に、設定を変えたら Metro のキャッシュを消してから再起動します。ここを飛ばすと古い解決結果が残り、直っているのに直っていないように見えます。

npx expo start --clear

これで先ほどの import TabIcon from "../assets/icons/home.svg" が、そのままコンポーネントとして描画されるようになります。

解決策2: currentColor でテーマに追従させる

表示はできても色が変わらない問題は、SVGの fill を固定色から currentColor に置き換えることで解決します。react-native-svg-transformer は SVG 内の currentColor を、コンポーネントに渡した color プロップに橋渡ししてくれます。

書き出された SVG のパスがこうなっていたら、

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <path fill="#111111" d="M12 3l9 7v11h-6v-6H9v6H3V10z" />
</svg>

固定色を currentColor に書き換えます。

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <path fill="currentColor" d="M12 3l9 7v11h-6v-6H9v6H3V10z" />
</svg>

呼び出し側では color を渡すだけで、テーマに応じて色が切り替わります。

import { useColorScheme } from "react-native";
import HomeIcon from "../assets/icons/home.svg";
 
export function HomeTab() {
  const scheme = useColorScheme();
  const tint = scheme === "dark" ? "#F2F2F7" : "#1C1C1E";
  return <HomeIcon width={24} height={24} color={tint} />;
}

複数の色を持つイラスト系SVGでは、変えたい部分だけ currentColor にして、変えたくない差し色は固定色のまま残す、という使い分けができます。アイコンのように単色で扱いたいものは全パスを currentColor に統一しておくと、後から配色を変える際に一箇所で済みます。

どちらの方法を選ぶか

状況向いている方法
デザイナー書き出しのSVGを大量に使う解決策1(transformer で import)
数点だけ・動的に形を変えたいreact-native-svg の Svg / Path で手書き
色をテーマに追従させたい解決策2(currentColor)を併用

私自身は、タブバーやリスト行の小さなアイコンは transformer で .svg を直接読み込み、色は currentColor に統一する形に落ち着きました。デザインの差し替えが .svg ファイルの入れ替えだけで済むので、運用がとても軽くなります。

予防策

同じ落とし穴を避けるために、私は次の3点を最初に固めるようにしています。

まず、プロジェクトを立ち上げた初日に metro.config.js と型定義を入れてしまうこと。後から入れると「なぜか表示されない」の切り分けに時間を取られます。

次に、SVGを追加したら必ず一度は 開発ビルド(Expo Go ではなく) で確認すること。Expo Go は同梱ライブラリの都合で挙動が異なることがあり、Expo Go で動いたことは本番で動く保証になりません。

最後に、設定を触ったら --clear を癖にすること。SVG 周りの「直したのに直らない」の大半は、Metro のキャッシュが古い解決結果を握っていることが原因でした。

参考リンク

小さなアイコンひとつでも、表示の仕組みを理解しておくと後々の運用がぐっと楽になります。同じところで足止めされている方の助けになれば幸いです。お読みいただきありがとうございました。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⬡ 開発ツール2026-10-07
日本語の見出しだけ太字にならない — Android で fontWeight が効かないときの切り分けと直し方
Rork で作ったアプリで、iPhone では太字なのに Android では日本語の見出しが細いままになる症状の切り分け記事です。原因の見分け方、fontFamily を重みごとに分ける直し方、確認用コードを載せています。
⬡ 開発ツール2026-09-21
exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック
eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。
⬡ 開発ツール2026-09-10
画面を暗くする機能を足したら、アプリを閉じたあとも iPhone が暗いままでした
expo-brightness の setBrightnessAsync は、Android では現在のアクティビティにだけ効き、iOS では端末の明るさそのものを変えます。戻す責任が片側にしかない理由と、AppState で後始末をするフックの実装をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます