Создание повторно используемого компонента путем обертывания библиотеки JS в компонент React без собственного кода

Вступление

Этот пост является продолжением и улучшением методик, рассмотренных в предыдущем посте. В этой статье я описал технику, которая объединила простоту разработки Expo, возможности упаковки Webpack, автоматизацию задач Gulp и компонент WebView React Native, чтобы скрыть библиотеку JavaScript, ориентированную на пользовательский интерфейс, в компонент React Native. Преимущество использования этого метода состоит в том, что он избегает использования собственного кода; делая компонент пригодным для использования с Expo.

Хотя предыдущий пост не относится к конкретному проекту, я реализовал эту технику в своих пакетах react-native-webview-quilljs и react-native-webview-leaflet.

Проблемы

Несмотря на функциональность, этот метод имел несколько недостатков. Во-первых, файлы JS, используемые файлом HTML, отображаемым WebView, не были включены в пакет пакета из-за ограничения процесса объединения Expo. Сборщик не импортировал ничего, что было включено с помощью тега <script src="myscripts.js"></script>. Это ограничение препятствовало объединению файлов JS и CSS, на которые опирается файл HTML, в приложение Expo.

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

Обходной путь, описанный в предыдущем посте, заключался в загрузке необходимых файлов HTML, JS и CSS из репозитория проекта на GitHub перед их использованием. Это требовало хостинга файлов, означало, что пользователь должен был иметь подключение к Интернету, когда WebView был впервые использован, и обязательный доступ к файловой системе для записи и чтения загруженных файлов.

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

Исправление

В этом сообщении описывается метод, позволяющий избежать этих проблем путем встраивания JS и CSS в файл HTML, загружаемый WebView. Это дает несколько преимуществ:

  1. Полная автономная работа, так как файлы не нужно скачивать
  2. Меньший пакет NPM, так как Expo больше не нужно включать
  3. Возможность создания пакета и приложения, созданного с помощью Expo, которое можно использовать для непосредственного тестирования пакета.
  4. Пакет можно использовать в приложениях, которые не включают Expo в качестве зависимости.

Он также сохраняет основное преимущество использования этой техники; возможность обернуть библиотеку JS в компонент React Native, подходящий для публикации NPM. Кроме того, Expo может использовать этот пакет, поскольку он не содержит собственного кода.

Дизайн

Я уже использовал Webpack для объединения своих JavaScript и CSS, так почему бы не использовать его также для встраивания JS и CSS?

Я закончил тем, что добавил «встроенный JavaScript» в список обязанностей Webpack, который уже включал создание HTML-страниц из файла шаблона HTML, оптимизацию и объединение моих JS и CSS, а также размещение исходных ссылок в результирующих файлах HTML, которые импортировали пакеты JS. .

Реализация

Вышеупомянутое требование было удовлетворено путем добавления html-webpack-inline-source-pluginplugin к моему существующему файлу webpack.config.js. Thehtml-webpack-inline-source-plugin делает то, что подразумевает его название; он помещает исходный код JS и CSS в HTML. Таким образом, если WebView может загружать файлы HTML, то он гарантированно сможет загрузить файлы JS и CSS.

Благодаря Webpack я смог создавать HTML-файлы, содержащие красиво скомпонованные фрагменты JS и CSS. Теперь этот файл был готов к использованию в качестве источника React Native WebView. Webpack поместил этот файл в каталог build проекта. Затем я использовал Gulp, чтобы скопировать этот файл из сборки в каталог assets/dist. В итоге я использовал Gulp, потому что не смог найти плагин Webpack, который откладывал бы копирование до завершения упаковки.

Тест и оценка

Я протестировал и подтвердил файл, получив обновленный пакет react-native-webview-quilljs, работающий в трех разных сценариях:

  1. Режим разработки в приложении Expo, созданном для тестирования и демонстрации пакета.
  2. В Expo опубликована версия демонстрационного приложения.
  3. Импортируется как пакет NPM в совершенно отдельное приложение

Первая проблема, с которой я столкнулся, была на первом этапе. Убедиться, что Webview обращается к правильному файлу, было нетривиальной задачей. Хотя правильным местом для моего файла была папка проекта asset/dist. Отрывок из журнала Expo SDK показывает, что программа следует пути assets/assets/dist, чтобы найти файл.

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

Метод, гарантирующий, что правильный HTML-файл найден и загружен, - это включить в HTML несущественный текст. Таким образом можно подтвердить наличие файла, даже если ошибка не позволяет загрузиться JS. Если текст виден, значит, страница загружается, в противном случае существует проблема, препятствующая загрузке страницы.

Дополнительные проблемы проявились после того, как WebView действительно отобразил контент. Например, на устройствах iOS текст был слишком мелким. Это было относительно легко исправить, добавив scalesPageToFit={false} в свойства WebView. Кроме того, для загрузки содержимого HTTP из другого источника (например, фрагментов карты, требуемых Leaflet) может потребоваться установка свойства WebView mixedContentMode={‘always’}

Переход ко второму шагу превратился в проблему из-за разницы в том, как файлы _14 _ / _ 15_ обрабатываются в приложениях Expo во время разработки и в производстве. Эта разница описана здесь в разделе документации Expo, уместно озаглавленном Где живут активы. Суть в том, что файлы HTML были недоступны для производственного приложения, потому что они не были объединены.

К счастью, пользователь Форумов Expo Джесси указал мне на следующий код, который при добавлении в app.json файл обеспечивает объединение файлов HTML для производства:

"packagerOpts": {
"assetExts": ["html"]
},

Другая проблема, которая может возникнуть на этом этапе, связана с доступом к файлу и может проявляться в следующей ошибке:

Это произошло из-за того, что WebView попытался получить доступ к файлу, который был недоступен или находился не в ожидаемом месте. Еще раз убедитесь, что путь к HTML-файлу соответствует ожидаемому, и оператор import, импортирующий файл, ищет в правильном месте.

Наконец-то; на третьем шаге я импортировал опубликованный пакет в другое приложение Expo и убедился, что WebView действительно отображает содержимое, как ожидалось.

Издательский

Я хотел опубликовать в NPM прямо из каталога проектов тестового приложения Expo. Для этого я создал сценарий Gulp, который обновил dependencies и index в package.json, чтобы он подходил для публикации NPM. Сценарий также увеличил значение версии и выполнил мои операции git. Наконец, он вернул dependencies и index , чтобы снова сделать проект пригодным для использования в качестве приложения Expo.

Резюме

Таким образом, используйте плагин Webpack html-webpack-inline-source-plugin для размещения исходных файлов JS и CSS вместе с файлом HTML. Кроме того, используйте Gulp для автоматизации операций публикации и git. Кроме того, следите за журналом Expo XDE, чтобы убедиться, что Webview ищет файл HTML в правильном месте. Наконец, обновите свой packagerOpts в app.json, чтобы включить ваш HTML-файл в опубликованный пакет пакетов.

Заключение

Включение JS и CSS в мой основной файл HTML сработало. Это позволило мне создать компоненты React Native, обертывающие Quill и Leaflet, и опубликовать их в NPM для успешного использования в совершенно отдельном проекте.

Самым большим недостатком является то, что компонент WebView загружается не так быстро, как нативный компонент. Это логично, поскольку JS должен выполняться в браузере, который является частью порока WebView, перекомпилированного в Swift of Java. Было бы неплохо, если бы существовал способ загрузки и запуска WebView, возможный непосредственно перед рендерингом компонента, а затем кэшировать результаты; с целью выполнить любую тяжелую работу с JS перед отображением компонента.

Что касается звездочки в названии, этот метод должен быть довольно гибким. Однако я уверен, что есть предостережения, которые не позволят ему стать универсальным решением. И хотя я бы не стал делать ставку на то, что этот метод позволяет превратить каждую JS-библиотеку в компонент React Native, он удовлетворил мои требования, в частности, для этих двух библиотек, и в будущем станет подходящим методом.

Реджинальд Джонсон - военный ветеран с более чем 20-летним стажем, который ведет блог, создает и преподает свой путь на пути к разработке программного обеспечения. Вы можете подписаться на него в Twitter по адресу @ reginald3 или связаться с ним в LinkedIn по адресу https://www.linkedin.com/in/reggie3/