Chulakov Dev – Telegram
Chulakov Dev
1.15K subscribers
140 photos
5 videos
205 links
Канал команды разработки Студии Олега Чулакова.

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

Обсудить проект @YuraAndreev
Download Telegram
Все по-старому

В прошлой заметке мы говорили про публикацию ссылок в соцсетях и про то, что VK и Facebook получают метаданные страницы, посылая на нее запрос и анализируя HTML-код.

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

Если вы обновили og:image или другие поля, то, для того чтобы пользователи начали ими делиться, нужно сбросить кэш для страницы. Для этого можно использовать специальные инструменты или методы API:
https://developers.facebook.com/tools/debug
https://vk.com/dev/pages.clearCache
Это была ошибка!

Если вы собираетесь использовать React 16, советуем обратить внимание на новую политику обработки ошибок рендера.

В 15ой версии ошибка мешала перерендериваться компоненту и всему поддереву, но оставляло его последнее состояние:
https://codepen.io/OlegChulakovStudio/pen/BYYjya

В 16ом релизе команда разработчиков приняла решение не оставлять компонент в дереве рендеринга и, более того, исключать все вышестоящие компоненты из него, пока не будет встречен компонент с новым методом жизненного цикла componentDidCatch (в 15ой версии он назывался handle_unstableError).

Таким образом, отсутствие компонентов-обработчиков теперь может привести к полному размонтированию дерева компонетов:
https://codepen.io/OlegChulakovStudio/pen/yvveyg

Мы подготовили демонстрацию применения такого компонента-обработчика (ErrorBoundary), который умеет подменять сломанный компонент другим, подготовленным заранее.
Опять то же самое?

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

Например, если вы делаете какой-нибудь посещаемый блог, главная страница которого содержит список из 50 публикаций с числом просмотров и комментариев каждой, то запросы к БД могут сильно нагрузить сервер, а рост числа посетителей может привести к увеличению времени загрузки сайта.

Один из самых простых в настройке способов серверного кэширования — nginx proxy cache:
https://bitbucket.org/snippets/OlegChulakovStudio/ae8gbz

Когда веб-приложение сгенерирует страницу, nginx сохранит результат в указанной ему папке. Последующие запросы на этот же адрес не дойдут до приложения: пользователю будет передан сохраненный в кэше файл. За счет этого нагрузка на сервер может многократно снизиться.
Балансировка

Nginx удобно использовать и для другого типа оптимизации — распределения нагрузки между несколькими зеркалами веб-приложения, которые могут находиться на разных серверах.

Настроить load balancer, который будет равномерно распределять запросы, очень просто:
https://bitbucket.org/snippets/OlegChulakovStudio/7eg8eG
Порталы в React

В некоторых случаях приходится использовать сторонние плагины, создающие разметку собственными методами. Нетривиальной задачей становится попытка вставить в эту разметку интерактивные элементы, описанные в рамках React-экосистемы проекта.

Ранее подобную проблему решали с помощью компонента-обертки, где сам рендер необходимого компонента осуществлялся не в методе render, а в componentDidUpdate с помощью функции ReactDOM.unstable_renderComponentIntoSubtree().

В новой версии появился метод createPortal объекта ReactDOM, который позволяет отрендерить React-компонент в DOM-дереве, о котором React ничего не знает. Для этого ему надо передать первым аргументом сам компонент, а вторым — ссылку на нужный DOM-узел.

Мы подготовили интерактивный пример использования этого метода. В примере рассматривается случай с интерфейсом плеера Video.js, в панель которого мы добавили компонент Likes.
Полезные команды Git. Удаление из индекса

Если вы случайно закоммитили файл, который не должен был попасть в индекс репозитория (например, конфигурационный файл или лог), добавление его в .gitignore уже не поможет. Все будущие изменения этого файла будут фиксироваться Git-ом.

Чтобы убрать файл из индекса, не удаляя его из директории, можно использовать следующую команду:
git rm --cached path-to/file.txt
Полезные команды Git. Перенос коммита

Если вы сделали коммит не в той ветке, вы можете легко скопировать его в нужную, используя команду:
git cherry-pick <хэш коммита>

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

Если вы внесли изменения в файлы, а теперь хотите вернуть их в изначальное состояние, можно воспользоваться командой:
git reset --hard HEAD
Полезные команды Git. Откат коммита

Если вы сделали коммит, но забыли внести в него некоторые файлы, вы можете отменить коммит, сохранив все ваши изменения на диске:
git reset --soft HEAD~1

Чтобы удалить последний коммит вместе с изменениями в файлах, вы можете воспользоваться командой:
git reset --hard HEAD~1

Вы также можете откатить несколько последних коммитов. К примеру:
git reset --hard HEAD~3
Полезные команды Git. Revert

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

Если команда разработчиков большая, можно воспользоваться командой git revert. Это команда делает новый коммит, в котором отменяет все изменения из указанного:
git revert <хэш коммита>
Плотность пикселей в JavaScript

При разработке веб-приложения или сайта может быть необходимо учесть плотность пикселей на экране устройства пользователя. Например, для четкого отображения контента в теге canvas необходимо создавать холст, содержащий большее число точек, а затем с помощью CSS уменьшать визуальный размер этого холста обратно:
https://codepen.io/OlegChulakovStudio/pen/BrKWYE?editors=0110

Самый простой способ узнать плотность пикселей в современных браузерах — обратиться к свойству devicePixelRatio объекта window.
Retina + CSS

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

Для этого можно использовать следующий медиа-запрос:
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)

Пример использования:
https://bitbucket.org/snippets/OlegChulakovStudio/7egg9R

Если в рамках проекта требуется максимально высокая кроссбраузерность, можно воспользоваться расширенной версией медиа-запроса:
https://bitbucket.org/snippets/OlegChulakovStudio/zeaaBK
Retina + CSS-препроцессоры

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

Эти проблемы легко решить, используя возможности любого из современных CSS-препроцессоров:
https://bitbucket.org/snippets/OlegChulakovStudio/yeGxpp

Аналогично можно поступить и с любым другим более распространенным медиа-запросом, вроде (max-width: 1024px).
​​Кубическая кривая Безье и CSS

Специалисты, которые работают с анимацией, знают про easeOutCubic, easeInOutExpo, easeOutBack и другие основные функции плавности.

Те, кто копнул в принципы работы этих функцией знают, что они реализуют поведение, соответствующее различным кубическим кривым Безье.

Эта кривая строится на основе четырех точек:
P0 и P3 — начало и конец кривой;
P1 и P2 — указывают ее направление.

В CSS-реализации можно изменять только точки P1 и P2. Координаты P0 здесь всегда равны «0, 0», а P3 — «1, 1».

Кубические кривые Безье можно использовать в свойствах transition-timing-function и animation-timing-function, чтобы настроить зависимость между временем и прогрессом выполнения анимации:
transition-timing-function: cubic-bezier(x1, y1, x2, y2)
​​Кубическая кривая Безье и SVG

Использовать кубическую кривую Безье можно и в SVG. Например, если нужно быстро нарисовать в интерфейсе какой-нибудь график или простую иконку.

Создать такую линию можно с помощью команды C, в которую нужно передать координаты точек P1, P2 и P3:
<path d="M x0, y0 C x1, y1, x2, y2, x3, y3" />

Пример использования:
codepen.io/OlegChulakovStudio/pen/zWLQYL
Кубическая кривая Безье и canvas

Аналогично можно нарисовать такую линию и в canvas. Для этого нужно воспользоваться функцией bezierCurveTo, которая доступна в рамках 2D-контекста:
context.bezierCurveTo(x1, y1, x2, y2, x3, y3)

Пример использования:
codepen.io/OlegChulakovStudio/pen/pLqOXz

О других возможностях 2D-контекста canvas можно узнать из нашей интерактивной презентации.
Базовые принципы защиты

В этой заметке мы рассмотрим базовые принципы защиты, которые помогут избежать серьезных проблем с безопасностью на вашем сайте. К потенциальным уязвимостям относятся SQL-инъекции и XSS-атаки.

Принцип №1: проверка корректности ввода обязательно должна осуществляться и в backend-части web-приложения. Часто разработчик допускает очевидную ошибку, оставляя валидацию вводимых данных только на стороне браузера. В современных фреймворках такого рода проверка и фильтрация обеспечиваются на уровне модели данных или на уровне middleware-сервисов. Так, например, Yii2 Framework поддерживает множество стандартных валидаторов, а также позволяет реализовывать кастомные механизмы проверки данных.

Принцип №2: работа с SQL-запросами в БД должна производиться с подготовленными на предыдущем этапе данными. Любые входные данные для любого SQL-предложения должны быть типизированы на уровне PDO-типов, а их вставка в SQL должна производиться с помощью переменных привязки.

Принцип №3: препроцессинг вывода. При выводе данных в HTML необходимо также обрабатывать данные. Если вы выводите plain-текст, то необходимо использовать функцию языка htmlspecialchars, а если вы выводите html, например, введенный пользователем через визуальный редактор, то необходимо использовть более сложный механизм обработки выходных данных. Например, HTML Purifier. К счастью, современные фреймворки также включают в себя хелперы и компоненты для этого. Например, Yii2 содержит метод encode в хелпере Html-detail) для вывода plain-text. Для вывода html в Yii2 реализован хелпер yii\helpers\HtmlPurifier, который достаточно легко настраивается под нужды разработчика.
Yii2 FileStorage

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

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

Другим примером служит разграничение уровня доступа к файлам по ролям пользователей в системе или определенным бизнес-правилам. Здесь необходима интеграция с системой управления привилегиями пользователей, используемой в web-приложении.

Для фреймворка Yii2 мы разработали компонент FileStorage, который реализует большинство необходимых задач:
1) загрузку файлов из различных источников (например, из POST-запроса или по URL-адресу);
2) централизованное хранение оригинальных и измененных файлов с привязкой к объектам моделей данных;
3) получение расширенной информации о загружаемом или загруженном ранее файле;
4) API для добавления, получения и удаления файлов с автоматизацией очистки кэша модификаций;
5) разграничение доступа к загруженным файлам на основе взаимодействия с системой аутентификации Yii2;
6) основные операции над изображениями: различные методы ресайза, наложение водяных знаков, генерация thumbnail-изображений и т.д.

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

В прошлой заметке мы рассказали о нашем компоненте Yii2 FileStorage.

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

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

Для файлов изображений доступны два базовых слушателя:
1) ImageManager — производит изменение оригинального файла изображения, при этом оригинал изображения не сохраняется. Действует как фильтр: какое бы изображение ни загрузил пользователь, оно будет приведено к нужному формату;
2) ThumbsManager — генератор превью для загружаемого изображения с удобными конфигурационными настройками.

Основными источниками событий являются загрузчики файлов. Они легко расширяемы и позволяют загружать файлы из различных источников. Например, из архива, удаленного сервера по прямой ссылке или BLOB-значения БД.

Мы реализовали три базовых источника:
1) UploadedFile — реализует получение файла при загрузке формы методом POST;
2) RemoteUplodedFile — получение файла по прямой ссылке;
3) LocalUploadedFile — получение файла из локальных ресурсов сервера.
Вращение в canvas

В 2D-контексте canvas есть функция rotate, работа которой ставит в тупик многих, кто пытается ей воспользоваться. Объекты, отрисованные после вызова этой функции, поворачиваются на указанный в ней угол. Однако есть одна сложность: вращение выполняется не относительно центра объекта, как в CSS, а относительно начала координат всего холста.

То есть, если отрисовать прямоугольник в центре холста, то опорной точкой вращения будет верхний левый угол всего canvas-а.

Чтобы выполнить вращение вокруг нужной точки, нужно сместить к ней начало координат с помощью функции translate и разместить новый объект с соответствующим сдвигом:
context.translate(originX, originY);
context.rotate(angle);
context.fillRect(x - originX, y - originY, width, height);


Пример с вращением прямоугольника относительно его центра:
codepen.io/OlegChulakovStudio/pen/NMxMzv
Channel name was changed to «Chulakov Dev»