見出し画像

stand.fm で React Native for Web を使ってる話

こんにちは。moriyuu です。

私の所属している stand.fm 社では、stand.fm というアプリの iOS/Android 向けアプリと Web ページを開発しており、技術的には、React Native 及び React Native for Web を採用しています。
今回は、React Native for Web をなぜ使っているのか、stand.fm というサービスで React Native for Web を使っていて感じたことなどを書きます。

React Native for Web とは

React はもともと Web の開発のために生まれた技術で、ネイティブアプリ向けにも展開したのが React Native なのですが、さらに React Native で作られたアプリケーションを Web ブラウザでレンダリングできるように開発されたのが React Native for Web です。

2017 年くらいから開発が開始され、同年 9 月には Twitter Lite に導入されていたようです。

stand.fm での導入経緯

stand.fm のコードに初めて react-native-web が登場したのは 2018/06 でした。

当時の実装者いわく、

個人的に <div>, <span> など使っていて違和感があったんですが、RNのコンポーネント <View>, <Text> + flexbox でコード書いていて全く問題がないことが分かったのでWebも同じようにしたいと思ってRN for Webにしました。

とのことでした。

実装時の issue に技術選定の経緯などは詳しく書いてはいなかったので、当時を振り返って考えていたことを聞いてみました ↓

導入時の懸念事項だったこと
- h1とかは自分で書かないといけなかった
  - 当時はaccessibilityRoleが無かった
  - 必要な所を随時書けばいいかとなった
- flexbox未対応ブラウザで表示できない
  - 導入時にこれは対応諦めると決めたはず
- DOM構造, CSSが汚い
  - 諦める判断をしました

導入の後押しになったこと

- Twitter Lite が利用している

導入後に分かったこと

- 結構アプリと同じコンポーネントが使える
- media queryが書きづらい
  - 今は改善している??

stand.fm では、先述した通りネイティブアプリ (iOS / Android)、Web ページを提供しているのですが、ネイティブアプリと Web で提供している機能はそれぞれ違っています。
ネイティブアプリでは音声コンテンツの収録機能、ライブ配信機能、いいね/コメント/フォロー機能などがありますが、Web にはまだこれらの機能が無い状態です。現状 Web では、大まかには収録放送・ライブ放送の視聴ができるだけ、というミニマムな機能のみとなっています。
UI もスマホサイズにのみ対応している状態なので、PCから閲覧するとスマホの幅でしか表示されないです。 

Web をリリースしようとなった当時、社内にはエンジニアが2人で、ネイティブアプリの開発にもっとも注力している状況でした。Webを開発するにあたって、リスナーが放送を聴けるというミニマムな機能だけを提供するという方針で、かつ実装コストを出来る限り下げたかったため、再開発しなくても済むように、という当時の社内事情がありました。

stand.fm での使用用途

iOS/Android 向けに開発したコードを 100% そのまま Web のプラットフォームにも対応させて出しているかというとそうではないです。前述したように、提供している機能が違っていたり、Web 向けの見せ方(UI)が異なっていたりします。
なので用途としては、「アプリ向けに作ったコンポーネントを一部 Web にも共有して使用している」です。

また、storybook, reg-suit を使った UI のリグレッションテストを計画していて、今社内で少しずつ進めています。
この辺については Naturalclar さんの資料がわかりやすいです。

実際どうか

※ 以下、ネイティブアプリのプロジェクトを app、Web ページのプロジェクトを web といいます

コンポーネントの再利用率
プロジェクトによってコンポーネントの切り分け方の粒度は異なると思うので参考までにですが、調べたところ web 全体の 60% のコンポーネントを app と共有していました。
数字を見るとなかなかコスト削減に成功しているっぽいですね。icon の割合がそこそこありますが。

内訳
- web で `import from app` しているコンポーネント数 = 41
- web で定義されたコンポーネント数 = 27
- web で使用しているコンポーネント数 = 41 + 27 = 68

放送ページ、ライブページの画面でいうと、このような感じです。(赤い枠線で囲ってある箇所が app の方から import してきているコンポーネントです)

画像1


SSR
stand.fm の web は SSR(Server Side Rendering) をしています。React Native for Web を使用していても、特に面倒なことはないです。
React Native for Web は SSR のために AppRegistry に getApplication というメソッドを用意してくれています。
https://necolas.github.io/react-native-web/docs/?path=/docs/guides-server-side--page

メディアクエリ
前述のとおり、現状の stand.fm の web は UI をスマホサイズにしか対応していないので、レスポンシブは未対応です。
実際に対応するとなると react-responsive とかそういうライブラリを使うことになると思います。そもそもネイティブアプリ向けに書いたコードに Web 文脈のコードがゴチャっと増えてしまうのはいやですけどね...
まあ本当にゴチャっとしてしまうようなら MyComponent.web.js とかファイルを分けて実装を分けちゃうのも手ですね。無理しないほうがいいですね。

Web 未対応ライブラリ
たまに Web に対応していないライブラリがあります。iOS/Android はそれぞれネイティブコードを呼び出していて、Web 向けのレンダリング方法が未定義だったりします。
例えば、グラデーションを描画するための react-native-linear-gradient とかです。(React Native は style に `background: "linear-gradient(...)"` とかを指定できないです)
こうなってしまうと、Web 向けの実装を自分らでどうにかするしかないです。react-native-linear-gradient に対する react-native-web-linear-gradient なんかが正にそうしていますが、こういうことをしないといけないです。まあそんなに心配する必要はないです。

デザイナーとのコミュニケーション
基本的には、ある機能や画面について、app のデザインのあとに web のデザインがされることがほとんどです。
エンジニアとしては Web ページのデザインに app と似た UI があったら同じ実装を使用したいです。一方、デザイナーもまた同じ機能であればプラットフォームに関わらずできるだけ同じ UI で表現したいと考えているので、積極的に同じコンポーネントを使用しています。このあたりは同じ気持ちなのであまり困ることは無いです。
実際に、app とほとんど同じだけど web だと微妙に違う UI があった場合には、同じコンポーネントじゃダメか相談するなどしています。

おわりに(エンジニアを採用中です!)

株式会社 stand.fm では、エンジニアを募集しております。
求人情報はこちらです(最近コーポレートサイトが新しくなりました)

それでは!

この記事が気に入ったらサポートをしてみませんか?