React Native Webとは?DOM変換の仕組みとExpo Web構成・更新停滞下の採用判断【2026年8月時点】
React Native Webは、React Native向けに書いた画面をブラウザで動かすための互換層です。同じコードでモバイルとWebの両方を出せるという説明だけで導入を決めると、どこまで共通化できるかの線引きで必ず判断を誤ります。実際に効いてくるのは、画面が似ているかどうかではなく、使う部品がこのライブラリの実装範囲に収まるかどうか。この記事では、DOMへの変換が何をしているのか、Expo Webとどう重なるのか、そして2026年8月時点で更新が止まっている事実をどう扱うかを、一次情報だけで整理します。
まとめ:意味構造は残せるが保守の主体はExpo側へ移っている
先に結論を三つ示します。第一に、react-native-webが出力するのはDOMです。canvasへ絵を描く方式とは違い、roleとariaを与えれば見出しや段落として実際のHTML要素になります。ログイン後の業務画面だけでなく、ある程度の意味構造をWeb側に求められる画面でも成立の余地がある、というのがこの方式の位置づけになります。
第二に、採用の可否を分けるのは共通化できる画面の比率ではありません。判定すべきは、画面仕様に出てくる部品とAPIが公式の一覧に収まるかどうか。表組みの作り込み、帳票、印刷用のスタイルはこのライブラリの外側に出るため、そこが要件の中心にある案件では作り分けが前提になります。
第三に、継続性の見方を変える必要があります。最新版0.21.2の公開は2025年10月16日で、リポジトリの最新コミットも同じ日付。2026年8月19日時点で約10か月止まっています。一方でExpoは57.0.14を2026年8月17日に公開し、依存関係にreact-native-webを並べたまま更新を続けている。単独のライブラリとして採るか、Expoを含む構成として採るかで、リスクの大きさが変わります。以下、それぞれの根拠を順に確認します。
React Native Webがネイティブ向けコードをDOMへ写す仕組み
この互換層が何をしているかは、部品の変換とスタイルの変換という二つの経路に分けると見通しが良くなります。どちらもビルド時に一括変換されるのではなく、実行時にReact DOM側の表現へ解決される点が共通しています。
React DOMとReact Nativeの互換層という位置づけの確認
公式ドキュメントはこのライブラリを「React DOMとReact Nativeの互換層」と定義しています。ViewやText、Image、TextInput、ScrollViewといったコア部品を備え、JavaScriptで書いたスタイルをCSSへ変換して出力する。ActivityIndicatorからSwitchまで十数点の部品と、AnimatedやAppState、Dimensions、Linking、PanResponder、Platform、StyleSheetなどのAPIが同じ名前で使えます。
注意すべきは変換の向きです。既存のWebコードがモバイルでも動くようになるのではなく、React Nativeの書き方へ統一したコードがブラウザでも動くようになる。divをViewへ、文字列をTextへ、CSSファイルをオブジェクトへ書き換える作業が先に来ます。この書き換え量をどう見積もるか、どの層までなら共有できるかについてはReactとReact Nativeの違いを描画・部品・スタイル・画面遷移の4層で比較で層ごとに整理しているため、本記事では立ち入りません。
スタイルは実行時にアトミックなCSSクラスへ変換される仕組み
スタイルの扱いは、単純なインライン展開ではありません。公式ドキュメントによれば、StyleSheet.createで定義したスタイルは最終的にCSSのクラス名として描画されます。個々の宣言はそれぞれ固有のアトミックCSSクラス名へ写され、クラス名はビルドをまたいでも一致する決定的な値になる。登録済みのスタイルは実行時にDOMのstyleプロパティへ解決され、結果が記憶されます。
ここで挙動が分かれるのが優先順位です。通常のCSSは後に書いたルールが勝ちますが、この仕組みでは指定の細かいプロパティが勝ちます。公式が挙げる例では、marginを0に、marginTopを10に指定した場合にmarginTopの値が採用される。CSSの記述順が描画結果へ影響せず、ルールの重複を効率良く畳めるようにするための設計です。
持ち込めない機能も明示されています。@ルール、セレクタ、擬似クラス、擬似要素には直接の対応がなく、メディアクエリも組み込みのAPIとしては持ちません。ホバー時の見た目やブレークポイントごとの分岐は、CSSではなくJavaScript側の状態と実測値で書き分ける前提になります。
roleを与えると見出しや段落のHTML要素として出力される
意味構造をどこまで残せるかは、role属性の扱いで決まります。公式のアクセシビリティ文書は、40を超えるARIA属性がW3Cの同名属性へ直接対応すると記載しています。加えて、要素の出し分けが具体的に決まっている。
- hrefを与えると、ViewもTextも見た目を保ったままa要素として描画される
- role属性に記事を示す値を与えたViewはarticle要素になる
- role属性に段落を示す値を与えたTextはp要素になる
- role属性に見出しを示す値とaria-levelの2を与えたTextはh2要素になり、aria-levelを省くとh1になる
裏を返せば、何も指定しなければ画面はdivの入れ子として出ます。検索エンジンや支援技術が読むのはこの構造なので、Web側で見出し階層を求められる画面では、ネイティブ向けのコンポーネントツリーにroleとaria-levelを配って回る作業が発生する。フォーカス制御はtabIndexで行い、0で操作順に含め、マイナス1で外す。roleの値をユーザー操作の後に切り替える書き方は、支援技術へ変更を通知する手段がないため避けるよう案内されています。ネイティブ側でこのツリーがどう組み立てられているかはReact Nativeとは?仕組みとNew Architectureの構造・採用判断で確認できます。
導入で決まるのは解決先の差し替えとプラットフォーム拡張子の二点
導入手順そのものは短く、設定として書くのは実質二つだけです。バンドラがreact-nativeをどこへ解決するかと、Web専用の実装をどう差し込むか。ここを押さえれば、あとは通常のWebアプリのビルドと同じ流れになります。
react-nativeの参照をreact-native-webへ解決させる設定
コード側のimport文は書き換えません。バンドラの解決先を差し替え、react-nativeへの参照がreact-native-webに届くようにします。webpackやViteであればaliasの一行、Metroであればresolverの設定に相当します。
resolve: {
alias: {
'react-native$': 'react-native-web'
}
}
組み合わせる版には制約があります。0.21.2が要求するreactとreact-domは、それぞれ18系または19系。ライセンスはMITです。React Native本体は0.87.0が2026年8月11日公開で別系統として進むため、両者の版を同時に上げる運用にはせず、動作を確認した組み合わせで固定してください。
web付きの拡張子でWeb専用の実装だけを安全に差し替える方法
共通化できない画面まで無理に一本化する必要はありません。Metroはプラットフォーム別の拡張子を解決するため、同じ名前でWeb向けのファイルを置けば、Webビルドのときだけそちらが読まれます。
DataTable.tsx ネイティブ向けの実装
DataTable.web.tsx Web向けの実装
DataTable.types.ts 双方で共有する型
粒度の目安を示します。分岐が数行で済むならPlatform.OSによる条件分岐で足り、画面の組み立てごと変わるならファイルを分ける。中途半端に条件分岐を積み上げると、どちらのプラットフォームでも読めないコードが残ります。
更新の遅れを踏まえて依存関係の版を固定する考え方と確認の手順
package.jsonでの指定はキャレット付きの範囲指定ではなく、版を固定する書き方を選んでください。理由は次の章で扱う更新間隔にあります。長く更新がないライブラリでは、周辺パッケージ側が先に進んで組み合わせが崩れる形の不具合が出る。lockファイルだけに頼らず、動いた組み合わせを明示的に記録しておくと復旧が早くなります。
Expo Webは素の導入と前提が違い生成物の指定で結果が変わる
2026年8月時点で実務投入されている構成の多くは、素のreact-native-webではなくExpoを経由したものです。前提が違うため、記事や資料を読むときはどちらの話かを見分ける必要があります。
Metroが標準でexpoのweb起動コマンド一行から始まる
Expoの標準バンドラはMetroで、Web向けのビルドも同じ経路を通ります。公式ドキュメントはreact-native-webの位置づけを「Webでは任意だが、プラットフォームをまたいで作るならコードの再利用を最大化するため推奨する」と書き、ViewやTextといったreact-domのプリミティブを包む部品群だと説明しています。つまりExpo構成では、Webへ出すかどうかとreact-native-webを使うかどうかが別々の選択になっている。
もう一つ、Web専用のDOMコンポーネントという仕組みも用意されています。こちらはWebの実装をそのまま書けますが、ネイティブ側では描画されません。Expoが持つビルド基盤そのものの全体像はExpo(React Native)とは?Expo Go・開発ビルド・EASの役割と採用判断にまとめています。
web.outputの指定で生成物と検索エンジンへの見え方が変わる
検索からの流入を少しでも見込むなら、静的書き出しの指定が要ります。app.jsonで出力形式を切り替えます。
{
"expo": {
"web": {
"output": "static"
}
}
}
この指定でルートごとのHTMLとCSSがdistへ書き出され、publicディレクトリのファイルも複製されます。データローダはビルド時に実行され、結果がHTMLへ埋め込まれる。制約も明示されています。リクエスト時のレンダリングには対応せず、動的ルートはgenerateStaticParamsで組み合わせを列挙しない限り生成されません。この関数はNode.js上のビルド時に走るため、localStorageやdocumentといったブラウザのAPIにもExpoのネイティブAPIにも触れない。単一ページアプリではないので、ホスティング側でSPA向けのリダイレクトを前提にする構成も取れません。
Expoの依存関係にreact-native-webが並ぶ構造の意味
expoパッケージの57.0.14は2026年8月17日の公開で、依存として要求する相手にreact、react-dom、react-native、そしてreact-native-webが並びます。56系、55系、54系のパッチも同じ日に出ている。Web出力を扱う実務的な更新が、互換層そのものではなくExpo側の周辺パッケージで進んでいる構図が、依存関係の並びからも読み取れます。
更新が約10か月止まっている状態は保守の主体で読み方が変わる
継続性の判断は、印象ではなく公開日の並びで行えます。ここは採用前に必ず確認しておく箇所です。
0.21.2が2025年10月16日で最後の公開になっている
npmのレジストリが返す公開日を並べると、間隔の変化がはっきりします。0.20.0が2025年4月3日、0.21.0が2025年7月25日、0.21.1が2025年8月20日、0.21.2が2025年10月16日。ここまでは2か月から3か月の間隔でした。以降、2026年8月19日時点まで新しい版は出ていません。
リポジトリ側も同じ日で止まっています。最新のコミットは2025年10月16日の版上げで、その直前にはinert属性の受け渡し対応、AnimatedPropsのコンストラクタにおけるメモリリーク修正、Modalのアニメーション修正が並ぶ。作業が中途で放置されているというより、区切りの良い状態で更新が途絶えた形です。
保守の実態がExpo側へ寄っている現状を構成別に読み分ける方法
この事実の解釈を言い切ります。react-native-webを直接の依存に置き、自前のバンドラ設定で組む構成は、2026年8月時点では受け皿が薄い。React本体やブラウザ側の仕様変更で不具合が出たとき、上流の修正を待つ選択肢が実質ありません。フォークして自社で当てる体制を組めるかどうかが、そのまま採用可否になります。
Expo構成であれば話が変わります。前章のとおりExpo側は週単位でパッチを出し、複数の系統を並行して保守している。互換層の更新が止まっていても、バンドラと周辺パッケージの側で問題を吸収できる余地がある。同じライブラリを使っていても、リスクの大きさは構成によって変わります。
採用の可否は共通画面の比率ではなく使う部品の実装範囲で決まる
採用判断でよく使われるのは「WebとモバイルでUIが同じになる画面の比率」という軸です。この軸は入口としては有効ですが、見積もりを外す原因はもっと手前にあります。比率が高くても、使う部品が一つでも実装範囲の外にあれば、その画面は結局作り分けになるからです。
使う部品とAPIが公式の一覧に収まるかを実装前に数えて判断する
順序を逆にしてください。画面比率を数える前に、画面仕様に出てくるUI部品と端末機能を列挙し、公式ドキュメントのコンポーネント一覧とAPI一覧に照らします。ViewやText、Image、TextInput、ScrollView、ActivityIndicator、Switchといった基本部品と、AnimatedやDimensions、Linking、PanResponder、Platform、StyleSheet、Clipboardあたりで足りるなら、共通化は素直に進みます。
数えた結果、一覧に無い部品が三つを超えたら共通化の前提を疑ってください。無い部品は自作するかWeb専用のファイルへ逃がすことになり、その分だけ二重管理が増えます。増えた二重管理は、共通化で削ったはずの工数をそのまま食い潰します。
表組みと帳票と印刷が互換層の外側に出る理由と見積もりの考え方
業務系Webで要求されやすい三点は、構造上この互換層の内側では作れません。理由はスタイルの制約にあります。擬似クラスが無いため行のホバー表示をCSSで書けず、メディアクエリが無いため画面幅による列の出し分けもCSSでは書けない。@ルールが無いということは、印刷用のスタイル指定も持てないという意味になります。
帳票の出力も同じ位置にあります。ヘッダ固定の表、列幅の追従、改ページ制御を求められる画面は、Web専用の実装として切り出す前提で見積もってください。これらを共通コードへ押し込む調整は、別々に書くより時間がかかります。
採用してよい場面と見送るべき場面を要件と保守条件で切り分ける
採用してよいのは、次の三つがそろう場合です。第一に、画面仕様に出てくる部品とAPIが公式の一覧にほぼ収まること。第二に、Web側の入口が検索ではなくログインであるか、静的書き出しで足りる程度の公開ページしか持たないこと。第三に、Expo構成で組めること。社内向けの管理画面、既存アプリのブラウザ版、パートナー向けの業務ポータルはこの三つを満たしやすい対象になります。
見送るべきなのは、次のいずれかに当てはまる場合です。帳票と印刷と表の作り込みが要件の中心にある。Web専用のデザインシステムやコンポーネント資産が既にあり、それを捨てられない。自前のバンドラでこの互換層を直接依存に置くしかなく、上流が止まったときの保守体制も組めない。この三つはどれか一つでも該当した時点で、状態とロジックだけを共有し画面は分けたほうが早く終わります。
Web出力を持つ他のクロスプラットフォーム基盤と迷う場合は、描画方式の違いから入ってください。Flutter Webとは?CanvasKitとWasmの描画差・SEO制約・採用条件で扱ったとおり、そちらはcanvasへ描く方式のため意味構造がHTMLに残りません。DOMを出せるかどうかが両者の分かれ目になります。判断材料を社内でそろえきれない段階なら、要件の棚卸しから相談できるFlutter / React Nativeによるクロスプラットフォーム開発もご検討ください。
よくある質問
導入すればWebサイトがそのまま作れますか?
そのままにはなりません。変換の向きが逆だからです。既存のWebコードがモバイルでも動くようになるのではなく、React Nativeの書き方へ統一したコードがブラウザでも動くようになります。divやspanをViewとTextへ置き換え、CSSファイルをJavaScriptのオブジェクトへ書き換える作業が先に必要です。
検索エンジンに本文を読ませることはできますか?
条件付きで可能です。出力されるのはDOMなので、canvasへ描く方式と違って本文をHTMLの要素として残せる構造です。ただし既定のクライアント描画のままでは中身がHTMLに現れないため、Expoのweb.outputで静的書き出しを指定し、あわせてroleとaria-levelで見出し階層を与える作業が要ります。この二つを省くとdivの入れ子だけが出力されます。
Expoを使わずに導入できますか?
できます。バンドラの解決先をreact-native-webへ向ける設定だけで動きます。ただし本文で触れたとおり、互換層そのものは2025年10月16日から更新が止まっている。自前構成では不具合が出たときの受け皿が薄いため、フォークして自社で修正を当てる体制を持てるかどうかを先に決めてください。
CSSのホバーやメディアクエリは書けますか?
直接の対応はありません。擬似クラス、擬似要素、セレクタ、@ルール、メディアクエリのいずれも組み込みでは持たない仕様です。ホバーや押下時の見た目はPressableが渡す状態で分岐させ、画面幅による出し分けはuseWindowDimensionsなどで実測値を取ってJavaScript側で切り替えます。
スタイルの優先順位はCSSと同じですか?
違います。CSSは後に書いたルールが勝ちますが、こちらは指定の細かいプロパティが勝ちます。marginを0に、marginTopを10に指定した場合はmarginTopが採用される。記述順が描画結果に影響しない設計のため、CSSの感覚で順序を入れ替えても表示は変わりません。