Галоўная / Артыкулы / Толькі React Native, Expo чыра Flutter: падбор мобайльных тэхналогій да вашай команды

Толькі React Native, Expo чыра Flutter: падбор мобайльных тэхналогій да вашай команды

Практычныя параверынкі чыстага React Native, Expo і Flutter: як кожны з іх выглядае ў кодзе, дзе кожны мае слабасці, а таксама пяцьх-запытковая схема для выбору між імі.

2627 слоў

Выбір мобільнага стэка, які працюе на розных платформах, раней быў пытаннем таго, якія компрэсіі вы можете прыміць. Сёння React Native, Expo і Flutter можаюць ствараць дапрыягі, якія выглядаюць натыўна, працуюць павольна і падходяць для вельмі большых аудытарыёў, таму чыстая швальнасць рэдка калі вялікана фактар. Фактарам є падходжымасць: навыкі, якія вже ў вашай командзе, код, які вы вже маеце, і штоўка, калі вам трэба прайсці да магазінаў. У гэтым артыкуле Expo рассматраецца як самастоятны варыянт, а не толькі дапаможны элемент для React Native; показана, як кожны варыянт выглядае на практыцы, і ў канцы даўаецца некалькі пытанняў, якія можна выкарыстаць для выбору.

Што змянілася ў всіх трох стэках

Некалькі структурных слабасцей, якія вплывалі на болейшыя порэвананні, былі усунуты:

  • Новая архітектура React Native є стандартной. Янаея адзін з класычным асінхронным мостам, таму JavaScript і код на натыўнай мове можаць кантактывацца болей прымусова. У результате вызывы да натыўных модуляў стаюць значна дарожэйшымі.
  • Рендерар Impeller у Flutter замяніў Skia як стандартны на мобільных прыстроях. Impeller збірае сваі шейдеры заздалегідь, чым усунуў вядомыя проблемы з першым запускам, вызваныя компіляцыей шейдераў, і дапамагае падтрымваць стабільную частоту кадраў.
  • Expo стаў стандартным спосабам стварэння дапытак на React Native. Ён больш не ўжо являе сабой інструмент толькі для пачаткуючых, а ўсерйозны інструментарый, які викорыстоўваюць вялікія компаніі.

Публікуемыя тэсты зазвычай паказуюць, што Flutter мае незначную перадачу ў процесе адрасавання інтэрфейсаў з вялікай колькасцю анімэйшнаў, тады як React Native пераважае па часе запуску, выкарыстоўванні памяці і працэсах вводу-выходу на роўні аператывай системы. Ставіцеся з асторожнасцю да конкрэтных цифраў, адтаколькі яны сильна разніцяюцца залежна ад прыкладнення і прыстрою. Для большасці продуктов гэтыя разлікі вучыніліся не такімі значнымі, каб вплываць на вынік. Якщо хочаце пазнаць позыцыю команд, якія вжываюць гэтыя выборы ўжо дзеўяль, наша стаття па прыему выбора між Flutter і React Native, якія стаюць зрозумелымі толькі пад час роботы прыкладнення раскрывае далекатэчныя наследкі.

Чысты React Native: максимальны контроль, максимальная адпаведнасць

React Native дазваляе пісаць інтэрфейс на JavaScript або TypeScript з викорыстанням React, тады як фрэймворк атрыбутуе справжнія компаненты платформы для iOS і Android. Не існуе WebView і ніякога спецыяльнага canvas: View становіцца натыўным відображэнням, а Text — натыўным компанентам тэксту.

Лічылка нижэй паказвае базовую структуру прыкладнага програмы па Новай архітэктуры з викорыстанням рендерара Fabric. Стан храніцца ў хуку useState, кнопка являе сабою элемент Pressable, а стылі задаюцца ўсё разам за дапамогою StyleSheet.create, што дазволяе іх перапрацаваць та практычна викорыстоўваць знову.

// App.tsx — React Native (New Architecture, Fabric)
import React, { useState } from 'react';
import { View, Text, Pressable, StyleSheet } from 'react-native';

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <View style={styles.container}>
      <Text style={styles.counter}>{count}</Text>
      <Pressable style={styles.button} onPress={() => setCount(c => c + 1)}>
        <Text style={styles.buttonText}>Tap me</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, alignItems: 'center', justifyContent: 'center' },
  counter: { fontSize: 48, fontWeight: '700', marginBottom: 24 },
  button: { backgroundColor: '#2563eb', paddingHorizontal: 24, paddingVertical: 12, borderRadius: 12 },
  buttonText: { color: 'white', fontSize: 16, fontWeight: '600' },
});

Нічога ў гэтым фрагменте не є спецыфічным для Новай архітэктуры; той самы код компаненту працюе і ў адной, і ў другой. Змяны в архітэктуры відбываюцца ў глыбіні, у спосабе, яким рендерар і натыўныя модулі взаімадзейнуюць з JavaScript.

Адрозніцы

  • Асалітныя віджэты. Вы атрымлеўце сабе самыя кантролі платформы, якія забезпечваюць доступнасць і правильную відобразэнне тэксту, а не яе апрыксіматыўную версію.
  • Найбольшы резерв талантав. Навыкі праектавання на JavaScript, TypeScript і React зустрэчаюцца значна частае, чым навыкі для іншых варыянтам.
  • Полны асалітны доступ. Вы маеце права на каталогі ios/ і android/, таму можете выкарыстоўваць мовы Swift, Kotlin, Objective-C або Java калі толькі патрэбна.
  • Вялічзёны экасыстэм. npm праставляе больш пакетаў ад трэціх сторон, чым pub.dev, і большасць мобільных SDK-аў для платежаў, карт і аналітыкі прыносіць офіцыйныя обгорткі на базе React Native.
  • Шырэйшыя асалітныя вызывы. Fabric, TurboModules і JSI усунулі стары бутлег асінхронных пераходаў, таму вызывы да асалітнага коду выкананыя майже мгновенна.
  • Адзінаванне коду з вебам. За дапомогай React Native Web каманда, яка вже мае веб-дзеяпл на базе React, можа перадыслаўваць большую частку свайго логіка і нават дзеяныя компаненты.
  • Слабасці

    • Вы самі керуеце інструментамі для стварэння натыўных дзеяплаў. Несувязкі версый Xcode, Gradle і CocoaPods, а таксама канфлікты залежнасцей у натыўных дзеяплах застаюцца частым выклікам.
    • Дасягненне адноснаўпорядкованасці на розных платформах трэбуе зусиль. Пакалькі фреймворк намеравана перадае даныя на натыўныя элементы, iOS і Android будуць выглядаць разна, якщо толькі вы не спроектуеце ўсё так, каб воны былі адноснаўпорядкованы.
    • Інфраструктура для розповсюджэння — ваша адпаведальнасць. Стварэнне CI/CD, падпісвання коду і апдэйтаў без перзавантажэння — задачы, якія нелегка рэалізаваць з нуля, і самэ гэтае ўсуне Expo.
    • Неравнамерная якасць трэціх сторон. Якасць адтрымання і падтрымкі натыўных модуляў варьюецца ад выключна высокай да занедбанай.

    Практычныя парады

    • Ўтримайцеся ад запуску новага дапрыягу ў чыстам React Native, як толькі у вас няма конкрэтнай прычыны, такой як спецыяльна натыўная SDK або існуючы натыўны дапрыяг, які вы мігруеце пашагоўна. Пачніце з Expo і стварайце натыўныя проекты толькі тады, калі гэта неабходна.
    • Для інтеракцый, чутлівых да выконавачасоўных характэрастыкаў, выкорыстоўвайце react-native-reanimated і react-native-gesture-handler. Яны выконваюць анімацыі і жесты на галоўнай вясі UI, таму занятая вясь JavaScript не спрычыняе падвыпадаў кадраў.
    • Закінчыце Hermes у ўвёранам стане; гэта стандартны двыжак. Ён заздалегідь компілюе JavaScript у байткод, што значна скарочывае час запуску і викорыстоўванне памяці у пораўнанні з JavaScriptCore.

    Expo: React Native з уключанай інфраструктурой

    Expo — это фреймворк і набор служб, створаныя на базе React Native. Раней яго репутацыя была такой, што ў яму існавала обмежаная среда без можлівасці доступу да натыўнага коду. Адныя гэтыя умовы больш не актуальны: завдака тэхналогіі prebuild, якая таксама называецца continuous native generation (CNG), Expo можа працаваць з усім екосыстэмам натыўных модуляў.

    На экране нижчэй выкарыстоўваецца Expo Router, які супарабатоўвае файлы ў каталозе app/ з маршрутамі так сама, як Next.js для вебу. app/index.tsx — галоўны маршрут, а router.push('/profile') пераводзіць на файл, які визначае /profile. Глыбокія лінкі і веб-адрэсы таксама ствараюцца на адной і той жа основе.

    // app/index.tsx — Expo Router (file-based routing)
    import { View, Text, Pressable } from 'react-native';
    import { useRouter } from 'expo-router';
    
    export default function HomeScreen() {
      const router = useRouter();
    
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', gap: 16 }}>
          <Text style={{ fontSize: 24, fontWeight: '600' }}>Welcome</Text>
          <Pressable onPress={() => router.push('/profile')}>
            <Text style={{ color: '#2563eb' }}>Go to Profile</Text>
          </Pressable>
        </View>
      );
    }
    

    Для стварэння і запуску проекту трэба выканаць тры каманды. Першая стварае структуру аплікацыі, а npx expo start запускае сервер развіцця, ўнаследке чаго можна ачыніць аплікацыю на прыстрое чы сімулятары.

    # Spin up a new project in under a minute
    npx create-expo-app@latest my-app
    cd my-app
    npx expo start
    

    Адрозніцы

    • Няма встроеных адзінства для пачатку работы. Для большайшай часткі працы няўжоба Xcode або Android Studio; вы можете тэставаць на фізычным прыстрое за дапамою Expo Go або спецыяльнага кліента для разработкі.
    • EAS Build. Компіляцыя для iOS і Android адбываецца ў хмаре з любой операцыйной системы, таму вы можетэ стварыць версію для iOS з Windows або Linux.
    • EAS Update. Апдэйты праз мерыя каналы негараздзе дастаюць змены ў JavaScript і ресурсах корыстнікам адразу, без чакання на перагляд у магазіне, як толькі няма зменаў у натыўным кодзе.
    • Expo Router. Маршрутызацыя на адной заснованай на файлах, з глэбокім паўязваннем і універсальным навігацыяй для вебу і натыўных прыстроёў, ёсць ужо з самага пачатку.
  • Большы кастамізаваныя SDK. Пакеты такія як expo-camera, expo-notifications, expo-location і expo-image інтеграваны, задокументаваны і супараднаўлены па версіях, таму яны можаць працаваць разам.
  • Плагіны для налаштавання. Вы можете зменяць файлы натыўных проектаў, такія як Info.plist і AndroidManifest.xml, за дапамогою app.json, замест таго каб рэдагаваць іх вручную, што дапамагае падтрымваць воспроізнаемасць процэсаў CI.
  • Няма прыгвожчання. Пад спадом застаецца React Native. Выкананне npx expo prebuild стварае натыўныя папкі кожны раз, калі вам трэбае цэлы натыўны контроль.
  • Слабасці

    • Niche SDK-яў трэбуе дадатковай працы. Кальколька спецыялізаваных натыўных SDK-аў яшчэ вымагае стварэння савастай плагіна налаштоўкаў або натыўнага модуля, што ўскладняе роботу чырвоныя React Native, хоча разліка становіцца все меньшай.
    • Пятна Expo Go. Частая залежнасць ад Expo Go можа закрыць факт таго, што спецыяльны натыўны модуль не будзе працаваць, пакуль не будзе створана версія для разработкі. Гэта часта стварае проблемы для новачакоў.
    • Косты сервісаў. EAS Build і Update маюць безплатныя тарифы, але серйозныя команды зазвычай пераходзяць на платныя пакеты, чаго не трэба робіць з чырвоным React Native з самастаяным CI.
    • Пасляўраныя ліміты. Будучы шаром на базе React Native, Expo застаецца з своімі недакладнасцямі: разніця ў інтэрфейсах платформ і аддзін нит JavaScript, якая можа стаць вузкам месца пад адной занадта вялікай вычысцоўкай.

    Практычныя парады

    • Заўядзейце npx expo prebuild, калі вам патрэбны натыўныя модулі, якіх не падтрымвае Expo. Ён стварае папкі ios/ і android/ за патрэбай, таму натыўны код завжды є на доступзе. Наша стаття па прыеме натыўных папак як выходу будовы з аднойчынам Expo prebuild і CNG дакладна поясняе гэты процес.
    • Іспользуйце EAS Update для выправлення бягучых проблем, а не для функцый, якія зменяюць працэс натыўнага програмнага забезпечэння. Правілы магазінаў дапытак обмежваюць тое, што можа быць зменена ў завантажаным кодзе, а выкліканне новых функцый пад маскай OTA-апдэйта можа прывести да адхоўкі; перад тым, як на гэта паспеліцеся, прачытайце чынныя правілы Apple і Google.
    • З аднойчынам новага проекту застосавайце Expo Router. Адкорэгаванне маршрутацыі на аднойчыні файлаў у існуючай системе навігацыі є складным.
  • Заўсёды запускайце expo doctor пры кожнай практычной нарабатце. Ён выявляе несуразнасці ў залежнасцях і версіях, якія інакш былі б прычыной незрозумелых адмов у нарабатцы для натыўных сістэм.
  • Flutter: контроль над кожным пікселем

    Flutter выбірае абсалютна іншы падход. У працоўным режыме ён не викорыстоўвае віджэты платформы, а сам стварае всю інтэрфейсную сістэму за дапамогою своего двыжка Impeller, пры чым код на мове Dart заздалегідь компілюецца у натыўны машынны код для процэсараў ARM або x86.

    Кантэйнер на мове Dart, паказанный нижчэ, адпавядае прыкладу React Native. MyApp абгортае всю аплікацыю ў MaterialApp, CounterScreen являе сабою клас StatefulWidget, у якога клас стану храніць значэнне _count, а нажатыя кнопкі вызываюць функцыю setState, якая прыказвае Flutter перзбудаваць тую частку інтэрфейсу з новым значэнням.

    // main.dart
    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(home: CounterScreen());
      }
    }
    
    class CounterScreen extends StatefulWidget {
      const CounterScreen({super.key});
    
      @override
      State<CounterScreen> createState() => _CounterScreenState();
    }
    
    class _CounterScreenState extends State<CounterScreen> {
      int _count = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('$_count', style: const TextStyle(fontSize: 48, fontWeight: FontWeight.bold)),
                const SizedBox(height: 24),
                ElevatedButton(
                  onPressed: () => setState(() => _count++),
                  child: const Text('Tap me'),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    Рабочы процес з командной лініі пакрывае весь жыцёвы цикл: стварэнне проекта, ўпрацоўкі яго з адразуевым перзапускам пад час розработы, а таксама стварэнне файнаў для публікацыі ў Google Play (пакет аплікэйшна) і App Store (файл IPA).

    flutter create my_app
    cd my_app
    flutter run          # hot reload in under a second
    flutter build appbundle --release   # Android
    flutter build ipa --release         # iOS
    

    Перавагі

    • Ідэнтычны інтерфейс паўсюду. Усім віджэтамі керуе сам Flutter, таму ўсё працюе аднакова на iOS, Android, у вебе і на десктопе без спецыфічных особлівасцяў платформ.
    • Высокая карыстоця анімацый. Завдзяк заздалегідь скомпільваным шейдерам і прымусоваму доступу да GPU через Impeller, Flutter часта перавышае іншыя аплікэйшныя раштры ў спрэчах за частоту кадраў у складных інтерфейсах з великай колькасцю анімацый.
    • Шасць цэлей з адной базы коду. iOS, Android, веб, Windows, macOS і Linux усе будуюцца з таго ж коду на мове Dart.
  • Адмінкстрыменты высокай якосці. DevTools, можлівасць гарячага перзачытання і стабільны, добра задокументаваны каталог віджэтов робяць ўсёце процес разработкі приўетным.
  • Няма інтэрпретара ў сцэнарыі выканання. Компіляцыя заздалегідь у машынны код означае, што ў час выканання няма двайчыка JavaScript або іншага мосту.
  • Апробавана у великіх масштабах. Google яе падтрымвае, а таксама вялікія продакшн-проекты, такія як Google Pay, додаткі BMW і Xianyu ад Alibaba, выкарыстоўваюць яе.
  • Слабасці

    • Экосыстэма Dart меньшая. Працаваць з яйнымі фахівцамі складней, чым з JavaScript або TypeScript, і нават апытныя разработчыкі зазвычай патрабуюць калькі недзеў, каб стаць продуктывнымі.
    • Ёй можа здавацца трохі нестандартной. Усёлякія платформовыя віджэты не выкарыстоўваюцца, таму уважныя корыстувальнікі можа зазначыць незначныя разлікі ў працэсе выканання, хоча гэтыя разлікі значна зменшыліся.
    • Большыя бінарныя файлы. Адынэткі двыжак Flutter ўключаецца ў кожныя дапрынты, таму пакеты зазвычай маюць большыя розмеры, чым адпаведныя дапрынты на React Native.
    • Менш пакетаў для спецыяльных задач. Сайт pub.dev ўжо непарадны, але менш развіты, чым npm, бальш таму, калі йдзе пра пакеты-обгорткі навакол спецыялізаваных натыўных SDK-аў.
    • Немагчымасць перадаўжання коду з веб-версіі React. Арганізацыя, якая вже мае развіты код на React для вебу, не можа перадаўжыць яго ў мобільныя дапрынты.

    Практычныя парады

    • З самага першага дня увімкніце flutter analyze з строгімі правіламі лінтингу. Абараненне ад значэння null у Dart ёсць справжнім прыямлём, але толькі якщо вы не будете паслабляць яго за дапамогою типаў dynamic у всіх месцах.
    • Для чаго-небудзь большага, чым протатэп, выберыце метод карыстоўвання станам, такі як Riverpod або Bloc; сама функцыя setState не падходзіць для розрабкі рэальных дапрынтов.
  • Перад тым, як заключаць, што у вас проблема з паваленням частоты адрадзеныя, перагляньце прафіль у режыме Performance засобам DevTools. Impeller уже пазбіралі большую частку проблем з компіляцыяй шейдэраў у минулом.
  • Якщо веб-продукт мае важлівую ролю, адразу прыступіце да тэставання Flutter Web. Його рендерары працуюць інакш, чым у мобільных версіях, а размах пакета можа быць неспадзяваным. На момент напісання Flutter акцэнтаваецца на рендерарах на аснове CanvasKit, таму пераканайцеся ў актуальной даследчыцкай матэрыяле, якія опцыі ўсё ще падтрымліваюцца.
  • Пяць запытанняў, якія дапамагаюць выбраць

    Раскідваеце іх па порядку. Зазвычай перша запытанне з ясным адказам вяршыць рашэнне.

    • Чы ваша команда вже працуе з React і JavaScript? Яктось — застойцеся ў экосістэме React Native і выкорыстоўвайце Expo як стандарт. Як ні — і вы маеце свабоду выбору, то Flutter і Expo абоўва є практычнымі варыянтамі; выберыце той язык, які ваша команда хоча болей хацела бы выучыць.
    • Чы рэклікаецеся да дизайна, ідентычнага пікселям, або складных спецыяльных анімацый, як у гэмы, творчых інструментах чы прыкладнае програмаў з вялікай колькасцю візуалайзацый? Flutter ў такіх случаях являецца лепшым выборам.
    • Чы хочаце раздаваць код чы компоненты з існуючай веб-аплікацыей на React? React Native, за дапамогою React Native Web, мае рэальную перадачу; Flutter на вебе працюе адначасова з іншымі тэхналогіямі.
    • Чы трэба адправляць пасправкі, якія ўключаюць толькі JavaScript, без перагляду з боку магазіна, чы ствараць аплікацыі для iOS без Mac? EAS Update і EAS Build з Expo працююць з гэтымі задачамі без проблем.
    • Чы вбудовваеце мультіплатформеныя экраны ў велікую існуючую натыўную аплікацыю? Чысты React Native чы падтрымка дадаць элементы ў аплікацыю у Flutter паслужаюць лепшым рашэнням, чым новы проект у Expo.

    Рэкамендацыі

    • Для каманды, якая работае з React або JavaScript і стварае новы прылад, выберыце Expo. Ён усуне большую частку проблем, звычайная для React Native, у сфере інструментаў для роботы з натыўным кодам, процэсаў CI/CD і апдэйтаў праз OTA, пры чым заставляе доступным усю моц натыўных тэхналогій, калі гэта неабходна.
    • Выберыце Flutter, калі важнейшыя ўмовы — гладкасць інтэрфейсу, карыстоўнасць анімацый і можлівасць выкарыстоўвання прылада на мобільных, десктопных прыладах і у вебе, чым перадпісвоўванне екосістэмы JavaScript, або калі ваша каманда не мае чыстага праблэму з выборам языка і проста пачынае роботу з нуля.
    • Застаўце чысты React Native для ситуацый, калі неабходна безпасэродная контроль над прыладовымі проектамі, як-то у разе вялікай існуючай базы натыўнага коду або нестандартных трэбаванняў да інтеграцыі з натыўнымі тэхналогіямі.

    Заключэнне

    Тры ўстаўкі достатньа схадзіліся па спэктару выконання і розвіты, таму можлівасці фрэймворку рэдкая стаюць прычынай спакускі. Ключовыя фактары — це людзі ў вашай командзе, код, які у вас вялікі ўжо є, і шырокае час, які вам трэба, каб выпусціць продукт. Вважайте Expo стандартным спосабам выкарыстоўвання React Native, заставьце чысты React Native для ситуацый, калі главная мета — кераванне натыўнымі проектамі, а Flutter — калі контроль над рэндарынгам і можлівасць работы на кальколькі платформ пераважаюць перавагі застосоўвання JavaScript. Як бы вы не выбралі, пераканайцеся ў надзеянасці самой рызыкаванай часткі вашага дапрынтку — будзь то натыўны SDK, складная анімацыя чы ўжо гэты веб-варыянт — ў першыя тыдні, а не пад час выпуску.