Введение
В данной статье будет рассмотрено возможное решение для разгрузки интерфейсов веб приложений – создание приложения с возможностью выноса части функционала в дополнительные окна, или же просто многооконное приложение.
Основа стека React + Redux.
Предисловие
Встречалось ли вам браузерное приложение с чересчур нагруженным интерфейсом, в котором боковые панели с настройками или данными перекрывают основное окно?
Мне практически нет, но это не значит, что их не существует.
Устроившись на новую работу мне повезло попасть на проект, в котором столкнулся с данной ситуацией. Приложение было наполнено множеством дополнительных панелей с разного рода информацией и кнопками. И всё это было рассчитано на большой экран и эргономично спроектировано, однако видя это на своём более-менее стандартном экране я ощущал дискомфорт.
Естественно, можно было бы забить, ведь заказчик будет пользоваться приложением только на огромных мониторах, но мне всё же ближе система из нескольких обычных мониторов.
Отступление
Скорее всего, на моё видение данного вопроса повлияло то, что я пришёл во фронтенд из инженерной области, где использовал программы с нагруженным интерфейсом, которые удобно разделялись на разные окна. Зачастую в процессе работы одна программа занимала 2 полных монитора.
В результате мысль о разделении веб приложения на несколько окон засела в голове, сопротивлялся я ей совсем не долго и быстро полез изучать данный вопрос. Как и было очевидно никому данный функционал особо не нужен, никто так не делает и описание готового решения я не нашёл. Но подобрав всего пару инструментов достичь цели оказалось легко.
К делу
Решение подбиралось для популярного стека React + Redux.
Потребовалось дополнительно установить React Router и redux state sync
В качестве примера используем написанное в образовательных целях классическое todo. Да, интерфейс явно не перегружен, но показывать на чем-то надо.
Идея максимально простая:
1. Разрабатываем приложение.
2. Осознаем, что есть панель, которая мешает основному контенту и было бы круто дать возможность пользователю вынести её в отдельное окно.
3. С помощью React Router делаем дополнительную страницу, которая содержит тот самый компонент, который мы хотим вынести в отдельное окно. В коде ниже это страница по пути "/settings".
function App() {
const mainState = useTypedSelector(state => state.main);
return (
<ThemeProvider theme={mainState.theme === 'light' ? lightTheme : darkTheme}>
<BrowserRouter>
<Routes>
<Route path="/" element={
<AppContainer>
<TodoContainer>
<Header />
<Main />
<Footer />
</TodoContainer>
</AppContainer>
} />
<Route path="settings" element={
<TodoFooter />
} />
</Routes>
</BrowserRouter>
</ThemeProvider >
);
}
4. Далее делаем кнопку, которая по нажатию открывает новое окно с вынесенным компонентом.
* Приложение с использованием styled‑components, ButtonOpenSettings просто стилизованный button
<ButtonOpenSettings
onClick={() => {
const params = 'scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,width=500,height=60,left=100,top=100';
open('/settings', 'test', params);
}}
>Открыть настройки</ButtonOpenSettings>
5. Для синхронизации состояния redux между вкладками подключаем Middleware readux state sync
https://www.npmjs.com/package/redux-state-sync
6. Вот и всё, теперь у пользователя есть возможность вынести часть функционала приложения в отдельное окно.
Приложение можно посмотреть тут - https://todo-app-liart-rho-37.vercel.app/
Репозиторий - https://github.com/GragertVD/todo-app/tree/master
7. Было бы правильнее ещё добавить состояние открытого окна в state, чтобы скрывать настройки в основном окне, дабы избежать дублирования кнопок и действительно разгрузить интерфейс основного окна, но я оставил так, чтобы лучше наблюдать синхронное изменение состояния.
P.S.
Из явных недостатков хочется отметить то, что я ещё не нашел способ сделать открытое окно браузера постоянно на переднем плане относительно всех остальных окон браузера.
Пишу с осознанием того, что рассмотренный метод достаточно специфичен и мало кому пригодится. Но я верю, что в определенных условиях это может быть прекрасным решением.
Да и просто хотел поделиться интересной идеей. Всем спасибо за внимание.
Комментарии (23)
ImagineTables
24.11.2023 22:15+5Помню сайт во времена позднего IE, который открыл запрашиваемый документ в отдельном окне, а ОС почему-то это окно не вывела на передний план. Я об этом узнал только когда закончил работу и закрыл главное окно браузера, впервые увидев окно с документом — до этого я думал, что сайт просто глючит и игнорирует мои запросы. Стоит ли работать на таком уровне, который ты как разработчик не контролируешь на 100% (браузер/ОС)? (В Windows, например, сложный запутанный API для управления активацией окон). И где нельзя обеспечить хотя бы «мягкую» модальность с закрытием при потере фокуса (всё-таки настройки же).
И, главное, у юзеров нет ожиданий, что за пределами вкладки может быть что-то, относящееся к веб-приложению.
В общем, применять лучше с большой осторожностью.
GragertVD Автор
24.11.2023 22:15Да, согласен со сказанным. Работать с тем, над чем нет контроля это плохая идея, именно поэтому я не полез в поиски того, как можно управлять расположением окон браузера и глубже. Но на уровне просто открыть дополнительное окно вполне всё контролируемо из JS.
А по поводу ожидания пользователей, это да. Для большинства пользователей от этого будет больше вреда. Думая над данным решением я предполагал, что это можно применять для узкого круга пользователей, которые точно готовы к разделению на несколько окон. В моем представлении это либо разработчик, который привык работает в несколько экранов, либо специфичное приложение не для широкой публики с четкой инструкцией об этой части функционала.
sobikon
24.11.2023 22:15С точки зрения фронтенда — это хороший опыт. Спасибо за статью! Ниже напишу небольшое дополнение к твоей статье.
Со стороны как дизайнер, хочу отметить, что в большинстве случаев функционал, вероятно, вызовет кучу проблем для обычного неопытного пользователя. Можно много описать неприятных сценариев, прежде чем пользователь перенесет на другой монитор или немного уменьшит размер основную область перегруженного интерфейса (что тоже не гуд)
И пригоден в большинстве случаев, в местах, где этот паттерн ожидаем. Например, как тут написали в комментариях про чат. Но в первую очередь это важно — не для самих пользователей смотрящих этот самый контент, а для стримеров, не пользующимися сторонними плагинами для вывода чата.
Так что, на самом деле — возможным решением для перегруженных интерфейсов, это проблематично назвать, и на практике не используется в вебе. А вот как дополнительным функционалом — да.Как и было очевидно никому данный функционал особо не нужен, никто так не делает и описание готового решения я не нашёл. Но подобрав всего пару инструментов достичь цели оказалось легко.
Было бы классно для статьи — предположить или описать, почему очевидно функционал оказался не нужным.Из явных недостатков хочется отметить то, что я ещё не нашел способ сделать открытое окно браузера постоянно на переднем плане относительно всех остальных окон браузера.
Я мало взаимодействую с фронтом и изучаю его, но предполагаю что его нет. Если бы этот функционал был, мы бы еще чаще встречались с агрессивной рекламой которая открывается в новых окнах.
GragertVD Автор
24.11.2023 22:15Насчет объяснения того, почему функционал не востребован, действительно не раскрыл в статье. Но ответ достаточно прост, и очень тесно связан как раз с тем, что вы написали в первых абзацах. Обычному пользователю данный функционал будет сильно непривычен и неудобен.
В целом, мне кажется, подавляющее большинство пользователей для просмотра браузера используют только один монитор, что действительно делает для них данных функционал неприменимым, и даже мешающим.
Но есть всё же группа пользователей, которым подойдет данная идея. Она применима к сайтам "для разработчиков", когда пользователь привык работать с несколькими мониторами и не потеряется от этого.
Я говорю про сайты на подобии этого: https://easyeda.com/ru . Наверное, лучший пример, где рассмотренная идея может применяться, множество дополнительных панелей и кнопок + пользователь разработчик, который привык пользоваться несколькими дисплеями.
LinaRSH
24.11.2023 22:15Через localstorage гонять стейт — ну такая себе затея. Работать будет, но медленно. Это сейчас стейт маленький и скорость не влияет на пользовательский опыт, но когда приложение начнет разрастаться не до hello-world и todo-list рыбы, а до настоящего продакшн проекта там и запоет разработчик.
Что будет делать разработчик, когда браузер решит увести неактивное окно в состояние экономии энергии? Это где практически весь мир замирает, а тайматуты троттлят жутко
А самое смешное, что вся статья заключается в идеи «подключить готовую библиотеку»
GragertVD Автор
24.11.2023 22:15Хотел бы отметить, что redux-state-sync под капотом использует Broadcast Channel API. Я не говорю про то, что данное решение супер быстрое и не застраховано от тормозов, к сожалению, тесты я не проводил. Просто хотел прояснить на чем работает и избежать путанности.
У самого же redux-state-sync есть возможность записи в блэклист состояний, которые не должны меняться в разных окнах, что возможно сокращает объем передаваемых данных между окнами до необходимого минимума.
Касаемо ухода неактивного окна в спящий режим, не очень понял проблему. Ушел и ушел, если пользователь им не пользуется пусть и весит в таком состоянии, это не должно никак мешать.
А насчет «подключить готовую библиотеку». Изначально я думал что придется самому писать инструмент для синхронизации изменения состояния между вкладками, в этом и была идея, но да, нашел готовое, которое прекрасно работает и я был рад. А статью решил написать больше не по коду а просто по идеи и возможности делать вот так вот
LinaRSH
24.11.2023 22:15По поводу localstorage я взяла информацию из npm репозитория библиотеки. Если на самом деле используется не localstorage - то это очень хорошо, ибо я лично применяла решения на базе localstorage на реальном проекте и это было фиаско
А по поводу сна я кейс увидела такой: два окна, оба находятся на экране одновременно (как на вашем скриншоте). Оба доступны к просмотру. Но в одном окне основной интерфейс, в другом например таймер (пиццерия считаем минуты до бесплатной доставки). Если окно не активировать, то его содержимое уйдет в троттлинг и таймер начнет считать секунды минутами а то и вовсе встанет. Это не документировано как фича языка, это анонсировано как фича браузеров. И с этим ничего не поделать. А две вкладки в одном окне действительно никому не мешает, даже если одна уснет
GoodOldDude
24.11.2023 22:15+1Решать проблему плохого или неудачного дизайна UI переносом части интерфейса в "плавающие окна" такое себе решение, особенно в веб приложениях. Даже когда пользователь имеет несколько мониторов, расположение инструментов должно быть строго раздельным по функционалу.
К примеру чат или отладчик можно держать отдельно от главного рабочего пространства приложения, но все часто используемые функции должны быть под рукой пользователя.
А в случаи, когда имеется только один монитор, то многооконный интерфейс скорее создаст еще больший дискомфорт, чем решит проблему перегруженности UI.
markelov69
24.11.2023 22:15+1Основа стека React + Redux.
Использовать Redux это уже сразу заведомо провал. Вы пишете статью из 2015 года? Все адекватные люди уже много лет используют в связке с React'ом только MobX.
Kuch
24.11.2023 22:15+2Достаточно токсичное и голословное утверждение. Есть какие-то подтверждающие факты? Особенно меня интересует корреляция с адекватностью.
markelov69
24.11.2023 22:15Вот пожалуйста, всё максимально наглядно - https://codesandbox.io/p/sandbox/adoring-banach-k8m9ss?file=%2Fsrc%2FApp.tsx
И представьте (или напишите) аналогичное поведение с redux'ом и сравните очевидность, наглядность и простоту понимания того что происходит. И сразу поймете почему все адекватные люди давным давно используют MobX.Kuch
24.11.2023 22:15+1К сожалению, это не имеет ничего общего с моим вопросом про статистику и корреляцию
markelov69
24.11.2023 22:15К сожалению, это не имеет ничего общего с моим вопросом про статистику и корреляцию
Ну вот смотрите, на примере IQ, чем люди умнее, тем их меньше, сильно меньше. То же самое и среди разработчиков. Т.е. талантливых разработчиков сильно меньше, прям сильно сильно меньше чем так сказать остальных, рядовых - и это не оспоримый факт. Особенно сейчас, когда в профессию приходит любая мартышка после курсов за деньгами, а не по тому что он предрасположен к этому и обладает соответствующим складом ума, думая что он теперь программист и справится с задачами сложнее чем hello world, захламляют все своими резюме и откликами, и для нормальных разработчиков просто у рекрутеров сил не хватает до скролить. Плюс из-за наплыва таких "разработчиков" работодатели пытаются дэмпинговать зарплаты. По тем же причинам людей которые пишут говнокод сильно больше, чем тех людей, которые пишут внятный, читаемый и понятный код. И тд и т.п.
Вот вам и вся корреляция. Разумеется папуасам и с копьем зашибись охотится, зачем им ружья то.
Ещё раз вам говорю, просто посмотрите на код и вам сразу всё станет понятно, ведь это очевидно и лежит на поверхности. А если вам этого не достаточно(или не понятно), то у меня для вас плохие новости.Kuch
24.11.2023 22:15Все ещё никакой статистики. Я могу так сказать "любой адекватный разработчик уровня синьер и выше не будет писать на mobx". И мое заявление имеет точно такой же вес как и ваше
Cere8ellum
24.11.2023 22:15Почему адекватные используют? А остальные, значит неадекватные? Не хочу холиварить, но сравни количество викли даунлоадс по реакт редаксу и реакт мобэксу. Нехорошо так высказываться....
jodaka
24.11.2023 22:15Количество скачиваний — это аргумент из серии "миллионы мух не могут ошибаться".
ruslan_astratov
24.11.2023 22:15Не удивлюсь, если и в этот тред приползёт один товарищ, который начнёт пихать свой на фиг никому не нужный фреймворк ("очередной убийца Redux, альтернатива MobX")
Kirill-112
24.11.2023 22:15Из явных недостатков хочется отметить то, что я ещё не нашел способ сделать открытое окно браузера постоянно на переднем плане относительно всех остальных окон браузера.
И хорошо. Было бы недостатком браузера - позволять сайту быть поверх всех окон. Браузер должен быть на стороне пользователя, а не на стороне разработчика сайта. И свой браузер я настроил так, чтобы даже всплывающие окна открывать в новой вкладке.
P.S. Я, например, так и не нашёл способ запретить окнам в операционной системе позволять себе всегда быть поверх всех окон.
ri1wing
Открыть чат в новом окне - стандартная функция на любом сайте, где можно смотреть стримы. Ютуб, твич, гудгейм, трово.
Mihaelc
Возможно, там чат связан не с основной страницей фронтенда, а связывается напрямую с бэком.
GragertVD Автор
Интересно, я искал где такое применяют, но про вынос чатов не нашел, спасибо за комментарий.
Я думал больше про приложения другого типа, к примеру: https://easyeda.com/ru.
А про ненужность функционала я действительно переборщил, скорее просто редкость и как следствии мало информации о том, как это сделать.