feat: 新アーキテクチャへの移行準備と依存関係の更新

- app.json: newArchEnabledをtrueに設定し、kotlinVersionを2.1.20に更新
- babel.config.js: lazyImportsを有効化し、react-native-reanimated/pluginを追加
- metro.config.js: experimentalImportSupportを有効化
- package.json: react-native-reanimated-carouselを4.0.3に更新
- 新しいプラグインwith-android-local-propertiesを追加
- 新しいドキュメントnew-architecture-migration-plan.mdを作成
- その他のファイルでの軽微な修正
This commit is contained in:
harukin-expo-dev-env
2026-03-18 05:43:21 +00:00
parent b7a09eda6e
commit cf611c6c8d
9 changed files with 272 additions and 12 deletions

View File

@@ -1,7 +1,7 @@
import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { Platform } from "react-native";
import { Platform, ActivityIndicator, View } from "react-native";
import { useFonts } from "expo-font";
import TNDView from "./ndView";
import { initIcon } from "./lib/initIcon";
@@ -77,6 +77,13 @@ export function AppContainer() {
"JNR-font": require("./assets/fonts/JNRfont_pict.ttf"),
"DiaPro": require("./assets/fonts/DiaPro-Regular.otf"),
});
if (!fontLoaded) {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<ActivityIndicator size="large" />
</View>
);
}
return (
<NavigationContainer ref={rootNavigationRef} linking={linking}>
{/* @ts-expect-error - Tab.Navigator type definition issue */}
@@ -89,7 +96,7 @@ export function AppContainer() {
}}
>
<Tab.Screen
{...getTabProps("positions", "走行位置", "barchart", "AntDesign")}
{...getTabProps("positions", "走行位置", "bar-chart", "AntDesign")}
component={Top}
/>
<Tab.Screen

View File

@@ -2,7 +2,7 @@
"expo": {
"name": "JR四国非公式",
"slug": "jrshikoku",
"newArchEnabled": false,
"newArchEnabled": true,
"scheme": "jrshikoku",
"platforms": [
"ios",
@@ -98,6 +98,7 @@
"policy": "sdkVersion"
},
"plugins": [
"./plugins/with-android-local-properties",
[
"expo-font",
{
@@ -498,7 +499,7 @@
"expo-build-properties",
{
"android": {
"kotlinVersion": "2.0.21"
"kotlinVersion": "2.1.20"
}
}
],

View File

@@ -4,8 +4,12 @@ module.exports = function(api) {
presets: [
['babel-preset-expo', {
'react-compiler': { enabled: false },
lazyImports: true,
}],
],
plugins: ['./plugins/babel-plugin-disable-font-scaling'],
plugins: [
'./plugins/babel-plugin-disable-font-scaling',
'react-native-reanimated/plugin',
],
};
};

View File

@@ -36,7 +36,7 @@ export const StationTrainPositionButton: FC<Props> = (props) => {
>
<View style={{ flex: 1 }} />
<AntDesign
name={"barchart"}
name={"bar-chart"}
size={20}
color={fixed.textOnPrimary}
style={{ marginHorizontal: 5, marginVertical: 5 }}

View File

@@ -0,0 +1,198 @@
# New Architecture 移行プラン
## 背景・問題
`react-native-reanimated` v4.x と `react-native-worklets` v0.5.1 は
**New Architecture が有効でなければビルド自体が失敗する**
```
FAILURE: Build failed with an exception.
> Task :react-native-reanimated:assertNewArchitectureEnabledTask FAILED
> Task :react-native-worklets:assertNewArchitectureEnabledTask FAILED
```
現在 `app.json``expo-build-properties``newArchEnabled` が未設定のため、
Gradle ビルドが必ず失敗している状態。**Old Arch 経由という選択肢は存在しない。**
---
## 依存パッケージ 互換性マトリクス
| パッケージ | バージョン | New Arch 対応 | 備考 |
|---|---|---|---|
| `react-native-reanimated` | ~4.1.1 | ✅ 必須 | New Arch 専用 |
| `react-native-worklets` | 0.5.1 | ✅ 必須 | New Arch 専用 |
| `expo-felica-reader` (local) | 0.2.0 | ✅ | Expo Modules API 使用 |
| `react-native-gesture-handler` | ~2.28.0 | ✅ | 公式対応済み |
| `react-native-screens` | ~4.16.0 | ✅ | 公式対応済み |
| `react-native-safe-area-context` | ~5.6.0 | ✅ | 公式対応済み |
| `lottie-react-native` | ~7.3.1 | ✅ | 公式対応済み |
| `@gorhom/bottom-sheet` | ^5 | ✅ | New Arch 対応版 |
| `react-native-maps` | 1.20.1 | ✅ | 対応済み |
| `react-native-svg` | 15.12.1 | ✅ | 対応済み |
| `react-native-webview` | 13.15.0 | ✅ | 対応済み |
| `react-native-view-shot` | ~4.0.3 | ✅ | 対応済み |
| `react-native-storage` | 1.0.1 | ✅ 想定 | JS-onlyAsyncStorage ラッパー)|
| `react-native-touchable-scale` | 2.2.0 | ✅ 想定 | JS-onlyAnimated ラッパー)|
| `react-native-responsive-screen` | 1.4.2 | ✅ 想定 | ユーティリティのみ |
| `react-native-vector-icons` | 10.2.0 | ✅ 想定 | 対応済み |
| `@react-native-vector-icons/*` | ^12.4.3 | ✅ 想定 | 同上 |
| `react-native-actions-sheet` | 0.9.7 | ⚠️ 要確認 | JS-only・reanimated 非依存。動作確認必須。問題時は v10.x へ更新 |
| `react-native-reanimated-carousel` | 3.5.1 | ⚠️ 要確認 | reanimated >=3 依存。reanimated 4 互換は実機テスト必要。最新 v4.0.3 あり |
| `react-native-sortables` | 1.1.0 | ⚠️ 要確認 | reanimated >=3 依存。最新 v1.9.4 あり |
| `react-native-android-widget` | 0.15.1 | ⚠️ 要確認 | 最新 0.20.1 で改善あり |
---
## 実装ステップ
### Step 1: New Architecture を有効化
`app.json``expo-build-properties` android セクションに `"newArchEnabled": true` を追加する。
**変更前:**
```json
["expo-build-properties", {
"android": {
"kotlinVersion": "2.0.21"
}
}]
```
**変更後:**
```json
["expo-build-properties", {
"android": {
"kotlinVersion": "2.0.21",
"newArchEnabled": true
}
}]
```
---
### Step 2: ネイティブプロジェクト再生成
```bash
rm -rf android
npx expo prebuild
```
prebuild が警告・エラーなく完了することを確認する。
---
### Step 3: Gradle ビルド確認
```bash
cd android && ./gradlew assembleDebug
```
または
```bash
npx expo run:android
```
以下のタスクが **PASSスキップではなく成功** することを確認:
```
> Task :react-native-reanimated:assertNewArchitectureEnabledTask
> Task :react-native-worklets:assertNewArchitectureEnabledTask
```
---
### Step 4: ⚠️ 要確認パッケージの動作テスト
ビルド成功後、以下を実機または Emulator で確認する。
#### 4a. react-native-reanimated-carousel (3.5.1)
- [ ] カルーセル表示・スワイプ動作を確認
- 問題が出た場合 → `v4.0.3` へアップデート
```bash
npx expo install react-native-reanimated-carousel@latest
```
#### 4b. react-native-sortables (1.1.0)
- [ ] ドラッグ並び替え動作を確認
- 問題が出た場合 → `v1.9.4` へアップデート
```bash
npx expo install react-native-sortables@latest
```
#### 4c. react-native-actions-sheet (0.9.7)
- [ ] ActionSheet が開く・閉じる・スクロールできることを確認JS-only なので高確率で問題なし)
- 問題が出た場合 → **v10.x へアップデート**
> ⚠️ **注意**: v10 はメジャーバージョンジャンプのため破壊的変更がある可能性あり。
> `registerSheet`, `SheetManager.show`, `useScrollHandlers` を使っているファイルが **約30ファイル**あるため、移行コストが大きい。
> まず現状バージョンで動作確認してから判断すること。
#### 4d. react-native-android-widget (0.15.1)
- [ ] Androidウィジェットの表示・タップ・更新動作を確認
- 問題が出た場合 → `v0.20.1` へアップデート([CHANGELOG](https://github.com/sAleksovski/react-native-android-widget) を確認)
```bash
npx expo install react-native-android-widget@0.20.1
```
---
### Step 5: EAS Build テスト
```bash
eas build --profile development --platform android
```
development ビルドを実機インストールし、全機能を通しでテストする。
---
### Step 6: production ビルド
```bash
eas build --profile production --platform android
```
---
## トラブルシューティング
### Gradle ビルドエラーが続く場合
```bash
cd android && ./gradlew clean
cd .. && npx expo prebuild --clean
```
### metro バンドルエラーが出る場合
```bash
npx expo start --clear
```
### reanimated 関連の実行時クラッシュ
`react-native-reanimated-carousel``react-native-sortables` が reanimated 4 の
内部 API を使用していた場合に発生しうる。各ライブラリを最新版にアップデートして再確認。
---
## 「Old Arch を使えないか?」について
| | Old Arch (`newArchEnabled: false`) | New Arch (`newArchEnabled: true`) |
|---|---|---|
| reanimated 4.x | ❌ **ビルド失敗** | ✅ |
| worklets 0.5.1 | ❌ **ビルド失敗** | ✅ |
| パフォーマンス | 低い | JSI による高速化 |
| 将来性 | RN 0.86 以降で削除予定 | ✅ 標準 |
Old Arch を使いたい場合、`react-native-reanimated` を v3 系・`react-native-worklets` を削除する必要があり、
機能に大きな影響が出るため現実的ではない。

15
metro.config.js Normal file
View File

@@ -0,0 +1,15 @@
const { getDefaultConfig } = require("expo/metro-config");
const config = getDefaultConfig(__dirname);
config.transformer = {
...config.transformer,
experimentalImportSupport: true,
};
config.resolver = {
...config.resolver,
experimentalImportSupport: true,
};
module.exports = config;

View File

@@ -51,7 +51,6 @@
"expo-constants": "~18.0.13",
"expo-dev-client": "~6.0.20",
"expo-device": "~8.0.10",
"expo-felica-reader": "file:./modules/expo-felica-reader",
"expo-font": "~14.0.11",
"expo-haptics": "~15.0.8",
"expo-intent-launcher": "~13.0.8",
@@ -77,7 +76,7 @@
"react-native-gesture-handler": "~2.28.0",
"react-native-maps": "1.20.1",
"react-native-reanimated": "~4.1.1",
"react-native-reanimated-carousel": "^3.5.1",
"react-native-reanimated-carousel": "^4.0.3",
"react-native-responsive-screen": "^1.4.2",
"react-native-safe-area-context": "~5.6.0",
"react-native-screens": "~4.16.0",

View File

@@ -0,0 +1,36 @@
const { withDangerousMod } = require("@expo/config-plugins");
const fs = require("fs");
const path = require("path");
const os = require("os");
/**
* Generates android/local.properties with sdk.dir during prebuild.
* Tries ANDROID_HOME env var first, then common locations.
*/
const withAndroidLocalProperties = (config) => {
return withDangerousMod(config, [
"android",
async (config) => {
const androidDir = path.join(config.modRequest.projectRoot, "android");
const localPropertiesPath = path.join(androidDir, "local.properties");
const sdkDir =
process.env.ANDROID_HOME ||
process.env.ANDROID_SDK_ROOT ||
path.join(os.homedir(), "android-sdk");
if (fs.existsSync(sdkDir)) {
fs.writeFileSync(localPropertiesPath, `sdk.dir=${sdkDir}\n`);
console.log(`[withAndroidLocalProperties] sdk.dir=${sdkDir}`);
} else {
console.warn(
`[withAndroidLocalProperties] Android SDK not found at ${sdkDir}. Set ANDROID_HOME.`
);
}
return config;
},
]);
};
module.exports = withAndroidLocalProperties;

View File

@@ -5472,10 +5472,10 @@ react-native-maps@1.20.1:
dependencies:
"@types/geojson" "^7946.0.13"
react-native-reanimated-carousel@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/react-native-reanimated-carousel/-/react-native-reanimated-carousel-3.5.1.tgz#3605b9959ffc0aa1c6b8b8736d98f91f46e36b17"
integrity sha512-9BBQV6JAYSQm2lV7MFtT4mzapXmW4IZO6s38gfiJL84Jg23ivGB1UykcNQauKgtHyhtW2NuZJzItb1s42lM+hA==
react-native-reanimated-carousel@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/react-native-reanimated-carousel/-/react-native-reanimated-carousel-4.0.3.tgz#975f4ff3f5da5bb3790fe60850a46ad8119612bc"
integrity sha512-YZXlvZNghR5shFcI9hTA7h7bEhh97pfUSLZvLBAshpbkuYwJDKmQXejO/199T6hqGq0wCRwR0CWf2P4Vs6A4Fw==
react-native-reanimated@~4.1.1:
version "4.1.6"