Мне нравится узнавать что-то новое и решать проблемы, связанные с этим занятием. Недавно я решил изучить Node.js и улучшить свои навыки в React. Что ж, у меня появилась идея многопользовательской игры, которую я обязательно скоро напишу. Обещаю. :)
Это своего рода совпадение, что мой клиент попросил меня создать интерфейсное приложение для отображения информации о заказах и аналитики из двух его интернет-магазинов на базе WooCommerce. Кроме того, должна была быть возможность изменять статусы заказов. Звучит как классическое веб-приложение!
Я мог бы выбрать более традиционный подход: статическое интерфейсное приложение, использующее установленную серверную структуру PHP и MySQL. Но… Почему бы не использовать что-нибудь современное и более адаптируемое? Может быть, что-то, что даже можно было бы превратить в мобильное приложение или Saas. Фактически, клиент переходил с Magento на WooCommerce, и наша команда уже создала ему новый веб-сайт с инновационной страницей оформления заказа, похожей на реакцию. Задача этого нового проекта заключалась в замене старого подхода новым, и также очень важно провести четкое различие между ними.
Думая об архитектуре
Будущее приложение казалось довольно простым. Но только на первый взгляд. Было бы здорово иметь простой, но надежный способ аутентификации. Следующая наиболее востребованная функция - это легкое обновление информации в реальном времени. Новые заказы поступают постоянно, и многие из них являются экспресс-заказами, которые необходимо выполнить в день заказа.
Не говоря уже о возможной конфликтной ситуации, когда два или более клиентов отправляют запрос на изменение статуса для одних и тех же заказов. Я решил разделить приложение на два - серверное и клиентское. Серверное приложение будет действовать как агрегатор данных, а клиентское приложение будет действовать как простое средство просмотра. Информационный поток будет выглядеть так:
Для реализации этой стратегии я создал:
* плагин WordPress, который предоставляет конечные точки REST API;
* серверное приложение Node.js + MongoDB;
* легкое и современное веб-приложение на основе React, которое будет служить клиентским приложением
Я использовал JSON Web Tokens (JWT) для аутентификации между приложением на основе Node.js и плагином WP и приложением на основе React.
Плагин WordPress
По сути, все, что мне нужно от сайтов на базе WooCommerce, - это данные. Вот интересный вопрос: передавать данные активно (отправлять их на определенные конечные точки серверного приложения) или пассивно (предоставлять через определенные конечные точки WP REST API)? Я выбрал последнее по двум причинам:
1. минимальная зависимость от окружения сайтов, нулевая дополнительная настройка хостинга - ни wp-cron, ни реального cron, ни чего-то еще; пуленепробиваемое решение;
2. некоторые данные, например отчеты о продажах, лучше запрашивать только по запросу, поэтому нет необходимости в отдельной настройке для разных типов данных; все доступно через один и тот же интерфейс - REST API - но с разных конечных точек;
Кроме того, в WordPress нет метода аутентификации JWT, поэтому я реализовал его в плагине, а также предоставил свои собственные конечные точки API. Хотя большинство из них являются форками существующих из WC, конечная точка заказов была изменена для вывода метаданных конкретных заказов - информации о выбранных пользовательских параметрах Uni CPO plugin.
Плагин доступен на GitHub, вы можете попробовать его или выполнить форк.
Серверное приложение
Приложение построено на фреймворке hapijs. Я нашел его очень гибким и интуитивно понятным. Напомню, что это был мой первый опыт работы с Node.js, и простота фреймворка мне очень помогла.
Связь на основе событий в реальном времени осуществляется Socket.io, который интегрирован в приложение и доступен только через некоторые серверные маршруты, а не один для всего. Я обнаружил, что этот подход работает лучше, поскольку приложение более структурировано. Я пробовал использовать оригинальный плагин hapi-io, но он не работал с новейшей версией hapijs (17.4+), поэтому я просто форкнул и адаптировал его.
Интеграция с Socket.io позволила легко обновлять данные клиентских приложений. Кроме того, мне пришлось найти обходной путь, когда несколько клиентов меняют статус одного и того же заказа, поэтому отменяют действия друг друга. Итак, клиенты «разговаривают» друг с другом через сервер. Это крайне простое решение, когда первый, кто инициирует действие, отправляет массив заказов, которые необходимо временно отключить для выполнения каких-либо действий с ними. Сервер передает эти данные всем остальным клиентам, которые блокируют заказы в пользовательском интерфейсе. Вот как это работает:
Для реализации JWT auth я использовал эти два пакета: hapi-auth-jwt2 и j« sonwebtoken ». Первый действует как плагин hapijs. Можно пометить определенные маршруты как требуемые JWT-авторизацию, а другие оставить неограниченными. Второй используется для выпуска и проверки токенов JWT для моего клиентского приложения.
Серверное приложение доступно на GitHub. В этой версии исключен код, связанный с получением и отправкой заказов, только отчеты о продажах.
Клиентское приложение
Он построен на React. Я использовал create-response-app для запуска процесса разработки. HTTP-клиент axios мне отлично подходит. Кстати, я использую его для обоих своих приложений. Библиотека дат« Day.js » как легкая альтернатива moment.js, но с тем же API. Данные о заказах отображаются с помощью response-table - быстрой и расширяемой сетки данных для React.
Я также использовал ReaKit (ранее известный как reas, но такого пакета npm больше не существует). Этот инструментарий состоит из различных компонентов, и я использовал многие из них, которые помогли мне ускорить разработку пользовательского интерфейса. Они легко компонуются, так как вы можете использовать свойство as и визуализировать компонент как любой HTML-тег, который вам нравится. В моем приложении я отображаю ссылки как теги span:
/ Core import React, { Component } from 'react'; import PropTypes from 'prop-types'; // Components import { styled, Link } from 'reas'; // Styled CSS const MyLink = styled(Link)` margin:10px 40px 10px 0; cursor:pointer; `; class GoBackLink extends Component { static propTypes = { currentPage: PropTypes.string.isRequired, switchPage: PropTypes.func.isRequired }; _goHome = () => { const { switchPage } = this.props; switchPage('home'); }; render () { const { currentPage } = this.props; return (['home', 'login'].includes(currentPage) ? null : <MyLink as="span" href="#" className="gloria-font" onClick={this._goHome}> To the list </MyLink>); } }
ReaKit использует стилизованные компоненты для стилизации компонентов. Он представляет собой технику CSS-in-JS, когда CSS составляется с использованием JavaScript, а не определяется во внешних файлах. Я нашел, что это идеально подходит для моего случая. Мне не нужно создавать отдельный файл CSS или SASS для каждого компонента React только для хранения нескольких строк стилей. Все находится в том же файле, что и компонент.
Клиентское приложение доступно на GitHub. В этой версии исключен код, связанный с отображением заказов. Только отчеты о продажах.
Вывод
У меня есть ценный опыт в новых областях, много многоразового кода, так что с моими будущими проектами все будет проще. Например, многопользовательская игра :) Я увлекаюсь JavaScript и функциональным программированием, в частности, и планирую и дальше совершенствовать свои навыки в Node.js и React.
Спасибо за чтение, надеюсь, вам понравилось и вдохновило;) Если у вас есть вопросы, не стесняйтесь спрашивать!