Разделение функциональности проекта на отдельные пакеты NPM

Обновление за май 2018 г.

Теперь, когда я узнал больше об использовании React Native и создании более дружественных пакетов NPM, я внес несколько существенных обновлений в пакет, подробно описанный в этой статье.

Теперь пакет называется react-audio-player-recorder-no-linking. Я выбрал это новое имя, чтобы подчеркнуть, что оно включает в себя отдельные компоненты Recorder и Player, а не только один компонент SoundRecorder, и что пакет не требует связывания с собственным кодом. Отсутствие связи обеспечивает безопасность пакета для использования с Expo.

Кроме того, весь пользовательский интерфейс (кнопки, значки и т. Д.) Был извлечен из компонентов Player и Recorder и доступен для импорта. Импортированные элементы пользовательского интерфейса могут быть предоставлены Player и Recorder как props. Что еще более важно, пользователь может предоставлять свои собственные элементы пользовательского интерфейса в качестве реквизита. Это означает, что пользователь может оформлять компоненты как угодно.

Наконец, репозиторий GitHub был изменен, чтобы отразить новое имя. Теперь пакет можно найти по адресу https://github.com/reggie3/react-native-audio-player-recorder-no-linking.

Все эти изменения приводят к значительному повышению гибкости и функциональности. Однако это также означает, что компоненты, упомянутые в статье, и соответствующие реквизиты, предоставленные компонентам, значительно изменились. Эти изменения должны быть отражены в файле readme.md, доступном в репозитории GitHub, упомянутом выше.

Вступление

Проект, над которым я усердно работал в течение нескольких месяцев, наконец, дошел до того момента, когда я был готов добавить еще одну функциональность. Пришло время дать моему творению возможность записывать и воспроизводить звук.

Мой проект построен с использованием expo.io, и они предоставляют документацию своего Audio API вместе с репозиторием Github, содержащим пример проекта, который можно запустить с помощью приложения expo. Имея такую ​​хорошую основу для работы, я старательно и методично начал включать код из примера в свой собственный проект.

Этот подход оказался успешным, но я начал понимать, что добавляю значительную часть в основном независимой функциональности в существующий проект за счет гибкости и тестируемости. Гибкость пострадает, потому что мне придется повторить процесс, если я захочу добавить такую ​​же возможность в новый проект. Тестируемость ухудшится, потому что я уже интегрировал эту функциональность нефункциональным образом, подключив ее к моему хранилищу redux и реализовав все остальные хорошие идеи, которые приходили мне в голову.

Итак, почему бы не использовать эту возможность в виде пакета NPM, который будет принимать некоторые входные данные и предоставлять мне нужную мне информацию о аудиоклипе? Это обеспечит желаемую тестируемость, даст мне массу возможностей для повторного использования и расширит мою работу за счет минимизации количества точек ввода и вывода, которые будут подключаться к конечному продукту.

Дизайн

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

Этот пользовательский интерфейс будет взаимодействовать с образцом кода, представленным в документации expo.io, чтобы фактически выполнять запись и воспроизведение.

Кроме того, пользовательскому интерфейсу также потребуются кнопки для сброса аудиоклипа в случае, если пользователь не был удовлетворен этим, и кнопка для выполнения каких-либо действий, когда пользователь завершит свою задачу. Это может быть так же просто, как вернуться на предыдущую страницу. Это приводит к окончательному требованию; пакет должен возвращать что-то, что позволяет вызывающему компоненту получить информацию о завершенном звуковом клипе. Поскольку документация expo показывает, что успешная запись приводит к файлу, сохраненному на устройстве, моей целью было бы передать соответствующую информацию о файле обратно вызывающему родительскому компоненту через функцию обратного вызова.

Реализация

Помня об этих желаемых целях, я начал создавать основу своего пакета NPM. Благодаря предыдущему опыту работы с моими проектами react-native-webview-braintree и react-native-webview-quilljs я разработал следующий процесс для создания проекта, готового к превращению в пакет NPM.

Сначала я создал пустой проект в Expo. Это приводит к рабочему приложению вместе с App.js файлом, содержащим компонент, поддерживающий реакцию, с именем App, который действует как «рамка» для публикуемого компонента. Компонент App отображает компонент SoundRecorder, который будет опубликованным продуктом. Одним из преимуществ использования этой техники является то, что я получу из нее работающее приложение, которым можно будет легко поделиться через клиент expo.

Компонент App также передает соответствующие реквизиты компоненту SoundRecorder таким же образом.

Приведенный выше список свойств не является исчерпывающим; см. документацию здесь для получения полного списка доступных свойств.

Единственная необходимая опора - это функция обратного вызова, которая получает записанную звуковую информацию от SoundRecorder. Помимо получения звуковой информации, обратный вызов также предоставляет возможность вызывающему компоненту (в данном случае App) выполнять некоторые последующие действия с информацией, предоставляемой SoundRecorder. Этим действием может быть переход на другую страницу, запись в хранилище redux, изменение пользовательского интерфейса и т. Д. Самое замечательное в том, что SoundRecorder все равно; его работа завершена после того, как он предоставит информацию о звуковом файле вызывающему компоненту. Как только SoundRecorder завершит свою задачу, он выполняет следующую onComplete функцию обратного вызова.

Как уже говорилось ранее, я сильно полагался на пример приложения expo.io Audio SDK. Репозиторий для этой локации находится на GitHub здесь. Я добавил некоторую настройку, чтобы диктовать статус кнопок записи и воспроизведения. Это включало в себя установку переменных состояния компонента для обязательного условного рендеринга указанных кнопок.

Наконец, для удобства была добавлена ​​возможность нажать кнопку и сбросить запись, а также кнопка для завершения процесса, чтобы можно было вызвать переданную функцию обратного вызова.

Окончательный результат можно увидеть ниже. К сожалению, одно ограничение аудио SDK означает, что я не могу записывать звук приложения, записывающего звук, поэтому вы должны поверить мне на слово, что оно действительно захватывает и воспроизводит звук.

Заключение

В целом мне нравится идея выделения монолитной функциональности в отдельный пакет NPM. Он поддерживает разделение проблем и тестируемость. Это также помогает мне есть слона по кусочку за раз.

Это также дает возможность внести свой вклад и получить информацию от сообщества пользователей, чтобы потенциально создать лучший продукт.

Окончательные результаты этого проекта размещены в репозитории react-native-sound-recorder-no-native на GitHub, который также содержит инструкции по установке и использованию NPM.

Вы можете отсканировать следующий QR-код, чтобы запустить это приложение, если на вашем устройстве Android или iOS установлен клиент expo.io:

Этот компонент был успешно протестирован на Android и iPhone.