Расширяй и властвуй вместе с Pug 🐶
#frontend #js
В Студии мы постоянно стремимся оптимизировать работу, применяя различные инструменты разработки. С недавних пор мы внедрили в корпоративные сборки для статической верстки шаблонизатор Pug.
Его основное преимущество — поддержка использования JavaScript прямо в синтаксисе шаблонов. Можно применять большое количество языковых конструкций, например переменные, классы или функции. Есть возможность делать код более модульным, разделяя его на компоненты — шаблоны и миксины.
Более того, стандартный функционал pug-шаблонов можно самостоятельно расширять. И далее мы расскажем как.
Например, нам очень хочется использовать npm-пакет classname в наших шаблонах. Реализуем его поддержку.
Поскольку Pug компилируется с помощью JavaScript в HTML, мы можем добавить необходимый функционал на этапе сборки проекта, а затем использовать его в шаблонах.
В нашем примере для автоматизации процесса расширения функционала будем использовать таск-менеджер Gulp. Для начала необходимо установить пакет gulp-pug и сконфигурировать его, как описано в документации. Затем с помощью опции locals плагина gulp-pug необходимо определить импортируемые js-переменные или функции, в нашем случае функцию cn. В шаблоне мы сможем вызывать ее из глобального контекста:
Пример gulp-задачи, реализующей описанное выше расширение функционала шаблонов, можно посмотреть здесь.
#frontend #js
В Студии мы постоянно стремимся оптимизировать работу, применяя различные инструменты разработки. С недавних пор мы внедрили в корпоративные сборки для статической верстки шаблонизатор Pug.
Его основное преимущество — поддержка использования JavaScript прямо в синтаксисе шаблонов. Можно применять большое количество языковых конструкций, например переменные, классы или функции. Есть возможность делать код более модульным, разделяя его на компоненты — шаблоны и миксины.
Более того, стандартный функционал pug-шаблонов можно самостоятельно расширять. И далее мы расскажем как.
Например, нам очень хочется использовать npm-пакет classname в наших шаблонах. Реализуем его поддержку.
Поскольку Pug компилируется с помощью JavaScript в HTML, мы можем добавить необходимый функционал на этапе сборки проекта, а затем использовать его в шаблонах.
В нашем примере для автоматизации процесса расширения функционала будем использовать таск-менеджер Gulp. Для начала необходимо установить пакет gulp-pug и сконфигурировать его, как описано в документации. Затем с помощью опции locals плагина gulp-pug необходимо определить импортируемые js-переменные или функции, в нашем случае функцию cn. В шаблоне мы сможем вызывать ее из глобального контекста:
header(class=cn('header', { header_auth: auth }))Пример gulp-задачи, реализующей описанное выше расширение функционала шаблонов, можно посмотреть здесь.
Лучше поздно, чем никогда: две особенности iOS 13
#qa #frontend
С момента официального релиза Apple iOS 13 по статистике «новая» ОС установлена более чем на 70% поддерживаемых устройств. В этой заметке мы расскажем о двух актуальных для веб-разработчиков особенностях системы, которые вы могли не заметить 😎
Теперь сложно найти рубль 😂
Разработчики iOS 13 стали более строго относиться к отсутствующим символам в шрифтах.
Например, пользователи русскоязычного сегмента интернета после обновления заметили исчезновение символа рубля на некоторых сайтах. Вместо него может отображаться непонятный прямоугольник. Всему виной отсутствие соответствующего глифа в используемых на злополучных сайтах шрифтах.
В прежних версиях iOS поиск отсутствующих символов производился по другим установленным в системе шрифтам. И чаще всего пропажа находилась. В связи с чем найденные глифы могли по-разному отображаться на различных устройствах/браузерах, что доставляло боль QA-инженеру и искушенному пользователю 😱 В iOS 13 от такого поведения случайно или намеренно отказались.
Проблему можно решить самостоятельным редактированием шрифта или более просто — указать в css семейство системных шрифтов.
Say my name
Планшетная версия iOS 13 была переименована в iPadOS 13. Это обусловлено желанием Apple продвигать новые iPad как полноценную замену ПК. В связи с этим заголовок User-Agent http-запроса идентифицирует клиентское устройство как MacOS:
В этих условиях отличить iPad от десктопа становится затруднительно, но возможно. Например, так:
В JS-коде именно второе условие, после логического «или», проверяет устройство на наличие iPadOS на борту.
#qa #frontend
С момента официального релиза Apple iOS 13 по статистике «новая» ОС установлена более чем на 70% поддерживаемых устройств. В этой заметке мы расскажем о двух актуальных для веб-разработчиков особенностях системы, которые вы могли не заметить 😎
Теперь сложно найти рубль 😂
Разработчики iOS 13 стали более строго относиться к отсутствующим символам в шрифтах.
Например, пользователи русскоязычного сегмента интернета после обновления заметили исчезновение символа рубля на некоторых сайтах. Вместо него может отображаться непонятный прямоугольник. Всему виной отсутствие соответствующего глифа в используемых на злополучных сайтах шрифтах.
В прежних версиях iOS поиск отсутствующих символов производился по другим установленным в системе шрифтам. И чаще всего пропажа находилась. В связи с чем найденные глифы могли по-разному отображаться на различных устройствах/браузерах, что доставляло боль QA-инженеру и искушенному пользователю 😱 В iOS 13 от такого поведения случайно или намеренно отказались.
Проблему можно решить самостоятельным редактированием шрифта или более просто — указать в css семейство системных шрифтов.
Say my name
Планшетная версия iOS 13 была переименована в iPadOS 13. Это обусловлено желанием Apple продвигать новые iPad как полноценную замену ПК. В связи с этим заголовок User-Agent http-запроса идентифицирует клиентское устройство как MacOS:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15В этих условиях отличить iPad от десктопа становится затруднительно, но возможно. Например, так:
const isAppleTouchDevice =
/(iphone|ipad|ipod)/i.test(navigator.userAgent) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
В JS-коде именно второе условие, после логического «или», проверяет устройство на наличие iPadOS на борту.
Во всем виноваты объекты[?]
#frontend #reactjs
Хуки, без сомнения, можно назвать главной фичей React-библиотеки. Однако из-за перехода от классовых компонентов к функциональным появился ряд подводных камней. Об одном камушке расскажем далее 👇
Распространенной ошибкой при использовании механизма хуков является неоптимальное применение массива зависимостей. Иногда в зависимостях перечисляют объекты, которые могут стать причиной лишних вычислений и ререндера компонентов.
Например, наш код производит сложнейшие вычисления на основе данных, полученных из локального хранилища 😱
Казалось бы, все правильно: есть сложное вычисление, и мы его мемоизируем. Но если объект data обновится, а значения его свойств count и limit не изменятся, то хук useMemo снова выполнится, вместо того чтобы вернуть уже вычисленное значение, которое также не изменилось.
Это связано с тем, что хуки в своих зависимостях используют для сравнения объектов строгое равенство, не сличая при этом значения свойств.
Решить проблему достаточно легко. Можно заставить хук сравнивать только необходимые нам конечные свойства объекта. Вот так. Теперь useMemo будет вычислять новое значение, только если изменятся свойства count или limit.
Добавлять объекты как зависимости хука нужно только при крайней необходимости. В остальных же случаях лучше использовать примитивы. Мы рекомендуем добавить в проект правила для линтера, которые помогут контролировать использование хуков React.
#frontend #reactjs
Хуки, без сомнения, можно назвать главной фичей React-библиотеки. Однако из-за перехода от классовых компонентов к функциональным появился ряд подводных камней. Об одном камушке расскажем далее 👇
Распространенной ошибкой при использовании механизма хуков является неоптимальное применение массива зависимостей. Иногда в зависимостях перечисляют объекты, которые могут стать причиной лишних вычислений и ререндера компонентов.
Например, наш код производит сложнейшие вычисления на основе данных, полученных из локального хранилища 😱
Казалось бы, все правильно: есть сложное вычисление, и мы его мемоизируем. Но если объект data обновится, а значения его свойств count и limit не изменятся, то хук useMemo снова выполнится, вместо того чтобы вернуть уже вычисленное значение, которое также не изменилось.
Это связано с тем, что хуки в своих зависимостях используют для сравнения объектов строгое равенство, не сличая при этом значения свойств.
Решить проблему достаточно легко. Можно заставить хук сравнивать только необходимые нам конечные свойства объекта. Вот так. Теперь useMemo будет вычислять новое значение, только если изменятся свойства count или limit.
Добавлять объекты как зависимости хука нужно только при крайней необходимости. В остальных же случаях лучше использовать примитивы. Мы рекомендуем добавить в проект правила для линтера, которые помогут контролировать использование хуков React.
Автоплей и режим энергосбережения в iOS 🎥
#frontend
Как известно, современные браузеры не позволяют автоматически проигрывать видео в HTML5-теге
Но в Apple iOS пользователей и разработчиков ждет еще один сюрприз, связанный с автопроигрыванием видео. Имя ему — Low Power Mode. При включенном режиме энергосбережения пользователь вместо автоматического проигрывания наблюдает большую серую кнопку Play на видеоблоке. Такой режим включается автоматически при достижении определенного уровня заряда батареи или принудительно, в настройках девайса. Индикатор заряда устройства окрасится в желтый цвет, а все видеоролики на сайтах по умолчанию будут стоять на паузе, даже если не содержат звуковой дорожки.
Обыграть проблему можно с помощью вывода изображения-заглушки поверх плеера, а также скрыв картинку по факту запуска видео, подписавшись на событие
Также можно отрисовать свою собственную кнопку ▶️ или даже реализовать обработку события
На просторах интернета можно найти больше примеров реализации автопроигрывания видео в режиме энергосбережения iOS.
Чтобы ваш клиент и QA-инженеры были довольны на 100%, предусматривайте описанную ситуацию в своем коде, особенно когда видеоролики являются фоновыми для блоков на странице.
#frontend
Как известно, современные браузеры не позволяют автоматически проигрывать видео в HTML5-теге
<video>, если оно содержит звук или тег не имеет атрибута muted. На этот случай есть некоторые исключения.Но в Apple iOS пользователей и разработчиков ждет еще один сюрприз, связанный с автопроигрыванием видео. Имя ему — Low Power Mode. При включенном режиме энергосбережения пользователь вместо автоматического проигрывания наблюдает большую серую кнопку Play на видеоблоке. Такой режим включается автоматически при достижении определенного уровня заряда батареи или принудительно, в настройках девайса. Индикатор заряда устройства окрасится в желтый цвет, а все видеоролики на сайтах по умолчанию будут стоять на паузе, даже если не содержат звуковой дорожки.
Обыграть проблему можно с помощью вывода изображения-заглушки поверх плеера, а также скрыв картинку по факту запуска видео, подписавшись на событие
play. Например, вот так.Также можно отрисовать свою собственную кнопку ▶️ или даже реализовать обработку события
touchstart у элемента body и запускать видео при касании экрана.На просторах интернета можно найти больше примеров реализации автопроигрывания видео в режиме энергосбережения iOS.
Чтобы ваш клиент и QA-инженеры были довольны на 100%, предусматривайте описанную ситуацию в своем коде, особенно когда видеоролики являются фоновыми для блоков на странице.
Темная сторона силы
#frontend #qa
Современных пользователей явно потянуло на темную сторону силы 😎 Их интерес к темным цветовым схемам интерфейсов ОС и приложений резко возрос. В конце 2018 года официальный Dark Mode появился в macOS Mojave, а в 2019 году аналогичные темы вышли и под другие ОС и мобильные платформы.
Темный режим функционирует на системном уровне, заставляя изменять свой облик нативные приложения ОС. Даже если интерфейс программы не поддерживает Dark Mode, часть его элементов может поменять свой цвет принудительно.
К счастью, смена темы не затрагивает контентную часть и внешний облик веб-страниц в браузере. При этом у веб-разработчика посредством медиазапроса prefers-color-scheme есть возможность самостоятельно контролировать стили светлой/темной темы, тем самым адаптируя сайт под предпочтения пользователя.
Увы, это не относится к почтовым клиентам 😭 Каждый из них имеет собственное мнение, что и как нужно поменять в письме, при этом далеко не все из них допускают механизмы контроля со стороны разработчиков. Изменению подвержены цвета шрифтов и фоны элементов.
Изначально белое письмо в темной теме может оказаться серо-черным. В большинстве случаев контент остается читаемым, однако, если в нем присутствуют изображения и иконки (особенно прозрачные), рекомендуем убедиться, что они не сливаются с фоном и текстом.
Более детальную информацию о такой проблеме в письмах можно найти в этой статье. А здесь можно найти краткую инструкцию по управлению темизацией интерфейсов различных ОС.
На какой стороне вы — решать только вам 😂
#frontend #qa
Современных пользователей явно потянуло на темную сторону силы 😎 Их интерес к темным цветовым схемам интерфейсов ОС и приложений резко возрос. В конце 2018 года официальный Dark Mode появился в macOS Mojave, а в 2019 году аналогичные темы вышли и под другие ОС и мобильные платформы.
Темный режим функционирует на системном уровне, заставляя изменять свой облик нативные приложения ОС. Даже если интерфейс программы не поддерживает Dark Mode, часть его элементов может поменять свой цвет принудительно.
К счастью, смена темы не затрагивает контентную часть и внешний облик веб-страниц в браузере. При этом у веб-разработчика посредством медиазапроса prefers-color-scheme есть возможность самостоятельно контролировать стили светлой/темной темы, тем самым адаптируя сайт под предпочтения пользователя.
Увы, это не относится к почтовым клиентам 😭 Каждый из них имеет собственное мнение, что и как нужно поменять в письме, при этом далеко не все из них допускают механизмы контроля со стороны разработчиков. Изменению подвержены цвета шрифтов и фоны элементов.
Изначально белое письмо в темной теме может оказаться серо-черным. В большинстве случаев контент остается читаемым, однако, если в нем присутствуют изображения и иконки (особенно прозрачные), рекомендуем убедиться, что они не сливаются с фоном и текстом.
Более детальную информацию о такой проблеме в письмах можно найти в этой статье. А здесь можно найти краткую инструкцию по управлению темизацией интерфейсов различных ОС.
На какой стороне вы — решать только вам 😂
Язык мой — враг мой 👅
#backend #qa
Все мы привыкли к автоматическому определению геолокации пользователя на сайте. Иногда, помимо региона или города, требуется определять язык интерфейса и отображения контента.
Первое, что приходит в голову, — прибегнуть к определению страны по IP-адресу пользователя и на основании этого подобрать язык. Представим ситуацию, когда китайский турист приехал в Россию. Тогда ему будет присвоен местный IP-адрес, а наш сервис для него установит русский язык по умолчанию. Такого поведения гость страны никак не ожидает.
Для того чтобы более корректно определить предпочитаемый для пользователя язык, существует специальный заголовок, который отправляет практически каждый браузер вместе с http-запросом — Accept-Language. Значениями этого заголовка могут быть: код локали, язык или перечень языков клиента, выстроенных в порядке приоритета. Эти данные браузер определяет на основе региональных настроек ОС пользователя.
Сложность разбора этого заголовка заключается в том, что браузеры могут устанавливать его значение в различном формате или вовсе разрешать любой язык. Не исключено, что малоизвестные браузеры вообще не отправят такой заголовок на сервер.
А с помощью специального механизма в Chrome DevTools можно легко изменять значения заголовка Accept-Language, тем самым тестировать поведение алгоритма его разбора на стороне сервера.
Теперь можно усовершенствовать наш механизм автоопределения языка, например, вот так:
1. Попытка анализа заголовка Accept-Language. В случае успеха — устанавливать соответствующий язык интерфейса по его значению.
2. Анализ IP-адреса клиента. Если не удалось однозначно определить язык по пункту 1, то он устанавливается с учетом принадлежности IP-адреса к стране/региону.
Таким образом, внедряя анализ специализированного заголовка, мы снижаем вероятность ошибочного автоопределения языка клиента в серверной логике нашего приложения.
#backend #qa
Все мы привыкли к автоматическому определению геолокации пользователя на сайте. Иногда, помимо региона или города, требуется определять язык интерфейса и отображения контента.
Первое, что приходит в голову, — прибегнуть к определению страны по IP-адресу пользователя и на основании этого подобрать язык. Представим ситуацию, когда китайский турист приехал в Россию. Тогда ему будет присвоен местный IP-адрес, а наш сервис для него установит русский язык по умолчанию. Такого поведения гость страны никак не ожидает.
Для того чтобы более корректно определить предпочитаемый для пользователя язык, существует специальный заголовок, который отправляет практически каждый браузер вместе с http-запросом — Accept-Language. Значениями этого заголовка могут быть: код локали, язык или перечень языков клиента, выстроенных в порядке приоритета. Эти данные браузер определяет на основе региональных настроек ОС пользователя.
Сложность разбора этого заголовка заключается в том, что браузеры могут устанавливать его значение в различном формате или вовсе разрешать любой язык. Не исключено, что малоизвестные браузеры вообще не отправят такой заголовок на сервер.
А с помощью специального механизма в Chrome DevTools можно легко изменять значения заголовка Accept-Language, тем самым тестировать поведение алгоритма его разбора на стороне сервера.
Теперь можно усовершенствовать наш механизм автоопределения языка, например, вот так:
1. Попытка анализа заголовка Accept-Language. В случае успеха — устанавливать соответствующий язык интерфейса по его значению.
2. Анализ IP-адреса клиента. Если не удалось однозначно определить язык по пункту 1, то он устанавливается с учетом принадлежности IP-адреса к стране/региону.
Таким образом, внедряя анализ специализированного заголовка, мы снижаем вероятность ошибочного автоопределения языка клиента в серверной логике нашего приложения.
Ты не пройдешь 🛑
#frontend #nodejs #express #cors
Веб-продукты, которые мы разрабатываем, часто интегрируются с внешними сервисами посредством RESTful API. В свою очередь, уважающие себя внешние сервисы реализуют CORS.
В этом случае для разработчика затрудняется локальная отладка веб-сервиса, особенно его frontend-части. Запросы типа XMLHttpRequest на внешний удаленный веб-сервер отправляются с localhost или тестовых локальных DNS-имен, что зачастую запрещено CORS-политиками внешних сервисов.
Для решения этой проблемы при разработке сайтов и сервисов мы в Студии используем реализацию простейшего прокси-сервера на node.js для подмены оригинального доменного имени клиента, выполняющего http-запрос.
Для реализации такого прокси-сервера нам потребуются следующие ингредиенты 👨🍳:
🌶 Express Framework
🥕 NPM-пакет http-proxy-middleware
🍆 NPM-пакет CORS
Как реализовать базовую конфигурацию Express, можно посмотреть здесь. Далее с помощью двух middleware-модулей осуществляем проксирование наших запросов с подменой доменного имени и поддержкой CORS.
Пример скрипта можно посмотреть здесь.
Для удобства динамические параметры, которые могут изменяться, выносим в переменные окружения:
Например, запустим наш прокси-сервер командой:
Тогда запрос
Такой лайфхак можно использовать практически в любом проекте, где в процессе разработки требуется выполнять кроссдоменные запросы к внешним сервисам.
#frontend #nodejs #express #cors
Веб-продукты, которые мы разрабатываем, часто интегрируются с внешними сервисами посредством RESTful API. В свою очередь, уважающие себя внешние сервисы реализуют CORS.
В этом случае для разработчика затрудняется локальная отладка веб-сервиса, особенно его frontend-части. Запросы типа XMLHttpRequest на внешний удаленный веб-сервер отправляются с localhost или тестовых локальных DNS-имен, что зачастую запрещено CORS-политиками внешних сервисов.
Для решения этой проблемы при разработке сайтов и сервисов мы в Студии используем реализацию простейшего прокси-сервера на node.js для подмены оригинального доменного имени клиента, выполняющего http-запрос.
Для реализации такого прокси-сервера нам потребуются следующие ингредиенты 👨🍳:
🌶 Express Framework
🥕 NPM-пакет http-proxy-middleware
🍆 NPM-пакет CORS
Как реализовать базовую конфигурацию Express, можно посмотреть здесь. Далее с помощью двух middleware-модулей осуществляем проксирование наших запросов с подменой доменного имени и поддержкой CORS.
Пример скрипта можно посмотреть здесь.
Для удобства динамические параметры, которые могут изменяться, выносим в переменные окружения:
PROXY_PORT — порт, на котором будет запущен express-сервер;TARGET_HOST — целевой хост удаленного сервера, на котором будем проксировать наши запросы.Например, запустим наш прокси-сервер командой:
TARGET_HOST=http://www.example.com node api-proxy.js
Тогда запрос
http://localhost:8088/locations будет проксирован на фактический адрес внешнего сервиса http://www.example.com/locations.Такой лайфхак можно использовать практически в любом проекте, где в процессе разработки требуется выполнять кроссдоменные запросы к внешним сервисам.
Фокусируйся правильно
#frontend #a11y
Полноценная навигация по веб-интерфейсу и его элементам управления возможна не только с помощью мыши. Современные браузеры позволяют перемещать фокус и манипулировать элементами управления веб-страницы в ее контентной области, используя только клавиатуру. Это повышает скорость и качество работы пользователей с ограниченными возможностями или пользователей, работающих со специфическими промышленными интерфейсами.
Обеспечить правильное и понятное поведение перемещения фокуса при нажатии клавиши Tab не сложно — достаточно использовать семантически верные HTML-сущности. Кнопки, ссылки и элементы формы имеют нативную поддержку фокусного состояния.
Но иногда нам необходимо исключить из навигации некоторую контентную часть страницы, нарушающую поведенческие ожидания пользователя по изменению фокуса. Например, модальное окно или выпадающее меню. В случае с этими элементами фокус может не очевидно для пользователя перемещаться в зоне скрытого контента.
Не лучшим решением проблемы является исключение таких элементов или блоков из фокусной цепочки с помощью
В этом случае нам поможет полифил inert, который обеспечит драгоценное 💎 поведение пропуска элемента в большинстве браузеров.
#frontend #a11y
Полноценная навигация по веб-интерфейсу и его элементам управления возможна не только с помощью мыши. Современные браузеры позволяют перемещать фокус и манипулировать элементами управления веб-страницы в ее контентной области, используя только клавиатуру. Это повышает скорость и качество работы пользователей с ограниченными возможностями или пользователей, работающих со специфическими промышленными интерфейсами.
Обеспечить правильное и понятное поведение перемещения фокуса при нажатии клавиши Tab не сложно — достаточно использовать семантически верные HTML-сущности. Кнопки, ссылки и элементы формы имеют нативную поддержку фокусного состояния.
Но иногда нам необходимо исключить из навигации некоторую контентную часть страницы, нарушающую поведенческие ожидания пользователя по изменению фокуса. Например, модальное окно или выпадающее меню. В случае с этими элементами фокус может не очевидно для пользователя перемещаться в зоне скрытого контента.
Не лучшим решением проблемы является исключение таких элементов или блоков из фокусной цепочки с помощью
display: none;. Существует даже специализированный атрибут HTML-элементов inert, позволяющий исключать нужный элемент из цепочки навигации. Но поддержка такого атрибута браузерами, судя по MDN-документации, крайне низка.В этом случае нам поможет полифил inert, который обеспечит драгоценное 💎 поведение пропуска элемента в большинстве браузеров.
Опять про письма и MS Outlook
#frontend #qa
Мы уже рассказывали, как удобно организовать тестирование верстки писем в десктопном приложении MS Outlook. В этой заметке поговорим об особенностях верстки писем для веб-версии знаменитого почтового клиента и его расширенной версии, входящей в состав MS Office 365.
Наличие полноценного веб-движка позволяет корректно отрисовывать сложные письма, выгодно отличая эту версию от ее десктопного собрата. Это один из немногих почтовых веб-клиентов, который поддерживает темную тему, изменяя контент письма при переключении на нее.
Эта особенность, а также повышенные требования к безопасному содержимому веб-контента заставляют веб-версию Outlook достаточно сильно модифицировать верстку писем, добавляя собственные
Перечислим несколько проблем верстки писем для веб-версии почтового клиента компании Microsoft из собственного опыта.
Проблема. Верстка не должна содержать ссылок-пустышек с атрибутом
Решение. Старайтесь всегда подставлять валидные и живые ссылки, даже на этапе отладки письма.
Проблема. При просмотре письма в мобильной версии почтового веб-клиента во все элементы попадает CSS-свойство
Решение. Добавьте стиль
Проблема. В мобильной версии веб-клиента тегу img добавляется стиль
Решение. Определите стиль
К счастью, последние две проблемы в мобильном приложении для устройств iOS и Android мы не встречали, а веб-версию всегда можно открыть в Chrome DevTools и упростить процесс отладки.
#frontend #qa
Мы уже рассказывали, как удобно организовать тестирование верстки писем в десктопном приложении MS Outlook. В этой заметке поговорим об особенностях верстки писем для веб-версии знаменитого почтового клиента и его расширенной версии, входящей в состав MS Office 365.
Наличие полноценного веб-движка позволяет корректно отрисовывать сложные письма, выгодно отличая эту версию от ее десктопного собрата. Это один из немногих почтовых веб-клиентов, который поддерживает темную тему, изменяя контент письма при переключении на нее.
Эта особенность, а также повышенные требования к безопасному содержимому веб-контента заставляют веб-версию Outlook достаточно сильно модифицировать верстку писем, добавляя собственные
!important-стили и удаляя сомнительные элементы.Перечислим несколько проблем верстки писем для веб-версии почтового клиента компании Microsoft из собственного опыта.
Проблема. Верстка не должна содержать ссылок-пустышек с атрибутом
href=#. Из соображений безопасности такие html-элементы будут заменены в DOM-дереве на статические альтернативы (div / span / table). На этапе отладки писем такое поведение может «сломать» верстку и внешний вид письма, например, если наша ссылка была стилизована под кнопку.Решение. Старайтесь всегда подставлять валидные и живые ссылки, даже на этапе отладки письма.
Проблема. При просмотре письма в мобильной версии почтового веб-клиента во все элементы попадает CSS-свойство
box-sizing: border-box. Его наличие может приводить к деформации изображений-иконок и прочих элементов.Решение. Добавьте стиль
box-sizing: content-box у проблемных элементов.Проблема. В мобильной версии веб-клиента тегу img добавляется стиль
max-width: 100%!important. В зависимости от DOM-структуры это может привести к деформации или полному удалению элемента из видимой контентной части письма. Решение. Определите стиль
max-width: <ширина_исходного_изобр.>px!important для элементов img.К счастью, последние две проблемы в мобильном приложении для устройств iOS и Android мы не встречали, а веб-версию всегда можно открыть в Chrome DevTools и упростить процесс отладки.
Опиши свой RESTful — и тебе воздастся 😇
#frontend #backend #restful
При разработке SPA на реактивных фреймворках мы не хотим ждать готовности необходимых RESTful-методов для манипуляции данными из backend-части. Мы хотим максимально распараллелить процессы серверной и клиентской разработки.
Для того чтобы достичь этого, нам необходимо договориться о формате обмена данных между командами backend- и frontend-разработки: payload-данные и их типы, http-заголовки, данные авторизации и кеша. Иными словами, нужно спроектировать и формализовать RESTful API, с которым будет взаимодействовать наше SPA. Для этого мы используем несколько сервисов и инструментов.
Swagger. Этот инструмент может работать в режиме self-hosted и не принуждает к использованию платного Saas. Базируется на собственных спецификациях различных версий, известных как OpenAPI. Спроектированное API можно мокать и тестировать.
Oracle ApiAry. Saas основывается на другом языке описания API — API Blueprint. Сервис позволяет в режиме одного окна описывать методы RESTful API, смотреть документацию по ним и тестировать их работу. Для небольших команд и ограниченного количества проектов, хватает бесплатного тарифа.
Используя такие сервисы, frontend-разработчики могут делать тестовые rest-запросы к замоканным данным, которые имеют четко описанную структуру, приближенную к боевым реалиям. Документирование RESTful API избавляет от эффекта недопонимания между разработчиками, ведь все параметры и данные теперь четко описаны и имеют легенды, а результат ответа имеет проработанные вариации.
#frontend #backend #restful
При разработке SPA на реактивных фреймворках мы не хотим ждать готовности необходимых RESTful-методов для манипуляции данными из backend-части. Мы хотим максимально распараллелить процессы серверной и клиентской разработки.
Для того чтобы достичь этого, нам необходимо договориться о формате обмена данных между командами backend- и frontend-разработки: payload-данные и их типы, http-заголовки, данные авторизации и кеша. Иными словами, нужно спроектировать и формализовать RESTful API, с которым будет взаимодействовать наше SPA. Для этого мы используем несколько сервисов и инструментов.
Swagger. Этот инструмент может работать в режиме self-hosted и не принуждает к использованию платного Saas. Базируется на собственных спецификациях различных версий, известных как OpenAPI. Спроектированное API можно мокать и тестировать.
Oracle ApiAry. Saas основывается на другом языке описания API — API Blueprint. Сервис позволяет в режиме одного окна описывать методы RESTful API, смотреть документацию по ним и тестировать их работу. Для небольших команд и ограниченного количества проектов, хватает бесплатного тарифа.
Используя такие сервисы, frontend-разработчики могут делать тестовые rest-запросы к замоканным данным, которые имеют четко описанную структуру, приближенную к боевым реалиям. Документирование RESTful API избавляет от эффекта недопонимания между разработчиками, ведь все параметры и данные теперь четко описаны и имеют легенды, а результат ответа имеет проработанные вариации.
Документировать или нет — это не вопрос
#frontend #backend
Говорят, что хороший код не требует документации. И мы в это свято верим 😁 Однако наш опыт разработки проектов с длинной линией жизни показывает, что документировать все-таки необходимо, и не только код.
По каждому проекту мы ведем свою базу знаний. Описываем сложности, с которыми столкнулись на этапе проектирования или разработки составных частей проекта. Статистически частые и наиболее общие проблемы, которые мы решаем постоянно, выносятся в общие разделы нашей внутренней wiki-системы. Это помогает не наступать на одни и те же грабли и экономить время производства.
Кстати, описание RESTful API также относится к технологической документации.
Для документирования кода проектов на PHP-фреймворках мы используем phpDocumentor, который способен генерировать интерактивную документацию по специализированной метаразметке структурных единиц кода веб-приложения: модули, классы, поля и методы — все покрывается описательной частью на уровне аннотаций. При необходимости можно даже получать интерактивные аналитические отчеты по покрытию кода тестами с помощью PHPUnit.
Код реактивных приложений на React.js, Vue.js и Angular также поддается документированию. Для этого наши разработчики используют плагин Storybook Addon Notes в связке с инструментом для разработки UI-компонентов Storybook.
Хорошо организованная документация кода снижает время погружения в проект новых разработчиков, облегчает передачу проекта на поддержку и обеспечивает отслеживание хронологии изменений.
Развивать, сопровождать и переиспользовать становится легко и удобно.
#frontend #backend
Говорят, что хороший код не требует документации. И мы в это свято верим 😁 Однако наш опыт разработки проектов с длинной линией жизни показывает, что документировать все-таки необходимо, и не только код.
По каждому проекту мы ведем свою базу знаний. Описываем сложности, с которыми столкнулись на этапе проектирования или разработки составных частей проекта. Статистически частые и наиболее общие проблемы, которые мы решаем постоянно, выносятся в общие разделы нашей внутренней wiki-системы. Это помогает не наступать на одни и те же грабли и экономить время производства.
Кстати, описание RESTful API также относится к технологической документации.
Для документирования кода проектов на PHP-фреймворках мы используем phpDocumentor, который способен генерировать интерактивную документацию по специализированной метаразметке структурных единиц кода веб-приложения: модули, классы, поля и методы — все покрывается описательной частью на уровне аннотаций. При необходимости можно даже получать интерактивные аналитические отчеты по покрытию кода тестами с помощью PHPUnit.
Код реактивных приложений на React.js, Vue.js и Angular также поддается документированию. Для этого наши разработчики используют плагин Storybook Addon Notes в связке с инструментом для разработки UI-компонентов Storybook.
Хорошо организованная документация кода снижает время погружения в проект новых разработчиков, облегчает передачу проекта на поддержку и обеспечивает отслеживание хронологии изменений.
Развивать, сопровождать и переиспользовать становится легко и удобно.
Франц Апачевич Кафка 🤣
#backend #php
Для того чтобы пользователь не ждал завершения тяжелых интеграционных операций, лучше исполнять их в фоновом режиме. Например, отправки email-письма через внешний SMTP-сервер или получения курса валют из системы внутреннего контура банка.
В зависимости от ситуации мы применяем различные механики запуска процессов в фоне, но в большинстве своем они сводятся к организации очередей обработки и к работе с брокерами сообщений.
В простейшем случае очередь сообщений можно организовать на одной таблице в реляционной БД, в которую добавлять записи с действиями для обработки и удалять (помечать выполненными) при завершении этой обработки. Для каждого современного фреймворка существуют расширения или composer-пакеты, реализующие работу с очередями.
Например, для Yii расширение yii2-queue включено в ядро фреймворка. Такие расширения поддерживают современные драйверы очередей, основанные на работе с RDBMS, Redis, RabbitMQ, Beanstalk, Gearman и т.д.
Отходя от фреймворков, рассмотрим, как в простейшем случае организовать работу с еще одним, более продвинутым, распределенным, журналируемым диспетчером сообщений — Apache Kafka.
Для быстрого запуска инфраструктуры, опишем сервисы, необходимые для работы Apache Kafka в docker-compose.yml. Допустим, что контейнер консольного PHP-приложения строится на образе php:7.3-cli-alpine. Тогда для взаимодействия c Apache Kafka нам необходимо дополнить этот образ специальным расширением-клиентом php-rdkafka.
Теперь осталось сделать простейшую реализацию механизма отправки и получения сообщений. В рамках пилотной настройки небольшой простейший сервис обмена сообщениями на основе Apache Kafka готов.
З.Ы. Для обеспечения подсветки синтаксиса в IDE при работе с классами
#backend #php
Для того чтобы пользователь не ждал завершения тяжелых интеграционных операций, лучше исполнять их в фоновом режиме. Например, отправки email-письма через внешний SMTP-сервер или получения курса валют из системы внутреннего контура банка.
В зависимости от ситуации мы применяем различные механики запуска процессов в фоне, но в большинстве своем они сводятся к организации очередей обработки и к работе с брокерами сообщений.
В простейшем случае очередь сообщений можно организовать на одной таблице в реляционной БД, в которую добавлять записи с действиями для обработки и удалять (помечать выполненными) при завершении этой обработки. Для каждого современного фреймворка существуют расширения или composer-пакеты, реализующие работу с очередями.
Например, для Yii расширение yii2-queue включено в ядро фреймворка. Такие расширения поддерживают современные драйверы очередей, основанные на работе с RDBMS, Redis, RabbitMQ, Beanstalk, Gearman и т.д.
Отходя от фреймворков, рассмотрим, как в простейшем случае организовать работу с еще одним, более продвинутым, распределенным, журналируемым диспетчером сообщений — Apache Kafka.
Для быстрого запуска инфраструктуры, опишем сервисы, необходимые для работы Apache Kafka в docker-compose.yml. Допустим, что контейнер консольного PHP-приложения строится на образе php:7.3-cli-alpine. Тогда для взаимодействия c Apache Kafka нам необходимо дополнить этот образ специальным расширением-клиентом php-rdkafka.
Теперь осталось сделать простейшую реализацию механизма отправки и получения сообщений. В рамках пилотной настройки небольшой простейший сервис обмена сообщениями на основе Apache Kafka готов.
З.Ы. Для обеспечения подсветки синтаксиса в IDE при работе с классами
RdKafka можно в зависимости проекта добавить stubs-пакет.Истории, которые мы заслужили 🤓
#frontend #storybook
При разработке сложных продуктовых интерфейсов встает вопрос дальнейшего масштабирования и сопровождения кодовой базы веб-сервиса. Со временем количество UI-компонентов растет, наряду с этим возрастает и порог вхождения в проект — его расширение и отладка затрудняются.
Привести мысли и структуру проекта в порядок поможет Storybook 😇
Этот инструмент для разработки пользовательских интерфейсов позволяет реализовывать отдельные части интерфейса изолированно от основного приложения, что упрощает тестирование и позволяет отладить компонент с различными данными. Для интерактивного взаимодействия с визуальными компонентами Storybook предоставляет специальный веб-интерфейс.
Одной из ключевых особенностей Storybook является то, что его можно использовать практически с любым инструментарием, будь то React.js, Vue.js или Angular.
Также существует множество плагинов, которые расширяют его интерфейс и добавляют дополнительные методы для работы с компонентами. В одной из прошлых заметок мы уже писали о плагине, с помощью которого можно описать документацию к UI-компонентам.
Основными объектами взаимодействия в Storybook являются истории. Именно они связывают среду разработки и компоненты. Чтобы Storybook мог отличить обычные файлы от историй, используется именование с префиксом .stories.js. Это правило, как и любое другое, можно поменять, расширив конфигурацию инструмента.
После создания истории она появляется в пользовательском интерфейсе вместе с отрендеренным состоянием компонента. Файлы .stories.js включают в себя ряд историй, где каждая из них — это рендер-функция, в которой отражается состояние компонента. Хорошим тоном считается, если один файл истории описывает один компонент в различных состояниях.
О том, как внедрить Storybook в свой проект, вы можете узнать из документации, соответствующей вашему стеку.
Жми на 🔥, и мы продолжим публикации о развитии окружения разработки UI-компонентов — от простого взаимодействия до E2E-тестирования 😎
#frontend #storybook
При разработке сложных продуктовых интерфейсов встает вопрос дальнейшего масштабирования и сопровождения кодовой базы веб-сервиса. Со временем количество UI-компонентов растет, наряду с этим возрастает и порог вхождения в проект — его расширение и отладка затрудняются.
Привести мысли и структуру проекта в порядок поможет Storybook 😇
Этот инструмент для разработки пользовательских интерфейсов позволяет реализовывать отдельные части интерфейса изолированно от основного приложения, что упрощает тестирование и позволяет отладить компонент с различными данными. Для интерактивного взаимодействия с визуальными компонентами Storybook предоставляет специальный веб-интерфейс.
Одной из ключевых особенностей Storybook является то, что его можно использовать практически с любым инструментарием, будь то React.js, Vue.js или Angular.
Также существует множество плагинов, которые расширяют его интерфейс и добавляют дополнительные методы для работы с компонентами. В одной из прошлых заметок мы уже писали о плагине, с помощью которого можно описать документацию к UI-компонентам.
Основными объектами взаимодействия в Storybook являются истории. Именно они связывают среду разработки и компоненты. Чтобы Storybook мог отличить обычные файлы от историй, используется именование с префиксом .stories.js. Это правило, как и любое другое, можно поменять, расширив конфигурацию инструмента.
После создания истории она появляется в пользовательском интерфейсе вместе с отрендеренным состоянием компонента. Файлы .stories.js включают в себя ряд историй, где каждая из них — это рендер-функция, в которой отражается состояние компонента. Хорошим тоном считается, если один файл истории описывает один компонент в различных состояниях.
О том, как внедрить Storybook в свой проект, вы можете узнать из документации, соответствующей вашему стеку.
Жми на 🔥, и мы продолжим публикации о развитии окружения разработки UI-компонентов — от простого взаимодействия до E2E-тестирования 😎
Расширяемая история
#frontend #storybook
В прошлой заметке мы рассказали, зачем нужен инструмент Storybook и как он помогает нам жить 😁 В свои корпоративные шаблоны мы начали внедрять его на основе оригинальной документации с учетом используемого стека. И конечно, встретились с несколькими сложностями.
Например, при внедрении Storybook в сборки React-приложений стало ясно, что некоторые типы импортируемых файлов ему не знакомы. В базовой конфигурации Webpack для Storybook отсутствовали используемые в приложении лоадеры. В нашем случае это были stylus-loader и css-loader с дополнительным набором опций для конфигурации css-modules.
Большинство схожих проблем вам удастся решить путем расширения базовой конфигурации Storybook. За это отвечает специальное поле
Небольшой пример по расширению конфигурации можно посмотреть здесь.
#frontend #storybook
В прошлой заметке мы рассказали, зачем нужен инструмент Storybook и как он помогает нам жить 😁 В свои корпоративные шаблоны мы начали внедрять его на основе оригинальной документации с учетом используемого стека. И конечно, встретились с несколькими сложностями.
Например, при внедрении Storybook в сборки React-приложений стало ясно, что некоторые типы импортируемых файлов ему не знакомы. В базовой конфигурации Webpack для Storybook отсутствовали используемые в приложении лоадеры. В нашем случае это были stylus-loader и css-loader с дополнительным набором опций для конфигурации css-modules.
Большинство схожих проблем вам удастся решить путем расширения базовой конфигурации Storybook. За это отвечает специальное поле
webpackFinal в файле .storybook/main.js. Важно понимать, что мы расширяем, а не полностью заменяем умолчательную webpack-конфигурацию (хотя и такой вариант возможен 😉). Расширение конфигурации описывается функцией, присвоенной полю webpackFinal. В качестве аргументов она принимает конфигурацию webpack по умолчанию и объект с метаинформацией, необходимой для работы Storybook.Небольшой пример по расширению конфигурации можно посмотреть здесь.
⚡️ Быстрый подбор контраста текста в Chromium
#news #frontend #chrome
В новой версии браузерного движка Chromium 86 появилась возможность быстрого подбора цвета текста для повышения его контрастности.
Теперь не придется терять драгоценное время в попытках подобрать нужное сочетание текста и фона по своим ощущениям: DevTools поможет сделать точный выбор.
https://twitter.com/argyleink/status/1296472539175227400?s=19
#news #frontend #chrome
В новой версии браузерного движка Chromium 86 появилась возможность быстрого подбора цвета текста для повышения его контрастности.
Теперь не придется терять драгоценное время в попытках подобрать нужное сочетание текста и фона по своим ощущениям: DevTools поможет сделать точный выбор.
https://twitter.com/argyleink/status/1296472539175227400?s=19
Twitter
Adam Argyle
in Chromium 86 now: 1-click #accessibility color contrast correction for AA and AAA ratios 🎉 Struggle to fix failing contrast ratios? Tired of the guess and check? @ChromeDevTools has your back. Here's a video of me fixing a few pesky ratio's with the new…
Жучки в моей голове 🐛🐞🐜
#backend #debug #php
Мы не раз писали о способах отладки и профилирования frontend-приложений посредством браузера.
А как же отлаживается backend?🤔 Начинающий php-разработчик предпочитает использовать простые конструкции вывода для отладки данных и структур. Например, такое сочетание крайне часто можно встретить в коде джуниор-разработчика:
Лишь бы такая отладка не дошла до прода 😩
Для полноценной отладки и профилирования кода мы используем Xdebug, который поставляется как php-расширение. Современные IDE, например JB PhpStorm, с легкостью интегрируются с этой библиотекой отладки, как в случае с локальным php-интерпретатором, так и в случае если Xdebug установлен в Docker-контейнере. Наши разработчики применяют специально подготовленное Docker-окружение, и поэтому мы используем второй вариант.
Современные php-фреймворки также предоставляют отладочные инструменты уровня приложения. Например, для профилирования SQL-запросов, которые генерирует ORM.
Удобные отладочные панели есть у фреймворков Yii и Laravel. Если вы не используете каркасы, а разрабатываете приложение на разнородных composer-пакетах или на микрофреймворках, то можно применять, например, PHP Debug Bar.
Важно помнить, что любые средства отладки, будь то отдельные php-расширения либо встроенные в ваш фреймворк компоненты и модули, должны быть отключены в промышленном и тестовом окружении. Их работа регрессивно влияет на производительность приложения, а также через отладочную информацию злоумышленник может получить ценные данные. Инструменты отладки и профилирования должны быть доступны только в процессе разработки веб-приложения.
#backend #debug #php
Мы не раз писали о способах отладки и профилирования frontend-приложений посредством браузера.
А как же отлаживается backend?🤔 Начинающий php-разработчик предпочитает использовать простые конструкции вывода для отладки данных и структур. Например, такое сочетание крайне часто можно встретить в коде джуниор-разработчика:
...
var_dump($someVar); // print_r($someVar);
die();
...
Лишь бы такая отладка не дошла до прода 😩
Для полноценной отладки и профилирования кода мы используем Xdebug, который поставляется как php-расширение. Современные IDE, например JB PhpStorm, с легкостью интегрируются с этой библиотекой отладки, как в случае с локальным php-интерпретатором, так и в случае если Xdebug установлен в Docker-контейнере. Наши разработчики применяют специально подготовленное Docker-окружение, и поэтому мы используем второй вариант.
Современные php-фреймворки также предоставляют отладочные инструменты уровня приложения. Например, для профилирования SQL-запросов, которые генерирует ORM.
Удобные отладочные панели есть у фреймворков Yii и Laravel. Если вы не используете каркасы, а разрабатываете приложение на разнородных composer-пакетах или на микрофреймворках, то можно применять, например, PHP Debug Bar.
Важно помнить, что любые средства отладки, будь то отдельные php-расширения либо встроенные в ваш фреймворк компоненты и модули, должны быть отключены в промышленном и тестовом окружении. Их работа регрессивно влияет на производительность приложения, а также через отладочную информацию злоумышленник может получить ценные данные. Инструменты отладки и профилирования должны быть доступны только в процессе разработки веб-приложения.
Быстро и метко про хороший ООП-код
#useful #backend #php
А вы думаете об архитектуре своего кода? Расскажите нам в комментариях.
Полезное видео от core-разработчика Yii Framework.
https://youtu.be/SKwchYgaJN8
#useful #backend #php
А вы думаете об архитектуре своего кода? Расскажите нам в комментариях.
Полезное видео от core-разработчика Yii Framework.
https://youtu.be/SKwchYgaJN8
Полезные обертки для историй 🤓
#frontend #storybook #react
Продолжаем рассказывать про экосистему инструмента Storybook. В предыдущих заметках мы рассказывали про установку и конфигурацию Storybook. Описанных действий будет достаточно, чтобы начать работать с компонентами дизайн-системы, которые не используют данные из React-контекста.
Однако в крупных проектах может быть реализована глубокая вложенность провайдеров контекста, которые необходимы для работы отдельных библиотек или всего UI.
Например, добавление в Storybook компонента, использующего Redux Store, вызовет исключение. Дело в том, что компоненты подписываются на Store с помощью специального провайдера, который располагается в корне проекта. Чаще всего это основной App-компонент. А поскольку Storybook изолирован от основного приложения, то ему ничего не известно и о провайдерах, используемых в этом приложении.
Решение есть! 🎉 Storybook позволяет реализовывать декораторы для «обертки» истории в рендер-функцию, в которой можно описать применение необходимых провайдеров. Декораторы можно использовать как в отдельно взятой истории, так и глобально — для всех описанных сторис.
Подробнее о том, как использовать библиотеку Redux в историях, можно почитать здесь. Ну а гайд по применению Storybook при разработке React-приложений можно найти тут.
#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 #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 #html
Рекомендуем удобный инструмент для проверки совместимости контентных моделей элементов. Теперь не нужно искать и пытаться интерпретировать информацию официальных источников. Все понятно и user-friendly 😎
#frontend #html
Рекомендуем удобный инструмент для проверки совместимости контентных моделей элементов. Теперь не нужно искать и пытаться интерпретировать информацию официальных источников. Все понятно и user-friendly 😎