发布于 2026-01-06 0 阅读
0

我的 React Native 技术栈(一年后)

我的 React Native 技术栈(一年后)

我在 Dev.to 上的第一篇文章,想和大家分享我的 React Native 项目结构、配置以及一些技巧。文章包含了我在一年 React Native 开发过程中积累的大部分经验,涵盖了从项目创建到最终发布的各个环节。

我创建了一个名为typescript-react-native-starter的 GitHub 仓库,现在我所有的项目都使用它。
希望它能对其他 React Native 新手开发者有所帮助。欢迎提交 PR :D

特征

最近,在几个项目让我深刻体会到类型化变量的重要性之后,我开始使用 TypeScript。虽然一开始可能需要一些时间学习,但绝对值得。TypeScript 可以帮你节省数小时甚至数天的调试时间。

此外,它还能使你的代码具有自文档性,这对于有多名开发人员的项目至关重要。

      import { action } from 'typesafe-actions';
      import * as types from './actionTypes';

      export const myAction = payload => action(types.MY_ACTION_TYPE, payload);
Enter fullscreen mode Exit fullscreen mode
// Before
handleClick()  {...}

<button onClick={ this.handleClick.bind(this) }></button>

// After
@boundMethod
handleClick() {...}

<button onClick={ this.handleClick }></button>
Enter fullscreen mode Exit fullscreen mode

项目结构

我使用的文件结构借鉴了很多资料,所以你可能会觉得似曾相识。我喜欢按类别整理文件,但一些特殊类别除外App.tsx,例如store.ts……

publishing文件夹还包含一些用于部署应用的实用占位图片。
例如,即使是内部测试,要将应用部署到 Google Play,也需要添加屏幕截图、功能图等。一开始还好,但做了几个项目之后就觉得很麻烦,所以我决定创建一些占位图片。

├── __tests__                            // Unit tests
│   ├── App.test.tsx                     // App component's tests
│   ├── components
│   │   └── MyComponent.test.txs
│   └── ...
├── android
├── app.json
├── assets                               // All assets: images, videos, ...
├── index.js
├── ios
├── publishing                           // Icon, screenshots, preview,... for App Store & Play Store
└── src
    ├── App.tsx
    ├── actions                          // Actions
    │   ├── actionTypes.ts               // Action types
    │   └── app.ts                       // appReducer's actions
    ├── components                       // Components
    │   └── MyComponent.tsx
    ├── constants                        // Colors, sizes, routes,...
    │   └── strings.ts                   // i18n
    ├── containers                       // Screens, pages,...
    ├── lib                              // Libraries, services,...
    ├── index.tsx                        // Root component
    ├── reducers                         // Reducers
    │   └── app.ts                       // appReducer
    ├── sagas                            // Redux sagas
    ├── store.ts
    ├── types                            // Type declarations
    │   └── index.d.ts
    └── utils                            // Utilities
Enter fullscreen mode Exit fullscreen mode

实用技巧

本部分内容是一些完全随机但实用的小技巧,欢迎在评论区分享你的想法或提交 PR。

导航服务

您可以使用NavigationService实现无需 navigation 属性的导航src/lib/NavigationService.ts

import NavigationService from '../lib/NavigationService';

//...

NavigationService.navigate('ChatScreen', { userName: 'Lucy' });
Enter fullscreen mode Exit fullscreen mode

可可豆荚

当您运行程序react-native link且链接的库包含 podspec 文件时,链接将使用 Podfile。要禁用此功能,请移除相关配置。

# Add new pods below this line
Enter fullscreen mode Exit fullscreen mode

从第 24 行开始ios/Podfile

静态包

每次以物理设备为目标时,即使在调试模式下,也会构建静态包。为了节省时间,调试模式下禁用了包生成。

react-native-screens

您可以将 react-native-screens 与 react-navigation 结合使用,以降低内存消耗。

  • 安装并按照react-native-screensUsage with react-navigation (without Expo)中的步骤操作

  • 打开./src/index.tsx并取消评论

// import { useScreens } from 'react-native-screens';
// useScreens();
Enter fullscreen mode Exit fullscreen mode

响应能力

  • 尽量避免使用“绝对”位置和硬数值(100、300、1680 等),尤其是对于较大的数值。
  • 改用弹性盒子布局和百分比值
  • 如果必须使用固定值,我有一个normalize函数可以根据屏幕的宽度或高度自动调整这些固定值。我稍后可能会把它上传到代码仓库:
import { Dimensions, Platform, PixelRatio } from 'react-native';

export const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get(
  'window',
);

// based on iphone X's scale
const wscale = SCREEN_WIDTH / 375;
const hscale = SCREEN_HEIGHT / 812;

export function normalize(size, based = 'width') {
  const newSize = based === 'height' ? size * hscale : size * wscale;
  if (Platform.OS === 'ios') {
    return Math.round(PixelRatio.roundToNearestPixel(newSize));
  } else {
    return Math.round(PixelRatio.roundToNearestPixel(newSize)) - 2;
  }
}
Enter fullscreen mode Exit fullscreen mode

现在我可以使用:

// iphone X
normalize(100) // = 100

// iphone 5s
normalize(100) // = maybe 80

// You can choose either "width" (default) or "height" depend on cases:
container = {
  width: normalize(100, "width"), // "width" is optional, it's default
  height: normalize(100, "height")
}
Enter fullscreen mode Exit fullscreen mode
  • 在正式发布之前,请在 3 个不同的模拟器上测试您的应用:iPhone 5s(小屏幕)、iPhone 8(中屏幕)和 iPhone Xs Max(大屏幕)。

使用 Fastlane 的 Beta 分布

  # Using RubyGems
  sudo gem install fastlane -NV

  # Alternatively using Homebrew
  brew cask install fastlane
Enter fullscreen mode Exit fullscreen mode

iOS

  • 打开你的项目 Xcode 工作区并更新你的应用程序Bundle IdentifierTeam
  • 初始化快速通道
  cd <PROJECT_NAME>/ios
  fastlane init
Enter fullscreen mode Exit fullscreen mode
  • 分发您的应用
  fastlane beta
Enter fullscreen mode Exit fullscreen mode

安卓

  • 收集您的 Google 凭据
  • 使用 Android Studio 打开您的项目,并更新您的应用程序applicationId文件build.gradle (Module: app)
  • Generated Signed Bundle / APK...Build菜单中选择
  • Next然后,……Create new...之下Key store pathNextFinish
  • 首次部署应用时,您必须手动将其上传到 Google Play 管理中心。Google 不允许在首次上传时使用其 API。
  • 在Google Play 管理中心创建您的应用(与 iOS 不同,Fastlane 无法为您完成此操作)。
  • 请确保这 4 个勾选图标均为绿色。

    推荐顺序:Pricing & distribution,,Content ratingStore listingApp releases

    Store listing您可以在publishing/android文件夹中找到所需的资源。

  • 初始化快速通道

  cd <PROJECT_NAME>/android
  fastlane init
Enter fullscreen mode Exit fullscreen mode
  • 使用 Fastfilepublishing
  cp publishing/android/fastlane/Fastfile android/fastlane
Enter fullscreen mode Exit fullscreen mode
  • 分发您的应用
  fastlane beta
Enter fullscreen mode Exit fullscreen mode

目前没有官方插件可以自动升级 Android 版本代码(与 iOS 版本不同)。
每次部署前,请务必手动升级versionCode其中的值android/app/build.gradle

更多的

Apple Store Connect 缺少合规性

如果您不使用 Fastlane,并且不想每次推送都提供出口合规信息,那么请将此添加到您的设置中。Info.plist

<key>ITSAppUsesNonExemptEncryption</key>
<false/>
Enter fullscreen mode Exit fullscreen mode


<true/>请注意,如果您的应用使用加密, 您可能需要进行相应设置。

文章来源:https://dev.to/newbiebr/my-react-native-stack-after-1-year-37j