<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Nikolay Ivanushkin</title><generator>teletype.in</generator><description><![CDATA[CTO of Teletype]]></description><image><url>https://teletype.in/files/be/bec30fa9-8338-4790-bc49-be1f1be49768.jpg</url><title>Nikolay Ivanushkin</title><link>https://blog.nick-iv.me/</link></image><link>https://blog.nick-iv.me/?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=nick-iv</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/nick-iv?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/nick-iv?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Tue, 07 Apr 2026 10:03:30 GMT</pubDate><lastBuildDate>Tue, 07 Apr 2026 10:03:30 GMT</lastBuildDate><item><guid isPermaLink="true">https://blog.nick-iv.me/HJWmIxraZ</guid><link>https://blog.nick-iv.me/HJWmIxraZ?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=nick-iv</link><comments>https://blog.nick-iv.me/HJWmIxraZ?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=nick-iv#comments</comments><dc:creator>nick-iv</dc:creator><title>Работа с изображениями в Teletype</title><pubDate>Wed, 29 Jan 2020 09:20:00 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/1b/1b3b2ec6-065c-4bde-9922-336a55468a7d.jpg"></media:content><category>Teletype</category><description><![CDATA[<img src="https://teletype.in/files/1b/1b3b2ec6-065c-4bde-9922-336a55468a7d.jpg"></img>Недавно Телетайп получил большое обновление. Мы переработали дизайн, добавили приятных фишек, вроде выключения ката, скрытия участников блога, цветовых схем и всякого look and feel. Внутри тоже произошли некоторые интересные изменения.]]></description><content:encoded><![CDATA[
  <p id="lrTD">Недавно Телетайп получил большое обновление. Мы переработали дизайн, добавили приятных фишек, вроде выключения ката, скрытия участников блога, цветовых схем и всякого look and feel. Внутри тоже произошли некоторые интересные изменения.</p>
  <p id="H9zF">Мне кажется, некоторые решения достаточно очевидны, но возможно не всем. Этой статьей я открываю небольшой цикл статей о технологиях и решениях, которые мы используем в Телетайпе.</p>
  <h2 id="DjqE">Вводные данные</h2>
  <p id="OnvF">Телетайп работает целиком на Node.js, и использует базу данных PostgreSQL. Все сервисы (кроме БД) мы оборачиваем в Docker-контейнеры, и балансируем через nginx. При этом сервисы общаются через Docker Network.</p>
  <h2 id="bMul">Генерируем картинки для шаринга в социальных сетях</h2>
  <p id="Ogy5">Телетайп поддерживает формат Open Graph. Нам очень хотелось, чтобы для каждой статьи и страницы блога генерировались красивые картинки для шаринга.</p>
  <figure id="KM5d" class="m_custom">
    <img src="https://teletype.in/files/1b/1b3b2ec6-065c-4bde-9922-336a55468a7d.jpg" width="375" />
  </figure>
  <p id="2n6h">Поскольку мы используем JavaScript, нам нет никаких проблем сделать такие картинки обычной HTML версткой. Всё что нам нужно, просто отрендерить на стороне сервера и сохранить картинку в PNG. Это очень упрощает жизнь, т.к. нет проблем сверстать это. А рендерингом занять <a href="https://phantomjs.org/" target="_blank">PhantomJS</a>.</p>
  <p id="rYvs">Весь сервис работы с картинками был вынесен из главного бекенда. По этому, когда статья обновляется, для нее на основном бекенде генерируется HTML, и отправляется на рендеринг в сервис работы с картинками. В ответ мы получаем уже адрес сохраненной картинки. Всё что нам нужно — просто обновить его в базе.</p>
  <h2 id="c8Mg">Загружаем картинки</h2>
  <p id="Z7NV">Телетайп поддерживает загрузку картинок до 5Мб. Если вы не злобный хакер, и не будете пытаться слать напрямую картинки через API, то картинки большего размера отсечет еще клиентское приложение, и время а отправку в сеть не будет потрачено. Но даже 5Мб могут серьезно нагрузить основной бекенд. По этому сервис работы с тяжелыми файлами был вынесен в дополнительный бекенд сервис. И теперь если кто-то грузит картинку, то на читающих статьи пользователях это никак не скажется.</p>
  <p id="sRzG"><strong>Что можно бы еще оптимизировать?</strong></p>
  <p id="h672">Во первых мы не удаляем картинки с сервера. Это сложно, не полезно для дисков, и медленно для редактора. Удобно же при редактировании поста просто удалить картинку, и не ждать, когда она удалиться.</p>
  <p id="kvmn">Во вторых, вполне нормальный пользовательский кейс, когда вы добавили картинку в статью, удалили, передумали и снова добавили. Значит мы загрузим две одинаковые картинки? Бесплатно? Ну нет.</p>
  <p id="Lgha">Можно генерировать хеш-сумму. Например SHA1. Просто храним ее для каждой сохраненной картинки, аватарки пользователя и картинки для шаринга в соцсетях. Есть небольшой нюанс. SHA1 считается уже слабым алгоритмом. Есть <a href="https://shattered.it/" target="_blank">вероятность коллизии</a>. Никому не захочется загрузить одну картинку, а получить чью-то чужую.</p>
  <p id="W2Ga">По этому, для картинки мы генерируем 2 хеш-суммы — SHA1 и SHA256. Это очень сильно про запас, но накладные расходы по сравнению с сохранением картинки на диск минимальны.</p>
  <p id="wrqm">Теперь перед загрузкой картинки, мы просто на клиенте берем 2 хеш-суммы, и делаем проверку одним запросом. Если такая картинка уже загружена — сервер вернет нам ее адрес. Все картинки обезличиваются, и сохраняются с UUID в имени: <code>https://teletype.in/files/be/bec30fa9-8338-4790-bc49-be1f1be49768.jpg</code>, как-то так. На всякий случай, при загрузке картинки, сервер сам сверит хеш-суммы с имеющимися в базе. Хранящиеся хеши в таблицах базы могут должны быть уникальными.</p>
  <h2 id="zoFQ">Обрабатываем картинки</h2>
  <p id="K2Jx">Не так давно, нам пожаловался пользователь. Он загрузил фотографии с телефона в статью, а они неправильно повернулись.</p>
  <p id="dFmz">Всё дело в EXIF. Изначально картинка повернута как попало, а правильная ориентация выставляется из EXIF данных с параметром <em>orientation</em>. Всего типов ориентации картинки может быть 8.</p>
  <p id="TYiO">Итого, нужно было повернуть картинку. Вырезать весь EXIF (и сэкономить немного памяти дискам), ну и в случае с аватарками привести их к нужным нам размерам.</p>
  <p id="flwh">Всё это можно было сделать с помощью ImageMagic. Но поскольку один из разработчиков Телетайпа большой любитель JS, да и человеко-понятность ImageMagic убывающе мала, мы нашли модуль для Node.js – <a href="https://www.npmjs.com/package/lwip" target="_blank">lwip</a>. Он умеет вполне достаточно: повернуть картинку, зеркально отразить, обрезать, поменять размеры, и сохранить всё с минимальным набором параметров. За одно, при сохранении добавили дополнительную оптимизацию картинок (85% качества для JPEG мало кто заметит, ведь да?).</p>
  <h2 id="KPSm">В следующих сериях</h2>
  <ol id="uiM9">
    <li id="drVK"><strong>Работа с изображениями</strong></li>
    <li id="aTin">Домены блогов. Как работает привязка</li>
    <li id="CzFv">Домены блогов. Как работают домены</li>
    <li id="mfN6">Домены блогов. Как работает HTTPS для доменов</li>
    <li id="gHbh">Изоморфный Телетайп без React и Virtual DOM</li>
    <li id="oQF1">Проблемы визуальных редакторов текста</li>
  </ol>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.nick-iv.me/SyKefU69x</guid><link>https://blog.nick-iv.me/SyKefU69x?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=nick-iv</link><comments>https://blog.nick-iv.me/SyKefU69x?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=nick-iv#comments</comments><dc:creator>nick-iv</dc:creator><title>Firefox 52 поддержал CSS Grid Layout</title><pubDate>Wed, 29 Jan 2020 09:19:48 GMT</pubDate><category>Development</category><description><![CDATA[Новый Firefox 52 вышедший 7 марта поддержал CSS Grid Layout. До этого поддержка была только у Internet Explorer и Edge, и то с префиксами и по драфтовой спецификации (кто их просил делать по драфту, привет Flex Box).]]></description><content:encoded><![CDATA[
  <figure class="m_column">
    <iframe src="https://codepen.io/nim579/embed/VVpWdo?default-tab=result"></iframe>
  </figure>
  <p>Новый Firefox 52 вышедший 7 марта поддержал <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout" target="_blank">CSS Grid Layout</a>. До этого поддержка была только у Internet Explorer и Edge, и то с префиксами и по драфтовой спецификации (кто их просил делать по драфту, привет <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout" target="_blank">Flex Box</a>).</p>
  <p>Возможно это будет одна из самых революционных фич за последнее время. Сеточки очень сильно облегчат жизнь, и дадут новый повод верстальщикам заставлять дизайнеров следовать сеткам. Кроме того, <a href="https://getbootstrap.com/" target="_blank">Bootstrap</a> тоже сможет избавиться от костылей вроде <code>clear: both;</code>.</p>
  <p>Теперь осталось дождаться только Хром (думаю уже скоро), и Сафари (вот тут неизвестно когда). Кроме того, поддержка пока не заявлена мобильными браузерами. Но никто не запрещает делать фолбеки, к тому же для мобильных браузеров самое милое дело.</p>
  <hr />
  <p>В общем, ура! Ждем пол-года и внедряем 🤗🎉</p>

]]></content:encoded></item></channel></rss>