Chulakov Dev
1.14K subscribers
140 photos
6 videos
206 links
Канал команды разработки Студии Олега Чулакова.

Советы по Frontend- и Backend-разработке web-сервисов, мобильных приложений, статьи и презентации от наших разработчиков, анонсы проектов и многое другое.

Обсудить проект @YuraAndreev
Download Telegram
CDN или нет — вот в чем вопрос
#frontend #react #nextjs

При масштабировании frontend-приложений на фреймворке Next.js нам часто приходится размещать статические файлы сборки на CDN-ресурсах. К таким файлам относятся бандлы JS/CSS и элементы дизайна в виде медиафайлов.

В Next.js предусмотрен стандартный механизм управления адресом хранения статических файлов приложения. Через параметр assetPrefix можно задать префикс, который будет использован при формировании пути к ассетам. Установить значение параметра можно в файле next.config.js.

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

Для тестового окружения переменная среды ASSET_PREFIX в .env-файле будет пустой, а для промышленного — будет содержать URL-адрес CDN-сервиса.

Например, в Stylus можно использовать префиксы при формировании адресов таким образом.

А в компонентах переменная окружения будет доступна из свойства env объекта process.

Пример конфигурации приложения для работы с различными префиксами, в зависимости от текущего окружения, можно посмотреть в сниппете.
Самое время поставить точку
#frontend #debug #react #nodejs

Каждый современный браузер, даже IE, имеет встроенные средства отладки клиентского JavaScript. У Chrome, например, есть инструменты разработчика, которые позволяют расставлять точки останова, выводить отладочную информацию и в режиме реального времени работать с некоторыми объектами js.

У такой отладки есть минусы — вы отлаживаете уже скомпилированный js, например из EcmaScript или TypeScript. Получается, что код пишется на одном языке, а отлаживается — на другом. Иногда удобно сразу исправлять код в момент отладки.

Наши frontend-разработчики используют IDE Visual Studio Code, в которой есть удобные встроенные средства отладки кода 🐞

VS Code позволяет настраивать различные сценарии отладки — можно отлаживать и серверный, и клиентский js.

Для настройки дебагера в VS Code используется файл ./vscode/launch.json. Чтобы мы могли отлаживать браузерный js, понадобится расширение, сопрягающее работу отладчика с браузерами движка Chrome. Для отладки nodejs-кода будем использовать вот это расширение.

Microsoft создала даже сборник рецептов настройки отладчика для различного типа приложений и языков разработки.
Например, для отладки кода на Next.js можно взять за основу вот эту инструкцию (https://github.com/Microsoft/vscode-recipes/tree/master/Next-js) и отлаживать как клиентскую, так и серверную часть вашего приложения. Не забудьте включить source-maps в настройках сборщиков для Dev-режима, чтобы отладчик показывал исходный, а не транспилированный код.

Старайтесь минимизировать использование механизмов псевдоотладки, типа console.log. Отладка в режиме runtime дает вам полностью объективную, живую картину состояния ваших переменных, объектов и текущего хода выполнения. Вы производите отладку внешними средствами, не изменяя свой код, и спите спокойно, не думая о том, что ваши console.log() проявят себя на промышленном сервере или в браузере у конечного пользователя 🙃
Алло, мы ищем таланты!
#job #frontend #react #redux

Если ты уверенный Frontend Developer и не понаслышке знаешь про React.js + Redux, а также работаешь с Next.js, то ты именно тот человек, который нам нужен.

Сегодня мы ищем сразу несколько супергероев:
Middle Frontend Developer в наш московский офис для работы над проектом крупнейшего банка, в офисе клиента (блек-джек, штаб-квартира и daily cash прилагаются);
Middle+ или Senior Frontend Developer в главный ростовский офис для управления командами разработчиков и работой над лучшими проектами страны.

Звони или пиши нам:
+7 863 303-61-91
hr@chulakov.ru
https://vk.com/olegchulakovstudio
https://www.instagram.com/chulakov.ru

Ты нужен нам, а мы — тебе 😎
Что за ссылка такая — ref?
#frontend #react

На собеседованиях мы обычно спрашиваем соискателя, что такое ref в React. Ответ часто таков: «Ref — это ссылка на DOM-узел». Такое определение необратимо устарело с выходом React v16.3.0. Именно в этой версии появилось API для создания объекта ref — React.createRef().

Получение ссылки на DOM-элемент — это всего лишь один из способов использования ref в React API. В более старых версиях React можно встретить методы refs callback для решения данной задачи.

Путаница с рефами стала более очевидной с приходом React Hooks. При изменении состояния функционального компонента может понадобиться не вызывать его повторный рендер. И это задача для рефов!

Например, нам необходимо остановить таймеры, проинициализированные функциями setTimeout или setInterval по клику на кнопку. Использование React.useState() избыточно для решения такой задачи и может ввести в заблуждение других разработчиков.

Из-за большого количества вопросов и issues на GitHub в официальной документации к React Hooks появился подобный вопрос: есть ли что-то вроде переменных экземпляра?https://ru.reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables.

Мы рекомендуем именно такое определение: «ref — это объект, а его изменяемое свойство current может хранить в себе любое значение».
Ошибки быть не должно!
#frontend #react #nextjs

Когда пользователь взаимодействует с веб-ресурсом, помимо ожидаемого результата, он может наблюдать специальные страницы, отображающие нештатные ситуации в виде http-исключений. Разрабатывая сервисы на Next.js, необходимо управлять выводом таких страниц, анализируя ответы от RESTful API. А с учетом технологии SSR обработчик должен уметь изменять Status Code при отдаче страницы с сервера.

Коробочное решение фреймворка позволяет обработать 404 и 500 http-статусы и кастомизировать вывод страниц для них. При этом обработчик не учитывает случай, когда скрипт страницы загружен, а метод API вернул статус >= 400.

Мы решили отказаться от стандартного способа перехвата и обработки http-исключений в пользу собственного хелпера handleResponseStatus.js.

В хелпере мы учли возможность добавления «глобальных» запросов, таких как авторизация, и «параллельных» запросов, например загрузки меню сайта. Эту задачу решает callback-функция requestFunction, которая возвращает Promise.all. В теле колбека можно контролировать последовательность выполнения с помощью async/await, а в Promise.all — добавлять параллельные запросы.

Осталось привести пример использования хелпера в _app.js и поделиться полезными ссылками 👇

NextJS | getInitialProps
NextJS | Custom Error
ReactDOMServer
Полезные обертки для историй 🤓
#frontend #storybook #react

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

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

Например, добавление в Storybook компонента, использующего Redux Store, вызовет исключение. Дело в том, что компоненты подписываются на Store с помощью специального провайдера, который располагается в корне проекта. Чаще всего это основной App-компонент. А поскольку Storybook изолирован от основного приложения, то ему ничего не известно и о провайдерах, используемых в этом приложении.

Решение есть! 🎉 Storybook позволяет реализовывать декораторы для «обертки» истории в рендер-функцию, в которой можно описать применение необходимых провайдеров. Декораторы можно использовать как в отдельно взятой истории, так и глобально — для всех описанных сторис.

Подробнее о том, как использовать библиотеку Redux в историях, можно почитать здесь. Ну а гайд по применению Storybook при разработке React-приложений можно найти тут.
Готовим новые доки 📄
#frontend #storybook #react

С момента выхода этой заметки появилась новая мажорная версия Storybook 6.0, а вместе с ней плагин Notes, который мы использовали для документирования UI, безвозвратно устарел и перестал поддерживаться 👨‍🦳

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

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

После подключения расширения в каждой истории появляется вкладка Docs, которая содержит соответствующую документацию по тому или иному компоненту.
По умолчанию за генерацию документации отвечает DocsPage-компонент. Документация строится на основе метаинформации о текущем сторис.

Для расширения возможностей документирования можно заменить стандартный DocsPage-компонент на кастомный, построенный на нужных нам Dock Blocks. Список доступных блоков c описанием можно найти здесь.

Аддон Docs позволяет использовать MDX-разметку, благодаря чему можно описывать компоненты с помощью Markdown-разметки и JSX для рендеринга их состояния по аналогии с нативным API Storybook. MDX-формат также можно использовать для написания только Markdown-разметки без вывода компонента. В таком случае Canvas будет повторять вкладку Docs. Подробнее о данной фиче можно узнать здесь.

Плагин Docs устроен сложнее своих аналогов, в том числе и устаревшего Notes. При этом обладает большими функциональными возможностями для описания UI-компонентов.
Реактивные формы 🚀
#frontend #react

Работая с библиотекой React, важно отслеживать производительность интерфейса и его компонентов. Самый простой способ оптимизации производительности — уменьшение количества повторных рендерингов компонентов при пользовательском взаимодействии с ними.

Рассмотрим пример простого, но часто достаточно нагруженного компонента — формы ввода данных. Подобный код можно встретить как в туториалах, так и в реальных проектах. Поле, значение, state… — на первый взгляд все так 🤔

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

Именно смена состояния компонента вызывает его дополнительные перерисовки, которые могут являться избыточными. Вместо того чтобы перезаписывать state, используйте ref-ссылку 🥳

После внимательного просмотра нашей формы становится очевидно, что состояние поля ввода input необходимо только перед ее непосредственной отправкой на сервер. Тогда можно получить ссылку на DOM-элемент input и передать его значение в обработчике отправки формы. Пример оптимизированного кода с использованием ref смотрите здесь.

Такой подход в лоб может применяться для простых компонентов. Для более комплексных решений мы рекомендуем рассмотреть библиотеку react-hook-form. Под капотом она использует схожую с нашим примером механику и применяет ref-ссылки для получения доступа к значению поля.
Опять это окружение
#frontend #react #nextjs

Фреймворк Next.js позволяет быстро приступить к разработке интерактивных интерфейсов, выстраивая компонентную архитектуру и обеспечивая бесшовность переходов пользователя внутри SPA-приложения.

Однако его базовой конфигурации не всегда достаточно для решения определенного рода проблем. Именно поэтому мы постоянно дорабатываем свои корпоративные шаблоны приложений, основанные на Next.js.

Недавно при реализации CI/CD-процесса мы столкнулись с проблемой. При сборке проекта с помощью CLI next конкретные значения используемых переменных окружения зашиваются в код финального бандла. И для того чтобы менять значение env-переменных, необходимо пересобирать проект.

Такой подход нас не устроил, так как необходимо было подменять значения переменных окружения при непосредственном запуске Docker-образа в различных средах. Например, для stage- и production-окружения значение переменной API_URL, которое содержит базовый URL для используемого RESTful API, может различаться.

Второй неприятностью стало то, что одноименной переменной в нашем коде на стороне сервера и клиента должны соответствовать значения различных переменных окружения. Например, в коде у нас есть переменная apiUrl, значение которой на клиентской стороне должно браться из переменной окружения CLIENT_API_URL, а на сервере — SERVER_API_URL. Ведь на сервере запрос к API делается внутри сети, а на клиенте — через внешний http-запрос на доменное имя backend-проекта.

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

🧠 Собрав небольшой брейнcторминг, мы нашли выход и написали хелпер, который помог нам справиться с задачами, описанными выше.

Next.js предоставляет интерфейс Runtime Configuration, с помощью которого возможно указать два набора конфигураций в файле: next.config.js — для сервера serverRuntimeConfig, общий — для клиента и сервера publicRuntimeConfig. В полях конфигураций и будут записаны переменные окружения, как это видно из документации.
СберИндекс — статистика, которой нам не хватало.
Часть 1/3: про Frontend

#release #sber #frontend #react #nextjs

Наличие качественных статистических данных — в наше время это не роскошь, а необходимость.

Для экосистемы продуктов Сбера мы разработали статистический и аналитический сервис «СберИндекс». Далее мы расскажем о самых примечательных технологиях, библиотеках и фреймворках, которые были задействованы в этом проекте. И начнем с frontend-части сервиса 😎

При разработке клиентской части мы использовали наши любимые базовые инструменты — фреймворк Next.js и библиотеку Redux, а также ряд полезных библиотек, помогающих решить бизнес-задачи в рамках сервиса:

React Google Charts — библиотека для построения графиков и диаграмм от Google, набор инструментов которой идеально подходит для задач сайта. Именно с помощью этой библиотеки мы реализовали наглядное представление статистических данных в виде графиков различного типа.
React HTML Parser — преобразует HTML-текст в React-компоненты, и, в отличие от своего аналога dangerouslySetInnerHTML, библиотека проводит ряд проверок и оптимизацию невалидной разметки. Через него пропускались тексты, заполненные с помощью WYSIWYG в панели управления сервисом: исследования, описания графиков и разделов и т.д.
React-responsive — библиотека помогает адаптировать сложные элементы интерфейса под любое устройство. Одним из решающих факторов в выборе инструмента стала возможность использования методов библиотеки при SSR. Вместо привычных ширины и высоты окна на сервере библиотека использует User-Agent пользователя.
Anime.js — легковесная, но продвинутая библиотека для реализации js-анимаций. С помощью этой библиотеки выполнены некоторые микровзаимодействия, например, анимация появления попапов.

Продолжение следует! В следующей заметке расскажем об инфраструктуре и backend-части сервиса.

Chulakov Dev
Слоты в React.js
#frontend #react

Современные frontend-библиотеки и фреймворки для работы с UI, будь то React, Angular или Vue.js, решают важную задачу разделения интерфейса на отдельные компоненты. У каждой такой библиотеки свой синтаксис, API и подходы к реализации компонентов.

Работая с различным стеком технологий, специалисты Студии выделили одну полезную особенность в API распределения контента у фреймворков Vue.js и Angular — слоты. Мы решили перенять такой подход для своих React-приложений.

В React-компонентах по умолчанию дочерние элементы можно добавить только в определенное место JSX-разметки.

Такой подход хорош для решения большинства задач, но создает ряд трудностей для компонентов со сложной структурой, дочерние элементы которых должны быть разнесены в различные части JSX-разметки.

Такую задачу мы решаем с помощью API React.Children. Используя методы объекта Children, мы можем легко разделить список дочерних элементов на несколько отдельных групп — слотов. Все, что нужно сделать, — в цикле сопоставить тип дочернего элемента с компонентом, от которого он был создан.

Для наглядной демонстрации мы подготовили небольшой пример, в котором решена задача с разделением свойства children для компонента страницы. В результате было выделено три слота: header, content, footer.