<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Ихрь постит в уютный бложик: заметки с тегом education</title>
<link>https://ifedyukin.ru/blog/tags/education/</link>
<description>Фрирайтинг, заметки, шитпостинг и все подряд</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.1 (v4098)</generator>

<itunes:subtitle>Фрирайтинг, заметки, шитпостинг и все подряд</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit></itunes:explicit>

<item>
<title>How to sync Obsidian between iOS devices</title>
<guid isPermaLink="false">79</guid>
<link>https://ifedyukin.ru/blog/all/how-to-sync-obsidian-between-ios-devices/</link>
<pubDate>Sun, 15 Oct 2023 19:39:31 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/how-to-sync-obsidian-between-ios-devices/</comments>
<description>
&lt;p&gt;I’ve written a lot of notes since 2010, I really like methodologies like second mind and Zettelkasten, and as a consequence I really like Obsidian.&lt;/p&gt;
&lt;p&gt;And many times I’ve seen people find solutions to synchronize different iOS/iPad OS devices without iCloud and Obsidian Sync. People use Apple Shortcuts and third-party tools like Working Copy to sync Obsidian via git, or use terminal emulators like iSH to mount the vault directory and sync it manually.&lt;/p&gt;
&lt;p&gt;But Obsidian on mobile devices (yes, iOS too) supports community plugins.&lt;br /&gt;
And instead of reinventing the wheel, you can... just install the plugin you need.&lt;/p&gt;
&lt;p&gt;Just go to Settings — Community Plugins — Browse. And install:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;«Obsidian Git» for synchronization with git;&lt;/li&gt;
&lt;li&gt;«Remote Save» to synchronize with S3/WebDav.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yes, it works on iOS devices, it works natively and automatically on startup, you just need to enable it in the settings. And also you can add shortcut to Obsidian menu to call action you need.&lt;br /&gt;
Enjoy!&lt;/p&gt;
</description>
</item>

<item>
<title>Диплом NaN. The end</title>
<guid isPermaLink="false">25</guid>
<link>https://ifedyukin.ru/blog/all/bachelor-work-nan/</link>
<pubDate>Sat, 07 Jul 2018 17:57:04 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/bachelor-work-nan/</comments>
<description>
&lt;p&gt;В общем-то изначально на цикл постов про написание диплома у меня были грандиозные планы (в прочем, как и на сам диплом). Однако, что-то пошло не так, и в один момент мне стало вообще лень писать диплом, не говоря уже про какие-то сопровождающие посты.&lt;/p&gt;
&lt;p&gt;Сейчас же уже прошло около месяца с момента защиты диплома, который я уже отдал в приемную комиссию вместе с заявлением на поступление в магистратуру. К слову, диплом был написан дописан в сжатые сроки, довольно быстро была “собрана” пояснительная записка, а защищено всё это на отлично.&lt;/p&gt;
&lt;p&gt;После всего вот этого взял отпуск на пару недель (жаль, что он почти завершился), провел некоторые мероприятия (воркшопы и лекции), провёл практику у студентов, наигрался в игры и поконтрибьютил во всякие интересные проекты &lt;a href="@WebPurple"&gt;&lt;a href="https://github.com/WebPurple"&gt;https://github.com/WebPurple&lt;/a&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Теперь надо намечать дальнейшие планы, отказываться от привычки играть в игры и изучать всякое новое, в планах есть погрузиться в Vue и PWA, а если брать бэкенд, то чуть глубже пощупать NestJS. Также, вероятно, стоит дочитать кучку начатых книг и, всё-таки, попробовать писать что-то осмысленное и конкретное в блок, но это — как пойдёт.&lt;/p&gt;
&lt;p&gt;На этом можно завершить цикл публикаций про диплом, вернусь к нему через пару лет, когда буду писать магистерскую “диссертацию”.&lt;/p&gt;
</description>
</item>

<item>
<title>Диплом 5. UI, FrontEnd</title>
<guid isPermaLink="false">24</guid>
<link>https://ifedyukin.ru/blog/all/bachelor-work-5/</link>
<pubDate>Sat, 03 Mar 2018 17:55:37 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/bachelor-work-5/</comments>
<description>
&lt;p&gt;Со всякими сложностями, возникшими в начале написания клиентской части разобрались, теперь можно и поверстать.&lt;/p&gt;
&lt;h2&gt;Январь 2018&lt;/h2&gt;
&lt;p&gt;Разумеется, мне лень всё придумывать с нуля, поэтому я пошёл в гугл, затем перешел к  &lt;a href="https://hackernoon.com/the-coolest-react-ui-frameworks-for-your-new-react-app-ad699fffd651"&gt;посту на Hackernoon&lt;/a&gt; с подборкой UI-тулкитов для реакта. Сейчас что-то подберу и начну творить.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Самым популярным оказался &lt;a href="https://github.com/mui-org/material-ui"&gt;Material-UI&lt;/a&gt;, его и возьмём, такой дизайн сейчас вроде модный, так что сойдёт.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Дока у них, конечно, странновата, хотя, может я где-то не там и как-то не так смотрю...&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Попытался обратиться к API, и всё сломалось, оказалось, сначала не к тому эндпоинту обращался, а я уже начал паниковать.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Только сейчас узнал, что `fetch` &lt;b&gt;не&lt;/b&gt; уходит в `catch`, если сервер отдаёт &lt;b&gt;не&lt;/b&gt;, на что потратил где-то полчаса, отыскивая причину возникающих ошибок. Подключил `axios`, не понимаю, почему сразу так не сделал.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Сделал красивую регистрацию с блекджеком и проверками на всякое разное, чтобы юзеру было хорошо. Ну и навигацию доделал, теперь она работает по всему так пока 4 страницы сайту.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Хотел начать с эвентов и их страниц, но всё-таки начну с юзеров, придумал ещё всякие таймлайны, лайф апдейт и всякие фичи, но их я, скорее всего, реализовывать не буду, а просто докину потом в текст диплома и презентацию как «возможные варианты развития».&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;По дизайну всё выходит ну очень не очень, но мне как-то лень что-то нормальное придумывать (да и не умею я в дизайн). От адаптива, вероятно тоже откажусь в итоговой версии, но это не точно.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Видимо, систему загрузки аватаров и подобного нужно будет как-то переписать...&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Сделал редактирование профайлов, загрузку аватара — работает отлично, вот только в коде там всё ужасно, но стадия рефакторинга у меня запланирована на потом. Пока делаю PoC. Теперь бы нужно разобраться с изменением пароля... Вот это самое ужасное в данном случае. Ну, и, конечно, валидность введенных данных надо проверять так же как при регистрации и красиво подсвечивать.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Сделал страничку со всеми юзерами. Сегодня результат вполне неплох. Теперь то же самое нужно для эвентов, но там полей и формочек в разы больше, конечно, а потом уже рефакторить и фичи пилить.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Вчера в `app.use(express.static(’build’))` забыл дописать `/client`, из-за чего у меня файл сервера торчал наружу, фейл на фейле, хорошо, в прод это не пошло :wink:&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;lt;off_topic&amp;gt;&lt;/b&gt;&lt;br /&gt;
Думаю впилить сюда какую-то систему комментариев, однозначно не Disqus, а других вариантов особо и нет. Facebook’ом из моего окружения мало кто пользуется, у Twitter нет виджета комментариев, а ВК я просто не хочу.&lt;/p&gt;
&lt;p&gt;Самый явный вариант — накостылить комментарии на основе Issues на GitHub, только тогда для комментирования нужен будет там аккаунт, но вот как раз это есть у всего моего окружения.&lt;/p&gt;
&lt;p&gt;Идея годная, но с одной стороны, с другой — те, кто хотят что-то обсудить и так пишут мне, например, в Telegram, а обсуждение чего-то, что не относится к репозиторию в его issues — использование не по теме, да и вообще оверинжениринг выйдет какой-то.&lt;br /&gt;
&lt;b&gt;&amp;lt;/off_topic&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Чуть-чуть пофиксил работу сервера и своих Middleware, только защитку от брута надо бы помягче сделать и фильтр доступных эндпоинтов выставить.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Выставил — всё поломалось. Не понимаю, почему, но всё где-то падает.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Кажется, я починил. Но почему оно сломалось, так и не понял.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Пытаюсь запилить изменение пароля, на фронте всё гуд, а вот на бэке, как оказалось, я там просто заглушку оставил...&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Всё поправил, роль сыграл один злополучный `await` и вызов метода.&lt;br /&gt;
&lt;b&gt;#np&lt;/b&gt;&lt;/p&gt;
&lt;script type="text/javascript" src="//vk.com/js/api/openapi.js?152"&gt;&lt;/script&gt;
&lt;!-- VK Widget --&gt;&lt;div id="vk_playlist_-64971419_83568980"&gt;&lt;/div&gt;&lt;script type="text/javascript"&gt;
VK.Widgets.Playlist('vk_playlist_-64971419_83568980', -64971419, 83568980, '04a3638bcfefbce53f');
&lt;/script&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Зачем-то запилил комментарии в блог (сюда), которые работают на основе... GitHub Gists.&lt;br /&gt;
Потестировать можно на посте «&lt;a href="/blog/2017/JScurrying/"&gt;Каррирование в JS&lt;/a&gt;».&lt;br /&gt;
А сейчас — самое время писать часть диплома для работы с сущностями типа «эвент». Ну или подумать над идеей для хакатона.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Хватит лениться, пора запилить добавление эвента.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Отодвинул разработку на «когда-нибудь»...&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;h2&gt;Март 2018&lt;/h2&gt;
&lt;p&gt;Первым делом сделал возможность собрать докер-контейнеры. Теперь всё цивильно: 3 контейнера (nginx, mongodb, nodejs). Контейнер с nginx проксирует запросы на ноду и балансит нагрузку, внутри ноды крутится кластер процессов ноды под pm2. В целом неплохо. На эту тему написал бы отдельный пост, но пока особо времени нет.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://ifedyukin.ru/blog/pictures/d5-docker.jpg" width="1280" height="555" alt="" /&gt;
&lt;/div&gt;
&lt;p class="foot"&gt;Смысла распределять нагрузку nginx’ом пока нет, поэтому с nodejs только один контейнер&lt;/p&gt;
&lt;p&gt;Теперь решил отказаться от Google-Material кита для React и перешёл на &lt;a href="https://ant.design"&gt;Ant Design&lt;/a&gt;. С формами тут всё гораздо лучше, логин и регистрацию накидал довольно быстро.&lt;/p&gt;
&lt;p&gt;Помимо этого развернул всё на сервере нормальном, здорово, когда работодатель способствует развитию и выделяет ресурсы на твои личные проекты.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Окончательно перетащил всё, что было, на новый дизайн. Параллельно несколько багов пофиксил и неплохо переделал логику редактирования профиля и загрузки аватарки.&lt;/p&gt;
</description>
</item>

<item>
<title>Технология блокчейн и её применение</title>
<guid isPermaLink="false">23</guid>
<link>https://ifedyukin.ru/blog/all/blockchain-technology/</link>
<pubDate>Thu, 15 Feb 2018 17:50:43 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/blockchain-technology/</comments>
<description>
&lt;p&gt;С &lt;a href="https://docs.google.com/presentation/d/1wbcZUIZSAzGdZrc3VQKeD9tGfGcAer1GT6RUmS2Yg4U/edit?usp=sharing"&gt;докладом&lt;/a&gt; про блокчейн, его достоинства, недостатки и хайп я выступил на &lt;a href="https://youtu.be/X9se89JEU-A?t=5m25s"&gt;WebPurple Meetup #25&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;На форуме «СТНО-2018» в секции «Информационные системы и защита информации» я выступил с &lt;a href="https://docs.google.com/presentation/d/1teRNiLFsUqp-NJx_QJFjWT-PpatnzWfDLrlunf2rcrg/edit?usp=sharing"&gt;докладом&lt;/a&gt; «Применение технологии блокчейн в области защиты информации и его недостатки».&lt;/p&gt;
&lt;p&gt;Ниже представлена тезисная статья (для научного сборника), которая посвящена самой технологии, базовым принципам работы и возможным способам использования в распределённых вычислениях и информационной безопасности веб-систем.&lt;/p&gt;
&lt;h2&gt;Введение&lt;/h2&gt;
&lt;p&gt;Первая ассоциация с блокчейном — биткоин и другие криптовалюты. Однако, блокчейн, как технология, не обязательно связан с ними и абсолютно от них не зависит.&lt;/p&gt;
&lt;p&gt;Блокчейн — цепочка блоков, представляющая собой связанный список. Его основные концепции: распределенность, одноранговость и защищенность. Распределенный “реестр” хранит историю всех операций между узлами одноранговой сети в виде блоков информации.&lt;/p&gt;
&lt;p&gt;В общем случае каждый блок характеризуется следующими параметрами:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;индекс;&lt;/li&gt;
&lt;li&gt;временная отметка;&lt;/li&gt;
&lt;li&gt;данные;&lt;/li&gt;
&lt;li&gt;хеш текущего блока;&lt;/li&gt;
&lt;li&gt;хеш предыдущего блока.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://ifedyukin.ru/blog/pictures/blockchain.png" width="500" height="164" alt="" /&gt;
&lt;/div&gt;
&lt;p class="foot"&gt;Схематичное представление блокчейна&lt;/p&gt;
&lt;p&gt;Хешами называют результаты хеширования.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Хеширование — это преобразование массива входных данных в битовую строку фиксированной длины, выполняемое определённым алгоритмом&lt;a href="https://ru.wikipedia.org/wiki/%D0%A5%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5"&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Хеш-функция работает таким образом, что даже незначительные изменения входных данных приведут к значительному изменению хеша. Из-за этого механизма блоки связываются в цепочку с жесткой зависимостью от содержания предыдущего блока.&lt;br /&gt;
Система хранит информацию о всех действиях внутри себя и является единственным достоверным источником данных для своих участников, причём информацию нельзя добавить, перезаписать или удалить, не согласовав действия с другими узлами сети. Сам блокчейн при соблюдении этих условий является единственным источником данных для своих участников.&lt;/p&gt;
&lt;p&gt;Блокчейн обеспечивает высокую надежность сохранности данных и прозрачность всех действий, в результате чего повышается уровень доверия участников сети друг к другу и к блокчейну.&lt;br /&gt;
Наиболее развитые области, в которых применяется технология блокчейн: финансы и налогообложение, проведение прозрачных процессов голосований, криптовалюты. Наиболее перспективны на данном этапе развития технологии областях распределённых вычислений BigData и информационной безопасности.&lt;/p&gt;
&lt;h2&gt;Применение блокчейна в области распределённых вычислений и BigData&lt;/h2&gt;
&lt;p&gt;Спрос на вычисления и обработку данных больших объемов постоянно растет как со стороны научного сообщества, так и со стороны бизнеса и частных лиц. На данный момент для решения задач таких объемов используют суперкомпьютеры и серверные кластеры. Устройства подобного рода занимают большие площади, дороги в разработке и обслуживании, являются ограниченным ресурсом и существенно увеличивают издержки.&lt;/p&gt;
&lt;p&gt;Число вычислительных устройств в мире с хорошими показателями вычислительных мощностей постоянно растёт, однако “КПД” этих вычислительных мощностей падает. При среднестатистическом использовании персонального компьютера большую часть времени центральный и графический процессоры в лучшем случае используются на 30%.&lt;br /&gt;
Неиспользуемые мощности персональных компьютеров, серверов и даже смартфонов могут приносить пользу, производить вычисления и решать какие-то задачи,  если использовать давно существующий подход распределённых вычислений.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Распределенные вычисления — способ решения трудоемких вычислительных задач с использованием нескольких компьютеров, чаще всего объединённых в параллельную вычислительную систему&lt;a href="https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D0%B5_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F"&gt;&lt;sup&gt;[2]&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Проблемой всех существующих систем распределенных вычислений является зависимость от какого-то управляющего центра. Задержки, вызванные особенностями работы сети интернет, большие нагрузки на системы провайдеров и особенности географического расположения узлов являются лишь малой частью проблем, возникающих при обработке данных, созданных на множестве независимых друг от друга устройств. Решением этой проблемы является предоставление устройствам возможности обмена данными друг с другом в режиме реального времени, что распределит нагрузку. В этом случае остаётся лишь одна крупная проблема — синхронизация и валидация различных узлов. С этой задачей и призван справиться блокчейн.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://ifedyukin.ru/blog/pictures/blockchain-destrib.png" width="680" height="383" alt="" /&gt;
&lt;/div&gt;
&lt;p class="foot"&gt;Распределённая сеть устройств на основе блокчейна&lt;/p&gt;
&lt;p&gt;С помощью блокчейна можно создать огромную распределенную сеть, узлами которой будут устройства. Работу каждого узла можно четко отследить, поэтому в зависимости от предоставленных вычислительных мощностей участнику сети делается выплата. Каждый узел сети будет характеризоваться собственным рейтингом, предоставляемыми для вычислений мощностями и их ценой.&lt;br /&gt;
Общий алгоритм работы подобной платформы предельно прост. Сначала контролирующим центром составляется список задач. Участники сети получают доступ к задачам или их частям в соответствии с их вычислительными мощностями и рейтингом. Результат вычислений проходит проверку контролирующим центром или другими участниками сети. Производятся выплаты. Обработанные данные возвращаются заказчику, где проходят дополнительные проверки. В случае успеха исполнителю производится выплата. Происходит переход к следующей задаче. Рейтинг пользователя строится на основе успешности выполнения задач и произведения платежей.&lt;/p&gt;
&lt;p&gt;Подобная платформа имеет огромный потенциал для снижения издержек и увеличения производительности в таких областях, как научные исследования, машинное обучение и рендеринг графики в несколько раз.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://ifedyukin.ru/blog/pictures/network-types.png" width="779" height="486" alt="" /&gt;
&lt;/div&gt;
&lt;p class="foot"&gt;Схематичные представления различных типов сетей&lt;/p&gt;
&lt;p&gt;Можно сделать вывод, что в сфере распределённых вычислений блокчейн имеет очень большое значение и крупные перспективы. Поскольку блокчейн позволяет создать децентрализованную инфраструктуру, она может приблизить данные к их производителям и потребителям, тогда как централизованные облачные вычисления и центры обработки данных, как правило, расположены в отдаленных районах.&lt;/p&gt;
&lt;p&gt;Спрос на вычисления будет продолжать расти по мере развития сопутствующих технологий. Будут ли облачные сервисы масштабироваться, чтобы удовлетворить требованиям ресурсов, затрат и скорости,еще не известно, но блокчейн предлагает выгодную альтернативу, может дать новые возможности и преуспеть в тех случаях, когда существующие технологии уже не смогут предложить ничего интересного.&lt;/p&gt;
&lt;h2&gt;Применение блокчейна в области информационной безопасности веб-систем&lt;/h2&gt;
&lt;p&gt;С точки зрения информационной безопасности, блокчейн — это технология, которая помогает шифровать все действия, выполняемые с файлом или объектом, в хеш. Фактически, это не совсем шифрованием, но оно не может быть отменено, изменено и или вскрыто простыми способами, в то же время все манипуляции с зашифрованными блоками остаются полностью прозрачными: всегда известно, какие транзакции были выполнены, когда и кем. Такой подход к обеспечению безопасности данных открывает новые возможности в области безопасности веб-приложений.&lt;/p&gt;
&lt;p&gt;Недостатком популярных сегодня средств общения (социальных сетей и мессенджеров) является централизация хранимых данных и не всегда надежное сквозное шифрование, используемое ими повсеместно, это ставит под угрозу защищенность данных, с помощью которых часто можно идентифицировать личность человека, отправляющего сообщение, его электронную почту и другие данные.&lt;/p&gt;
&lt;p&gt;Блокчейн решает эту проблему, избавляя пользователя от необходимости постоянного использования личных данных для авторизации в системах, а компании от необходимости поиска надежного хранилища и организации его защиты. Все данные будут случайным образом разбиты на небольшие кусочки (чанки) и распределены по пользователям всей системы. Отдельный пользователь не сможет извлечь из отдельного чанка никакой информации, а злоумышленник не сможет собрать все чанки воедино.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://ifedyukin.ru/blog/pictures/blockchain-logo.jpg" width="1356" height="668" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Децентрализация хранилища данных делает провайдеров данных менее уязвимыми для централизованных атак, так же позволят предприятиям обеспечить безопасность коммерческих данных гораздо эффективнее и снизить затраты на хранение информации. В случае внутреннего нарушения протокола блокчейн позволит безошибочно узнать источник опасности и изолировать его.&lt;/p&gt;
&lt;p&gt;Блокчейн предоставляет множество возможностей для обнаружения и предотвращения хакерских атак на веб-сайты. Признаки  DDoS-атак сохраняются в блоки, и при повторном обнаружении подобных атак доступ злоумышленнику будет ограничен, такой подход уже используют PayPal, Twitter, Spotify и другие крупные компании.&lt;/p&gt;
&lt;p&gt;У существующей системы DNS-серверов тоже есть проблемы с защищенностью информации, потому что они хранят ключи доступа в централизованном хранилище и часто почти полностью полагаются на кеширование. Эту проблему можно решить с помощью блокчейна, используя распределенную сеть ключей и ключевых узлов-серверов. В конечном счете, блокчейн защитит серверы от хакерских атак и сделает их практически недоступными для злоумышленников, а также снизит риски отказа в обслуживании в результате высокой нагрузки на централизованный сервер или нарушения целостности кеша.&lt;/p&gt;
&lt;p&gt;Блокчейн — самое перспективное изобретение в области кибербезопасности последнего десятилетия. Вероятно, это произведет революцию существующих систем кибербезопасности, обеспечит гораздо более безопасный интернет на долгие годы и, в любом случае, запустит новый цикл эволюции индустрии.&lt;/p&gt;
</description>
</item>

<item>
<title>Диплом 4. Redux, роутер, SSR</title>
<guid isPermaLink="false">22</guid>
<link>https://ifedyukin.ru/blog/all/bachelor-work-4/</link>
<pubDate>Sun, 28 Jan 2018 17:44:51 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/bachelor-work-4/</comments>
<description>
&lt;p&gt;Сегодня я начинаю писать клиентскую часть диплома. Первым делом надо всё донастроить, сконфигурировать и связать с роутером и redux’ом.&lt;/p&gt;
&lt;p&gt;Втащить Redux несложно, сложно его подключить нормально и прокинуть всё через роуты. Так ещё и ESlint ругается на код типа:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;class App extends React.Component {
  methodName = () =&amp;gt; {
    /*Говорит, что methodName undefined =/ */
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Окей, ESlint оказался как-то слишком старым, обновил — вроде всё завелось.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Так, вроде бы заработало, успел всё сломать и починить пару раз. `react-router-redux` заюзать всё-таки пришлось. Пока далеко от роутинга не ушёл, нужно серверный рендеринг сделать.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Серверный рендеринг + react + redux = вообще ад какой-то. Что-то то одно, то другое ломается, мануалы везде разные, ЧИТО ДЕЛАТЬ.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Сейчас, например, babel-node ну никак не хочет модключать стили в изоморфный компонент со стороны сервера.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Ладно, решил уже не заморачиваться с «горячей» отладкой SSR, поэтому его только после билда можно проверить. Что касается мануалов — самый подходящий оказался на [codeburst](&lt;a href="https://codeburst.io/react-isomorphic-universal-app-w-nodejs-redux-react-router-v4-be80aa57dcaf)."&gt;https://codeburst.io/react-isomorphic-universal-app-w-nodejs-redux-react-router-v4-be80aa57dcaf).&lt;/a&gt; Теперь рендеринг на сервере работает, но вот правильно или нет я пока не совсем разобрался.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Удалил `react-router-redux`, ибо не так он уж мне и нужен. Я так-то пока не придумал, зачем мне вообще в этом проекте Redux.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Всё-таки у меня есть предположение, что менеджмент состояний я умудрился сломать, но с проблемами буду разбираться по мере их поступления.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Хм, опять же это всего диплом, а я не планировал делать SSR для кого-то кроме поисковых ботов, так что пока вообще всё неплохо идёт.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Так, всплыло куча косяков со статикой и подобным, но сейчас исправлено всё, кроме, конечно, режима разработки, в котором у меня NodeJS через babel запускался, но теперь-то там в каких-то местах в компоненты стили импортируются, в результате чего babylon падает с ошибкой.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Поправил dev-сборку, а всё ломалось из-за того, что где-то там, через 2 файла подключался компонент со стилями, чего babel терпеть не желал. В процессе ещё со статикой нахватал проблем и gzip, но там я над фиксами долго думал по причине невнимательного чтения доков.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Результатом части вчерашнего дня и почти всего сегодняшнего является исправленные конфиги сборки и работающий серверный рендеринг, хотя могло бы быть лучше.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p class="note"&gt;Больше они не работают, т. к. блог уже пару раз переехал&lt;/p&gt;
&lt;p&gt;Под конец дня зачем-то добавил в блог &lt;a href="https://www.webpagefx.com/tools/emoji-cheat-sheet/"&gt;Github emoji&lt;/a&gt; :sunglasses: (чуть-чуть пописал на jQuery).&lt;/p&gt;
&lt;p&gt;А сейчас пора почитать что-то интересное и отдыхать, например, &lt;a href="https://medium.freecodecamp.org/rest-is-the-new-soap-97ff6c09896d" class="nu"&gt;«&lt;u&gt;REST is the new SOAP&lt;/u&gt;»&lt;/a&gt;, а так же пара ответов &lt;a href="https://philsturgeon.uk/api/2017/12/18/rest-confusion-explained/" class="nu"&gt;«&lt;u&gt;A Response to REST is the new SOAP&lt;/u&gt;»&lt;/a&gt; и &lt;a href="https://philsturgeon.uk/api/2018/01/20/rest-confusion-explained-further/" class="nu"&gt;«&lt;u&gt;Still Going on REST is the new SOAP&lt;/u&gt;»&lt;/a&gt;.&lt;/p&gt;
</description>
</item>

<item>
<title>Диплом, часть 3. MongoDB, API, Cloudinary</title>
<guid isPermaLink="false">20</guid>
<link>https://ifedyukin.ru/blog/all/bachelor-work-3/</link>
<pubDate>Wed, 17 Jan 2018 17:35:20 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/bachelor-work-3/</comments>
<description>
&lt;p&gt;Формат, когда я просто рассказываю, что я сделал меня не совсем устраивает, ибо в будущем я хочу проанализировать ход разработки. Поэтому воспользуюсь форматом, похожим на то, как герой фильма «Социальная сеть» описывал разработку Facemash: короткие записи о каждом небольшом шаге.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Прикрутить базу оказалось несложно, работать с ней тоже проще простого. Начнём с написания авторизации пользователей.&lt;br /&gt;
В этот раз я решил юзать `passport.js` и ещё некоторые обвесы. Писать буду на основе своих существующих знаний и серии видео по написанию системы логина с использованием выше названной библиотеки.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;iframe style="margin: 0 auto; display: block;" width="560" height="315" src="https://www.youtube-nocookie.com/embed/Z1ktxiqyiLA" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;В общем и целом объясняют не совсем так, как мне хотелось бы и как объяснял бы я именно взаимодействие NodeJS, работу Express. Но непосредственно по `passport.js` меня всё устраивает.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;На самом деле многие моменты этих видео-уроков оставляют желать лучшего. Единтсвенное, что оказалось полезным... да ничего, наверно, просто нужно было понять в каком месте в общей системе надо подцеплять библиотеку и что как и где использовать.&lt;/p&gt;
&lt;p&gt;—-&lt;/p&gt;
&lt;p&gt;Долго сидел и искал непонятную ошибку, которая всё мне роняла, причиной оказалась моя невнимательность и особенность Express, в 1 и 2 строке сниппета res не одно и то же, т. к. в зависимости от числа параметров в функцию пробрасываются отличающиеся параметры:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;export default (err, req, res, next) =&amp;gt; ...
export default (err, req, res) =&amp;gt; ...&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Помимо всего `passport.js` как-то не особо укладывается в архитектуру приложения, которую я сначала хотел реализовать. Пока сделаю чисто так, чтобы просто работало, а затем уже буду рефакторить.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;У этой библиотеки ну очень странная документация и очень странное поведение. Довольно долго разбирался со всем этим. Пока готова простейшая регистрация и логин. Нужно прикрутить токены, и, в принципе, серверная часть с авторизацией будет готова.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;После деплоя все вызовы API работают, это гуд. Прикручиваю токены.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Всё оказалось гораздо проще, и Passport мне вообще не нужен будет, ибо есть JWT. День в пустую.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Окей, с API логина и регистрации разобрались. Теперь накидаем простые варианты API и чуть расширим схемы моделей.&lt;br /&gt;
Конечно, я шифрую пароли bcrypt’ом. Сейчас объект юзера в БД хранится в примерно таком виде:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;{
  &amp;quot;_id&amp;quot;: {
    &amp;quot;$oid&amp;quot;: &amp;quot;5a5cbe2425ac100014571bd4&amp;quot;
  },
  &amp;quot;login&amp;quot;: &amp;quot;root&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;$2a$10$YWEDx35UrhtLOg1x2FPP5ezxPP7XSbFfuYsvpdWblGGbo9nqLLzZe&amp;quot;,
  &amp;quot;email&amp;quot;: &amp;quot;root@example.com&amp;quot;,
  &amp;quot;__v&amp;quot;: 0
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Сделал API для юзеров. Вроде бы всё ок, нужно только продумать, как быть с аватарами и всякими такими файлами.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Серверная часть готова абсолютно, если исключить всякие особенности и, конечно, загрузку файлов.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Несколько часов промучался с загрузкой файлов, а все проблемы были в правах и неверных заголовках. Теперь вроде бы окей работает загрузка отдельных файлов в виде `form-data`. За это спасибо `Multer.js`. Теперь ещё впилю поддержку облака `cloudinary`.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Собирался накостылять своё решение, но вовремя нашёл `multer-storage-cloudinary.js`. Закинул в деплой, теперь осталось чуть-чуть протестировать.&lt;/p&gt;
&lt;p&gt;Окончательная версия выглядит примерно так:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Routes.js&lt;/b&gt;&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;import express from 'express';
import checkToken from '../middlewares/checkToken';
import * as FileController from '../controllers/file';

const router = express.Router();
router.post('/avatar', checkToken, FileController.uploadFile('avatar'), FileController.uploadController);
router.post('/event', checkToken, FileController.uploadFile('event'), FileController.uploadController);

export default router;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Controllers.js&lt;/b&gt;&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;import path from 'path';
import multer from 'multer';
import cloudinary from 'cloudinary';
import cloudinaryStorage from 'multer-storage-cloudinary';
import config from '../config';

cloudinary.config(config.cloudinary);

const storage = fieldName =&amp;gt; (config.isProduction ?
  cloudinaryStorage({
    cloudinary,
    folder: `${config.uploadDirectory}/${fieldName}`,
    allowedFormats: ['jpg', 'jpeg', 'png', 'gif'],
    filename: (req, file, callback) =&amp;gt; {
      callback(null, req.user._id);
    },
  }) :
  multer.diskStorage({
    destination: config.uploadDirectory,
    filename: (req, file, callback) =&amp;gt; {
      callback(null, req.user._id + path.extname(file.originalname));
    },
  })
);

export const uploadFile = fieldName =&amp;gt; multer({
  storage: storage(fieldName),
  limits: { fileSize: config.maxFileSize },
}).single(fieldName);

export const uploadController = async (req, res, next) =&amp;gt; {
  if (req.file) {
    if (config.isProduction) {
      return res.json({
        fileUrl: req.file.url,
      });
    }
    const filePath = req.file.destination.slice(req.file.destination.indexOf('/') + 1);
    return res.json({
      fileUrl: `/${filePath}${req.file.filename}`,
    });
  }

  return next({
    status: 500,
    message: 'Upload error!',
  });
};&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Проверить работу можно следующим образом (отправлять запросы можно, например, Postman’ом):&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Регистрируемся, послав &lt;b&gt;post&lt;/b&gt;-запрос на &lt;a href="http://diploma.ifedyukin.ru/api/user/register,"&gt;http://diploma.ifedyukin.ru/api/user/register,&lt;/a&gt; формат `x-www-form-urlencoded`, поля: login, password, email (что в них отправлять, думаю, не стоит комментировать); последующий вход осуществляется отправкой такого же запроса, только на &lt;a href="http://diploma.ifedyukin.ru/api/user/login"&gt;http://diploma.ifedyukin.ru/api/user/login&lt;/a&gt; и без поля «email» — в ответ придёт токен авторизации;&lt;/li&gt;
&lt;li&gt;В ответе получаем объект, в котором нас интересует поле `token`, содержимое этого поля вносим в заголовок `Authorization`;&lt;/li&gt;
&lt;li&gt;Посылаем &lt;b&gt;post&lt;/b&gt;-запрос на &lt;a href="http://diploma.ifedyukin.ru/api/file/avatar,"&gt;http://diploma.ifedyukin.ru/api/file/avatar,&lt;/a&gt; формата `form-data`, с полем `avatar`, в котором будет лежать картинка.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Прикрутил аналитику от «Keen.io» и логгирование от «Logentries». Теперь могу смотреть статистику всяких событий, отслеживать «атаки» (сегодня в 4 утра кто-то пытался подбирать пароли к учетным записям, которых нет) и много-много всего интересного, а так же анализировать ошибки, внезапно возникающие при работе.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;В планах прикрутить авторизацию на основе блокчейна (воспользуюсь готовым сервисом, но главное — блокчейн &lt;s&gt;антихайп&lt;/s&gt;), server-side рендеринг страничек полностью реализовать и сделать нормальную систему service-worker’ов, чтобы клиентская часть работала быстро в нескольких потоках (вероятно) и вообще: всё было здорово.&lt;br /&gt;
Но к этому я перейду после того, как сделаю базовую часть клиентской части, ибо, по сравнению с сервером, времени на это уйдёт ну очень много.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Впилил защиту от бесконечных регистраций и брутфорса паролей, ну и, конечно, закинул сбор статистики кого и с каким IP заблокировала «защита».&lt;/p&gt;
</description>
</item>

<item>
<title>Диплом, часть 2. Сборка и CI</title>
<guid isPermaLink="false">19</guid>
<link>https://ifedyukin.ru/blog/all/bachelor-work-2/</link>
<pubDate>Sun, 14 Jan 2018 17:29:01 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/bachelor-work-2/</comments>
<description>
&lt;p&gt;Как уже было сказано &lt;a href="https://aegeus.ifedyukin.ru/blog/all/bachelor-work-1/"&gt;в предыдущем посте&lt;/a&gt;, диплом я буду писать полностью на JavaScript. 2018 год, поэтому никакие Gulp’ы (или Makefile’ы) для сборки JS я использовать не буду. Обойдусь одним WebPack.&lt;/p&gt;
&lt;p&gt;Изначально я планировал собирать только FrontEnd, но потом и BackEnd решил тоже включить в сборку, ибо это даст больше профита, т. к. нативно NodeJS не всё хорошо поддерживает. Да и это отличная возможность пощупать TypeScript везде, где возможно.&lt;/p&gt;
&lt;p&gt;Т. к. собираются и клиент и сервер, то будет соответственно 2 конфига webpack’a. Ничего особенного в них нет, если не брать во внимание, что в каждом конфиге есть и babel, и TypeScript. Приложение я планирую писать всё-таки на JS, а всякую сложную логику на TypeScript. В результате такой “архитектуры” у меня и в конфигах некоторая путаница (на первый взгляд), и линтеров целых 2. Ну, опять же в первую очередь я хочу хоть чуть пощупать TypeScript, так что приемлемо.&lt;/p&gt;
&lt;p&gt;Конфиги клиента так же имеют кучу всяких loader’ов для стилей, картинок и всего-всего, но в них углубляться не буду. “Для вязкости” были добавлены всякие плагины.&lt;/p&gt;
&lt;p&gt;В production-сборке:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;config.plugins = [
  new CaseSensitivePathsPlugin(),
  new HappyPack({
    id: 'JavaScript',
    threads: Math.min(os.cpus().length, 4),
    loaders: [{
      loader: 'babel-loader',
    }],
  }),
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks(module) {
      return module.context &amp;amp;&amp;amp; module.context.indexOf('node_modules') !== -1;
    },
  }),
  new JavaScriptObfuscator({
    rotateUnicodeArray: true,
  }),
  new HtmlWebpackPlugin({
    title: 'Event-Listener',
    template: '../src/client/templates/production.html',
  }),
  new CompressionPlugin({
    algorithm: 'gzip',
  }),
];&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В development-сборке:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;config.plugins = [
  new HappyPack({
    id: 'JavaScript',
    threads: Math.min(os.cpus().length, 4),
    loaders: [{
      loader: 'babel-loader',
    }],
  }),
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks(module) {
      return module.context &amp;amp;&amp;amp; module.context.indexOf('node_modules') !== -1;
    },
  }),
  new HtmlWebpackPlugin({
    title: 'Event-Listener',
    template: '../src/client/templates/development.html',
  }),
  new CaseSensitivePathsPlugin(),
];&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Серверный конфиг оказался поинтереснее для меня, ибо их я никогда не писал, да и в результате поиска решений некоторых ошибок всплыли интересные особенности. Серверную часть, конечно, так же можно писать и на JS, и на TS. По итогу конфиг webpack’а для сборки сервера выглядит так:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;const config = {
  entry: {
    server: path.resolve(__dirname, '../src/server/index.js'),
  },
  target: 'node',
  externals: fs.readdirSync(path.resolve(__dirname, '../node_modules'))
    .reduce((acc, mod) =&amp;gt; {
      if (mod === '.bin') {
        return acc;
      }

      acc[mod] = 'commonjs ' + mod;
      return acc;
    }, {}),
  node: {
    console: false,
    global: true,
    process: true,
    Buffer: false,
    __filename: false,
    __dirname: false,
  },
  output: {
    path: path.resolve(__dirname, '../build/server'),
    filename: '[name].js',
    publicPath: '/',
  },
  resolve: {
    extensions: [
      '.ts',
      '.js',
      '.json',
    ],
  },
  module: {
    loaders: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        loader: 'awesome-typescript-loader',
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.json$/,
        loader: 'json',
      },
    ],
  },
};&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;CI/CD одна из тех вещей, которую я делал не потому что надо (в отличие от webpack-конфига), а потому что интересно было всё это настроить. В &lt;a href="https://aegeus.ifedyukin.ru/blog/all/bachelor-work-1/"&gt;предыдущем посте&lt;/a&gt; я рассказал, что деплой на Heroku — просто. Не совсем так.&lt;/p&gt;
&lt;p&gt;Я хотел, чтобы билд производился на GitLab CI, а уже собранное приложение заливалось на Heroku.&lt;br /&gt;
Первая проблема: dpl заливал “чистую” версию приложения, без билда, без ещё чего-то. Я долго не мог понять, почему так, нормальной документации у dpl нет и не было (либо я не нашел). Но, где-то в обсуждениях GitLab CI я нашел решение: параметр —skip-cleanup. Теперь “скрипт”, производящий деплой выглядит так:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;- dpl --provider=heroku --app=el-dev --api-key=$HEROKU_API_KEY --skip-cleanup&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Для stage’а “Deploy” в качестве зависимости указан stage “Build”:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;dependencies:
  - &amp;quot;Build&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Stage “Build” производит сборку и сохраняет результат на 3 часа (не знаю, почему именно на 3, но просто сделал так):&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;&amp;quot;Build&amp;quot;:
  image: node:8.9.2
  stage: Checks
  dependencies:
    - &amp;quot;Install&amp;quot;
  script:
    - npm run build
  artifacts:
    expire_in: 3 hrs
    paths:
      - assets
      - build
      - public&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;С деплоем собранного приложения разобрались, но так же на Heroku улетало множество конфигов, исходников и подобных бесполезных для production’а файлов. Нужно было удалять всё лишнее. В *nix довольно несложно решить эту проблему, однако большая часть способов построена на использовании глобальных параметров системы или изменении. Использовать эти способы CI не позволяет, поэтому решением стал небольшой sh-скрипт, удаляющий всё лишнее:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#!/bin/bash

find ./ \
     -type f \
     -maxdepth 1 \
     -mindepth 1 \
     -name &amp;quot;*&amp;quot; \
     ! -name &amp;quot;Procfile&amp;quot; \
     ! -name &amp;quot;app.json&amp;quot; \
     ! -name &amp;quot;package.json&amp;quot; \
     ! -name &amp;quot;package-lock.json&amp;quot; \
     -exec rm -r {} \;

find ./ \
     -type d \
     -maxdepth 1 \
     -mindepth 1 \
     -name &amp;quot;*&amp;quot; \
     ! -name &amp;quot;public&amp;quot; \
     ! -name &amp;quot;assets&amp;quot; \
     ! -name &amp;quot;build&amp;quot; \
     ! -name &amp;quot;.git&amp;quot; \
     -exec rm -r {} \;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;После удаления можно заливать только необходимые файлы на Heroku.&lt;br /&gt;
Кстати, Heroku передаёт вообще все переменные проекта через process.env.VARIABLE, например, параметры MongoDB.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://ifedyukin.ru/blog/pictures/ci-schema.png" width="1010" height="245" alt="Схема CI в Gitlab" /&gt;
&lt;/div&gt;
&lt;p class="foot"&gt;Схема CI в Gitlab&lt;/p&gt;
&lt;p&gt;Теперь можно начать писать чисто код, изредка добавляя loader’ы в конфиг клиентского webpack и не о чем другом не думать. Особенно хорошо, что в TypeScript я могу погружаться совсем понемногу и использовать его только там, где нужно, хотя, вероятно, для подобного использования стоило бы просто втянуть Flow, но уже поздно (да и мне как-то лень)…&lt;/p&gt;
&lt;p&gt;Ну, и, конечно, можно прикрутить Docker, чтобы не думать об окружении, но это уже в будущем, если вообще понадобится.&lt;/p&gt;
</description>
</item>

<item>
<title>Диплом, часть 1. Главное начать</title>
<guid isPermaLink="false">17</guid>
<link>https://ifedyukin.ru/blog/all/bachelor-work-1/</link>
<pubDate>Sat, 30 Dec 2017 17:17:43 +0300</pubDate>
<author></author>
<comments>https://ifedyukin.ru/blog/all/bachelor-work-1/</comments>
<description>
&lt;p&gt;Итак, 4 курс. В конце этого учебного года надо защищать диплом.&lt;br /&gt;
За процессом написания диплома надо как-то наблюдать, ну а чтобы как-нибудь потом порефлексировать, буду сюда писать небольшие посты.&lt;/p&gt;
&lt;p&gt;В любом деле самое сложное — начать. Благо, начать писать диплом мне помог Hacktoberfest. А как именно — я рассказал на &lt;a href="https://youtu.be/amkV3KRyw28?t=44m10s"&gt;последнем митапе&lt;/a&gt; WebPurple.&lt;/p&gt;
&lt;p&gt;В целом, всё, что я получил от Open Source сообщества — заготовки общих концепций. Нужно переходить к конкретики.&lt;/p&gt;
&lt;p&gt;Результатом моего диплом, в теории, должно быть готовое программное обеспечение, решающуе какую-либо проблему. Моя тема — “ПО для организации мероприятий”. Под мероприятиями подразумеваются митапы, конференции, etc. Тема несложная, что и как должно работать я понимаю, поэтому с продумыванием реализации проблем возникнуть не должно.&lt;/p&gt;
&lt;p&gt;С технологиями я решил чуть-чуть подзагнаться (хотя мог бы взять PHP и нашлёпать за день), поэтому буду писать диплом с надеждой изучить что-то новое и закрепить знания в том, что знаю.&lt;/p&gt;
&lt;p&gt;На клиенте у меня будет типичная связка React + Redux, к которым я прикручу TypeScript (ибо давно хотел его подробно пощупать), а так же SASS (чтобы стили просто писались).&lt;br /&gt;
На сервере будет NodeJS и Epress, а в качестве БД — MongoDB с Mongoose. Этот стек серверных технологий мне кажется наиболее подходящим для текущей задачи, да и он мне интересен сильнее других.&lt;/p&gt;
&lt;p&gt;Так как относительно недавно я открыл в себе интерес к DevOps, то всё это должно быть максимально автоматизировано, тестироваться, деплоиться и выполнять трюки само. Для этого я планирую использовать GitLab CI (потому что он клёвый).&lt;/p&gt;
&lt;p&gt;Именно с CI/CD я и начал. Попытался сделать конфиг, который бы деплоил приложение на Express на Heroku. Вышло что-то типа этого:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;stages:
  - heroku

before_script:
  - apt-get update -y
  - apt-get install apt-transport-https -y

deploy:
  stage: heroku
  script:
    - apt-get update -yq
    - apt-get install rubygems ruby-dev -y
    - gem install dpl
    - dpl --provider=heroku --app=el-dev --api-key=$HEROKU_API_KEY&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;К моему удивлению всё это с первого раза задеплоилось и заработало, исключая SSL-сертификаты, но это уже проблемы моего конфига Cloudflare.&lt;/p&gt;
&lt;p&gt;На этоп часть первая окончена, следующим шагом планирую написать все конфиги (babel, webpack, etc) для development и production.&lt;/p&gt;
&lt;p&gt;Production-билд будет крутиться на &lt;a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ"&gt;diploma.ifedyukin.ru&lt;/a&gt;.&lt;/p&gt;
</description>
</item>


</channel>
</rss>