Сервисы Digital Skynet
80

React Native: структурируем проект и управляем статическими ресурсами

React и React Native - это всего лишь фрэймворки, они не диктуют, как структурировать проекты. Все зависит от ваших предпочтений и особенностей проекта. В статье мы рассмотрим, как структурировать проект и как управлять локальными assets.

В закладки
Digital Skynet

Для проекта, загруженного с помощью react-native init, мы используем только базовую структуру.

Есть папка ios для проектов Xcode, папка Android для проектов Android и index.js и App.js для отправной точки React Native.

Как человек, который работал с native на Windows Phone, iOS и Android, я обнаружил, что структурирование проекта сводится к разделению файлов по типу (type) или функции (feature)

Группировка по типу

Так мы можем видеть тип каждого файла и легко запускать скрипт к определенному типу файла. Это общее правило для всех проектов, но оно не отвечает на вопрос «о чем проект?» Это новостное приложение? Это приложение для лояльности?

Организация файлов по типу удобна для машины, но не для человека. Мы работаем над фичами не один день, и искать файлы в нескольких каталогах - это лишние хлопоты.

Группировка по функциям

Более разумным решением является организация файлов по функциям. Файлы, объединенные одной функцией, должны быть размещены вместе. И тестовые файлы должны храниться вместе с исходными файлами.

Функция может быть связана с логином, подпиской или профилем пользователя. Функция может содержать вспомогательные, если они принадлежат одному и тому же функционалу. Если бы мы захотели переместить вспомогательную функцию, это было бы легко, так как все связанные файлы уже сгруппированы.

Моя типичная структура проекта, основанная на функциях, выглядит так:

Помимо традиционных файлов App.js и index.js и папок ios и android, я помещаю все исходные файлы в папку src. Внутри src у меня есть res для ресурсов, library для общих файлов, используемых во всех функциях, и screens для экранов.

Как можно меньше зависимостей

React Native основан на множестве зависимостей, я стараюсь быть в курсе всех обновлений. Для навигации я использую react-navigation.

Я не поклонник redux, так как он добавляет ненужную сложность проекту. Добавляйте зависимость только тогда, когда она вам действительно нужна, иначе вы просто создаете себе больше проблем.

Что мне нравится в React - это компоненты. В компоненте мы определяем вид, стиль и поведение. React имеет встроенный стиль - это похоже на использование JavaScript для определения сценария, HTML и CSS. Это соответствует функциональному подходу, к которому мы стремимся. Поэтому я не использую стилизованные компоненты. Стили - это объекты JavaScript, мы можем делиться ими в библиотеке.

src

Мне очень нравится Android, поэтому я называю src и res в соответствии с соглашениями о папках.

react-native init настраивает babel для нас. Но для типичного проекта JavaScript правильно организовывать файлы в папке src. В моем electron.js приложение IconGenerator, я поместил исходные файлы внутри папки src. Это не только помогает с точки зрения организации, но и помогает babel транспилировать всю папку сразу. Одна команда, и у меня есть файлы в src транспилированные dist в мгновение ока.

Screen

React основан на компонентах. Есть контейнер и презентационные компоненты, но мы можем создавать компоненты для создания более сложных компонентов. Это Page в Windows Phone, ViewController в iOS и Activity в Android.

index.js или нет?

Каждый screen считается точкой входа. Вы можете переименовать LoginScreen.js в index.js, используя функцию Node модуля:

Модули не обязательно должны быть файлами. Мы также можем создать папку find-me в разделе node_modules и разместить index.js файл там. Та же строка require('find-me') будет использовать index.js.

Вместо import LoginScreen from './screens/LoginScreen', мы можем просто сделать import LoginScreen from './screens'.

Использование index.js приводит к инкапсуляции и предоставляет публичный интерфейс для этой функции. Я предпочитаю явное имя для файла, следовательно, имя LoginScreen.js.

Navigator

React-navigation самый популярный выбор для обработки навигации в приложении React Native. Для такой функции, как onboarding, есть много экранов, управляемых навигацией стека, поэтому есть OnboardingNavigator.

Вы можете думать о Navigator как о чем-то, что группирует вспомогательные экраны или функции. Поскольку мы группируем по функциям, разумно разместить Navigator внутри папки с функциями. Обычно это выглядит так:

Library

Самая противоречивая часть при структурировании проекта. Если вам не нравится имя library, вы можете назвать utilities, common, citadel, как угодно.

Здесь мы размещаем общие утилиты и компоненты, которые используются многими функциями.

В React Native нам часто нужно реализовать кнопку с фоновым изображением на многих экранах. Вот простой пример, который остается внутри library/components/ImageButton.js. Папка components предназначена для повторно используемых компонентов, иногда называемых atomic components. В соответствии с соглашениями об именовании React первая буква должна быть прописной.

Если мы хотим разместить кнопку внизу, мы используем функцию utility для предотвращения дублирования кода. Вот так library /utils /moveToBottom.js:

Используйте package.json, чтобы избежать относительного пути

Где-то в src/screens/onboarding/term/Term.js мы можем импортировать данные, используя relative paths:

Это грозит ошибками, так как нужно вычислить, сколько .. мы должны поставить. И если мы перемещаем объект, все пути должны быть переписаны.

Поскольку библиотека предназначена для использования во многих местах, хорошо ссылаться на нее как на абсолютный путь. В JavaScript обычно существует 1000 библиотек для одной задачи. Быстрый поиск в Google показывает тонны библиотек для решения вопроса.

Решение состоит в том, чтобы превратить библиотеку в модуль, чтобы узел мог найти его. Добавление package.json в любую папку превращает его в модуль узла . Добавить package.json в папку библиотеки с простым содержимым:

Теперь в Term.js мы легко можем импортировать данные из библиотеки, потому что теперь это модуль:

res

Вы можете задаться вопросом, какие res/colors, res/strings, res/images и res/fonts приведены в примерах выше. Для front end проектов есть компоненты и стиль использования шрифтов, локализованных строк, цветов, изображений и стилей. JavaScript очень динамичный язык и легко использовать строгую тепизацию везде. У нас может быть куча #00B75D color во многих файлах или Fira как fontFamily во многих текстовых компонентах. Всё это трудно рефакторить.

res/colors

res/strings

res/fonts

res/images

Группировка цветов, изображений, шрифтов с палитрой

Дизайн приложения должен быть согласованным. Некоторые элементы должны быть одинаковыми, чтобы не запутать пользователя. Например, в тексте заголовка должен использоваться один цвет, шрифт и размер шрифта. Компонент Image должен использовать то же изображение. В React Native мы уже используем имена стилей с const styles = StyleSheet.create ({}),.

Пример, в котором определяются общие стили для заголовка и текста:

res/palette

Далее мы можем использовать их на экране.

Здесь мы используем оператор распространения объекта для слияния palette.heading и нашего объекта пользовательского стиля. Это означает, что мы используем стили из palette.heading, но также указываем дополнительные свойства.

Создание изображений

Вы можете увидеть в /src/res/images.js свойства для каждого изображения в папке src/res/images

Это утомительно делать вручную, и если есть изменения в соглашении об именах изображений, мы должны обновить данные. Вместо этого мы можем добавить скрипт для создания images.js на основе изображений, которые у нас есть. Добавьте файл в корень проекта /scripts/images.js:

Node удобен тем, что у нас есть доступ к модулю fs, который действительно хорош в обработке файлов. Здесь мы просто просматриваем изображения и обновляем соответственно /src/res/images.js.

Всякий раз, когда мы добавляем или меняем изображения, мы можем запускать:

И мы также можем объявить скрипт внутри нашего основного package.json

Теперь мы можем просто запустить npm run images и получить обновленный файл images.js.

В этой статье я рассказал и показал вам, как структурировать папки и файлы в проекте React Native. Также узнали, как управлять ресурсами и получать доступ к ним более безопасно.

Адаптированный перевод статьи How to structure your project and manage static resources in React Native от Digital Skynet :)

Материал опубликован пользователем. Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Написать
{ "author_name": "Digital Skynet", "author_type": "self", "tags": ["00b75d"], "comments": 0, "likes": -3, "favorites": 3, "is_advertisement": false, "subsite_label": "services", "id": 50650, "is_wide": false, "is_ugc": true, "date": "Mon, 12 Nov 2018 12:15:45 +0300" }
{ "id": 50650, "author_id": 187179, "diff_limit": 1000, "urls": {"diff":"\/comments\/50650\/get","add":"\/comments\/50650\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/50650"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 200396, "possessions": [] }

Комментариев нет 0 комм.

Популярные

По порядку

0
{ "page_type": "article" }

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fizc" } } }, { "id": 4, "label": "240х200_mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "flbq" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "bscsh", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-223676-0", "render_to": "inpage_VI-223676-0-1104503429", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=bugf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Плашка на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudx", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byzqf", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvc" } } }, { "id": 19, "label": "Тизер на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "p1": "cbltd", "p2": "gazs" } } } ]
Команда калифорнийского проекта
оказалась нейронной сетью
Подписаться на push-уведомления
{ "page_type": "default" }