Closed4
Expo(React Native) + Next.jsでアプリとWebでコードをできるだけ共通化して開発してみる【Tamagui/Solito】
ExpoはWebに対応しているが、SPAかSSGでしかリリースできない。
SEOのためにSSRやISRしたいので、WebはNext.jsで開発する。
できるだけWebとNativeでコードを共通化して、工数を減らしたい。
solitoとtamaguiの組み合わせで、コードをできるだけ共通化して開発してみる。
tamaguiのnpm createでFree Expo + Next テンプレートを使う。
$ npm create tamagui@latest
Creating tamagui app...
✔ Project name: test
? Pick a template: › - Use arrow-keys. Return to submit.
❯ Free - Expo + Next in a production ready monorepo
作成されたフォルダでyarn install
$ cd ./test
$ yarn
下記のコマンドでそれぞれの開発環境が立ち上がる。
// Next.js
$ yarn web
// Expo
$ yarn native
Web | Native |
---|---|
作られたフォルダ構成は下記の様な形。
expoとnextに関してはいつもどおりの中身。
packagesに共通のものを入れていき、appsそれぞれで使っていく形っぽい。
..
├── apps # アプリケーション関連のコード
│ ├── expo # Expoアプリケーション(モバイル版)
│ └── next # Next.jsアプリケーション(Web版)
├── packages # 共通のライブラリやコンポーネント
│ ├── app # アプリケーション関連の共有ライブラリ
│ ├── config # 設定ファイルや設定関連のコード
│ └── ui # 共通のUIコンポーネントやスタイル
それぞれのホームスクリーンのtsxを見てみると、HomeScreenのComponentを読み込んでいるだけ。
expo/app/index.tsx
import { HomeScreen } from 'app/features/home/screen'
import { Stack } from 'expo-router'
export default function Screen() {
return (
<>
<Stack.Screen
options={{
title: 'Home',
}}
/>
<HomeScreen />
</>
)
}
next/app/page.tsx
'use client'
import { HomeScreen } from 'app/features/home/screen'
export default HomeScreen
全体的に、TamaguiでScreenを表示しているが、リンク部分だけはsolitoを使っています。
solitoのuseLinkHookを使って、Next.js/Expo両方に対応したリンクのPropsを作成し渡すようにしています。
app/features/home/screen.tsx
import { useLink } from 'solito/navigation'
export function HomeScreen({ pagesMode = false }: { pagesMode?: boolean }) {
const linkTarget = pagesMode ? '/pages-example-user' : '/user'
const linkProps = useLink({
href: `${linkTarget}/nate`,
})
return (
<YStack f={1} >
<Button {...linkProps}>Link to user</Button>
</YStack>
)
}
Appディレクトリに共通Componentなどを入れていくようになっている。
app/
├── features/
├── provider/
└── navigation/
featuresはScreenではなく、機能単位で分割されたComponent.
providerはラップする必要のある処理を置くフォルダ。
このスクラップは1日前にクローズされました