DEV Community: Даниил Пронин The latest articles on DEV Community by Даниил Пронин (@grawl). https://dev.to/grawl https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F130360%2F1effee26-b8ad-43ba-8f63-034ef873b2e7.jpeg DEV Community: Даниил Пронин https://dev.to/grawl en Как установить купленный WarCraft III: The Frozen Throne в 2025 году? Даниил Пронин Thu, 07 Aug 2025 16:46:23 +0000 https://dev.to/grawl/kak-ustanovit-kupliennyi-warcraft-iii-the-frozen-throne-v-2025-ghodu-128h https://dev.to/grawl/kak-ustanovit-kupliennyi-warcraft-iii-the-frozen-throne-v-2025-ghodu-128h <p>Так случилось, что в детстве мне удалось купить два диска с WarCraft III: Reign of Chaos и The Frozen Throne. Два диска с лицензионными ключами на внутренней стороне коробки.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmt8zlro1ge8wvmp07b0j.jpg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmt8zlro1ge8wvmp07b0j.jpg" alt="Диски WarCraft III: Reign of Chaos и The Frozen Throne" width="800" height="388"></a></p> <p><em>Фотка не моя, нашёл в интернете - сейчас я уже и не помню, где они. Но мои были точно такими же.</em></p> <p>Когда у меня появился интернет, я зарегистрировал оба кода в профиле на сайте battle.net.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1rkmffbsb7msr5i6so0.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1rkmffbsb7msr5i6so0.png" alt="Главное меню WarCraft III The Frozen Throne" width="800" height="450"></a></p> <p>Спустя ещё несколько лет (где-то в 2018, кажется) я захотел поиграть с друзьями в варик по сети. У меня уже был макбук тогда. На battle.net я обнаружил, что скачать игру не получается - ссылка не работала. А на торрентах официальную сборку под мак найти не удалось. Тогда я поиграл в пиратский репак через BootCamp, маки были ещё на Intel.</p> <p>И вот спустя ещё несколько лет Blizzard выпускают WarCraft: Reforged. Сразу же подумалось, что WarCraft III они полностью удалят отовсюду, а купивших его будут гайлайтить кнопкой "купи рефорж".</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fii5az2x6uu1uwgyrqlfv.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fii5az2x6uu1uwgyrqlfv.png" alt="Клиент battle.net предлагает мне купить WarCraft: Reforged" width="800" height="500"></a></p> <p>Но нет, у меня в профиле на сайте battle.net всё ещё есть обе купленные игры. В самом низу страницы <a href="proxy.php?url=https://account.battle.net/games#classic-game-accounts" rel="noopener noreferrer">Игры и подписка</a> есть обе игры, и ключи к ним. И ссылка "Загрузить" возле каждой.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8az4l58ab7fo225flxlx.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8az4l58ab7fo225flxlx.png" alt="WarCraft III: Reign of Chaos и The Frozen Throne на странице Игры и подписка на battle.net" width="800" height="485"></a></p> <p>Ссылка ведёт на страницу <a href="proxy.php?url=https://eu.support.blizzard.com/ru/article/256212" rel="noopener noreferrer">Как установить Warcraft III: Reforged и Warcraft III: Ледяной Трон</a>, на которой есть четыре ссылки: две игры под Windows, и две под macOS.</p> <p>Я скачал The Frozen Throne, запустил <code>Downloader_Warcraft3_The_Frozen_Throne_enUS.exe</code>, и меня встретило странное окно, предлагающее сохранить куда-нибудь http_404_webOC, или открыть его.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2h3w874bcnz01o59v1e.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2h3w874bcnz01o59v1e.png" alt="Программа скачивания Thr Frozen Throne предлагает сохранить или открыть какой-то файл" width="532" height="326"></a></p> <p>Я его сохранил, и тогда вылезло следующее окно, предлагающее выбрать папку:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgxiyj8s7zmugy9ddfaw.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgxiyj8s7zmugy9ddfaw.png" alt="Окно выбора папки" width="418" height="500"></a></p> <p>Я выбрал, и скачивание началось, но без режима Peer-to-peer. И верхняя часть окна сломана.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxklb07di7wve02duuusb.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxklb07di7wve02duuusb.png" alt="Окно загрузки WarCraft III: The Frozen Throne" width="738" height="663"></a></p> <p>По окончанию загрузки меня встретило напоминание о том, почему я купил два диска, а не один.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7lno0zygkjyrm5gicxb.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7lno0zygkjyrm5gicxb.png" alt="Для установки WarCraft III: The Frozen Throne требуется Reign of Chaos" width="800" height="631"></a></p> <p><em>Скриншот на русском, так как он был сделал чуть позже по хронологии событий. Просто представьте, что он на английском.</em></p> <p>Кнопка "Купить" ведёт на страницу <a href="proxy.php?url=https://eu.shop.battle.net/en-us/product/warcraft-iii-reign-of-chaos" rel="noopener noreferrer">https://eu.shop.battle.net/en-us/product/warcraft-iii-reign-of-chaos</a>, но по ней ожидает только разочарование:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37g9k59o4lpm9cghbisf.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37g9k59o4lpm9cghbisf.png" alt="Ошибка 404 после нажатия на кнопку Купить WarCraft III: Reign of Chaos" width="800" height="478"></a></p> <p>Со страницы <a href="proxy.php?url=https://eu.support.blizzard.com/ru/article/256212" rel="noopener noreferrer">Как установить</a> я скачал Reign of Chaos, и мне удалось установить обе игры, и они запустились.</p> <p><strong>Но на английском языке.</strong></p> <p>А я хочу <em>ту самую</em> локализацию: <em><strong>никто не смеет мне приказывать!</strong></em></p> <h2> Русский язык </h2> <p>Я погуглил, и вспомнил, что переключить язык установленной игры никак нельзя. Только удалить и / или установить поверх русскую версию. Полный установщик.</p> <p>(Есть смутные воспоминания, что были какие-то патчи, которые тогда регулярно выходили, вечно ломая доту, но не уверен, что были языковые патчи.)</p> <p>Вот все ссылки с той страницы:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>https://us.battle.net/download/getLegacy?product=WAR3&amp;locale=enUS&amp;os=WIN https://us.battle.net/download/getLegacy?product=W3XP&amp;locale=enUS&amp;os=WIN https://us.battle.net/download/getLegacy?product=WAR3&amp;locale=enUS&amp;os=MAC https://us.battle.net/download/getLegacy?product=W3XP&amp;locale=enUS&amp;os=MAC </code></pre> </div> <p>Если в ссылке поменять <code>enUS</code> на <code>ruRU</code>, то скачается русская версия.</p> <p>Для RoC и TFT под Windows нужны вот такие:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>https://us.battle.net/download/getLegacy?product=WAR3&amp;locale=ruRU&amp;os=WIN https://us.battle.net/download/getLegacy?product=W3XP&amp;locale=ruRU&amp;os=WIN </code></pre> </div> <p>По ним скачиваются <code>Downloader_Warcraft3_Reign_of_Chaos_ruRU.exe</code> и <code>Downloader_Warcraft3_The_Frozen_Throne_ruRU.exe</code> - загрузчики, после работы которых будут скачаны папки <code>War3-1.27-Installer-ruRU-ROC</code> и <code>War3-1.27-Installer-ruRU-TFT</code>.</p> <p>Учитывая, в каком это всё отвратительном состоянии, мне кажется, что я просто обязан теперь всё скачанное выложить на торренты. Однажды Blizzard точно доломают и без того хромой и косой процесс доступа к лицензионной игре. (Интересно, Battle.net всё ещё работает в ней?)</p> <h2> Видеоролики </h2> <p>Я точно помню, как TFT запускается: сверху спускается правая часть главного меню с кнопками. Но у меня игра при запуске показывает сначала чёрный экран, а потом меню уже на своём месте, без спуска. Но это я переживу.</p> <p>А не переживу я то, что в <strong>видеороликах есть звук, но нет видео</strong>.</p> <p>Проблема в том, что с Windows 11 не поставляется тех кодеков, которые нужны игре. Решается проблема установкой <a href="proxy.php?url=https://codecguide.com/" rel="noopener noreferrer">K-Lite Codec Pack</a>. Я решил подстраховаться, и скачал Mega. Эх, если бы кто знал, какой именно кодек нужен игре.</p> <h2> macOS </h2> <p>Самое интересное для меня сейчас - это работа всего этого же, но на маке.</p> <p>Я скачал скачиватель RoC под Mac, но он отказался запускаться</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wkllr6ts73dyzbkp8j3.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wkllr6ts73dyzbkp8j3.png" alt="Программа скачивания WarCraft III: Reign of Chaos не работает на MacBook M1" width="800" height="536"></a></p> <p>И есть даже подозрение, что это даже не из-за того, что программа скачивания была написана под архитектуру Intel, а я пытаюсь запускать её на Apple Silicon (M1). Есть же Rosetta 2. Скорее всего это из-за того, что она 32-битная, и тут уже надо начинать какой-то пердолинг с эмуляцией.</p> <p>Пока я не разобрался с этим, но интерес и желание есть. Дополню статью, если разберусь. Какой-нибудь Game Porting Toolkit 2, или что-то с Rosetta 2.</p> Можно ли заменить базы данных Notion с помощью Obsidian? Даниил Пронин Sat, 23 Mar 2024 17:57:50 +0000 https://dev.to/grawl/mozhno-li-zamienit-bazy-dannykh-notion-s-pomoshchiu-obsidian-lfc https://dev.to/grawl/mozhno-li-zamienit-bazy-dannykh-notion-s-pomoshchiu-obsidian-lfc <p>Я очень активно пользуюсь базами данных в Notion для организации связных данных. Связывать множество таблиц между собой — отличный способ организовать мою свадьбу, например. Или все внутренние дела страйкбольного клуба (я был секретарём).</p> <p>Но отсутствие нормального оффлайна в Notion жёстко вставляет палки в колёса. А ещё он иногда разлогинивает. Не очень такое способствует задачам вроде "быстро накидать пару идей", достав телефон из кармана — нажав на иконку Notion, я часто видел либо экран входа, либо попытку синхронизации (например, когда я в лифте), в общем — я стал чаще пользоваться Apple Notes.</p> <p>И вот пришёл хайп на Obsidian. Мол, он заменит Notion. Ладно, попробуем.</p> <p>Obsidian обеспечивает оффлайн организацией всех данных в файлах Markdown. Локально. Синхронизация — через Dropdox, например. Или любое другое облако, хоть собственный сервер NextCloud или ownCloud.</p> <p>Ладно, что там с БД? В Notion это пушка просто, миллион фич и всё отлично работает. А есть ли такое у Obsidian?</p> <p>У Obsidian по-умолчанию только голые файлы Markdown в папках. Чтобы навернуть что-то посложнее, надо ставить плагины. Этим он и славится — кто угодно можно создать плагин, и все смогут им пользоваться. Стек — веб-страница.</p> <p>Поищем:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fderidbyfky4uceginqlu.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fderidbyfky4uceginqlu.png" alt=" " width="800" height="673"></a></p> <p><a href="proxy.php?url=https://www.reddit.com/r/ObsidianMD/comments/14vybi9/how_well_can_you_replicate_notion_in_obsidian/" rel="noopener noreferrer">На реддите</a> сразу ошарашивают:</p> <blockquote> <p><strong>НЕТ ВЫ НЕ ДОЛЖНЫ ПЫТАТЬСЯ ЗАМЕНИТЬ ОДИН ИНСТРУМЕНТ ДРУГИМ</strong></p> </blockquote> <p>(первый же развёрнутый ответ, который говорит мне, что вопрос просто так не решится — сворачиваю, читаю дальше)</p> <h2> <a href="proxy.php?url=https://rafaelgb.github.io/obsidian-db-folder/" rel="noopener noreferrer">Database Folder</a> </h2> <p>Ок, выглядит как то что нам нужно. Поставим его и его зависимость DataView.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjx27z8c0pai46uic8bz7.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjx27z8c0pai46uic8bz7.png" alt=" " width="800" height="525"></a></p> <p>Выглядит сомнительно.</p> <p>Типы колонок вроде те что надо:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljii0xv6he8bdl7zayw5.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljii0xv6he8bdl7zayw5.png" alt=" " width="800" height="530"></a></p> <p>Тут и Relation, и Rollup, и формула.</p> <p>Попытаюсь перетащить <a href="proxy.php?url=https://grawl.notion.site/1c5b5b9108184c23a5a917be9e189295?v=19be5852bc9748d986886ae2c45d26b8&amp;pvs=4" rel="noopener noreferrer">мою табличку модов для майнкрафта</a>.</p> <p>Ок, сразу вижу, что не хватает типа колонки для ссылок. Ладно, надеюсь, Markdown сам поймёт, что текст в ячейке это ссылка.</p> <p>Выглядит либо как что-то сломанное, либо как результат неквалифицированного труда.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3klc6q3mpk6zcgrz7x1p.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3klc6q3mpk6zcgrz7x1p.png" alt=" " width="800" height="525"></a></p> <p>Ладно, заполним несколько строк:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ew2ms3qncrm8kw7zc0h.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ew2ms3qncrm8kw7zc0h.png" alt=" " width="800" height="396"></a></p> <p>Дальше с этим плагином возиться мне как-то не хочется.</p> <p>Что там ещё есть из плагинов?</p> <h2> <a href="proxy.php?url=https://www.make.md/" rel="noopener noreferrer">MAKE.md</a> </h2> <p>Скриншоты на сайте более обнадёживают. Попробуем.</p> <p>Немного потыкавшись, становится понятно, как с этим работать: </p> <ul> <li>создаём Space (или New Space from Note)</li> <li>переключаем Files на Table View</li> </ul> <p>С этого момента становится похоже на Notion.</p> <p>Добавляя колонки, сразу же наблюдаю баг: если ввести её имя, потом выбрать тип — меню закрывается, ничего не появляется. Нужно сначала создать колонку с дефолтным типом, а потом поменять его.</p> <p>Заполняя первую колонку, нахожу следующий: теги не добавляются. Ок, попробую вместо тегов сделать Option с функцией Multiple.</p> <p>Следующая проблема: галочка "Multiple" нажимается только если целиться в галочку, но подсвечивается вся строка меню, намекая, что нажимать можно в любом её месте.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0magq3dcb5ycce7ong1b.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0magq3dcb5ycce7ong1b.png" alt=" " width="610" height="512"></a></p> <p>Следующая проблема: вот это вот меню постоянно появляется, и уже в виде нескольких копий, что понятно по чернейшей тени под ними:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqekwj07wcrm7dwqeb4bj.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqekwj07wcrm7dwqeb4bj.png" alt=" " width="800" height="521"></a></p> <p>Мда.</p> <p>Ладно, попробуем заполнить ещё две строки.</p> <p>Вводить теги становится сложновато</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdp7duh07hb7ri0b1qio.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdp7duh07hb7ri0b1qio.png" alt=" " width="740" height="840"></a></p> <p>Следующая проблема: в пустой ячейке колонки Option нет введённых в других строках вариантов.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasgdhegbgh3h5vq97dy2.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasgdhegbgh3h5vq97dy2.png" alt=" " width="800" height="721"></a></p> <p>Может, нужен другой тип колонки? Но нет, теги-то вообще не работают. Чепуха какая-то.</p> <p>Цвет опции поменять нельзя:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsywl5jw8qqrplpe2q7d2.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsywl5jw8qqrplpe2q7d2.png" alt=" " width="780" height="462"></a></p> <p>Если это — лучшая альтернатива Notion, то я пока пас.</p> <p>Пойду, поищу ещё.</p> <h2> <a href="proxy.php?url=https://github.com/blacksmithgu/datacore" rel="noopener noreferrer">Datacore</a> </h2> <p>У проекта пока что есть только репозиторий, в описании которого нет ничего про установку плагина.</p> <p>Скриншотов тоже нет.</p> <p>В Community plugins тоже его нет.</p> <h2> <a href="proxy.php?url=https://dataloom.xyz" rel="noopener noreferrer">DataLoom</a> </h2> <p>Сразу позиционирует себя как то, что я ищу.</p> <p>Не стал уже пытаться перенести моды, просто потыкал.</p> <p>Вижу, что нет Relation:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1s6vcxtldt44vj9tip2e.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1s6vcxtldt44vj9tip2e.png" alt=" " width="800" height="482"></a></p> <p>Нажимается он неплохо, но без Relation и Rollup далеко не уедешь.</p> <h2> <a href="proxy.php?url=https://github.com/marcusolsson/obsidian-projects" rel="noopener noreferrer">Projects</a> </h2> <p>Немного не туда, но тоже таблица.</p> <p>Правда, типов колонок вообще жесть как мало:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugsfsrvacpng8n7u91vy.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugsfsrvacpng8n7u91vy.png" alt=" " width="800" height="662"></a></p> <h2> Вывод </h2> <p>Погуглив ещё немного, я нашёл на форуме Obsidian очень много таких же как и я. Некоторые предлагают одно из решений выше, некоторые просто ноют. Некоторые обсуждают решения вроде <a href="proxy.php?url=https://b3log.org/siyuan/en/" rel="noopener noreferrer">Siyuan</a>, но это уже не Obsidian, там свой сервер поднимать надо.</p> <p>Нет, я не могу заменить Notion на Obsidian. До свидания.</p> Vue 3 Composition API + socket.io Даниил Пронин Thu, 26 May 2022 08:48:32 +0000 https://dev.to/grawl/vue-3-composition-api-socketio-5den https://dev.to/grawl/vue-3-composition-api-socketio-5den <p>Migrating from Vue 2 to Vue 3, you might want to start using Composition API.</p> <p>If you want to use socket.io you can search 'vue 3 socket.io' and find <a href="proxy.php?url=https://www.npmjs.com/package/vue-3-socket.io" rel="noopener noreferrer"><code>vue-3-socket.io</code></a>. You will see following in it's readme:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="k">this</span><span class="p">.</span><span class="nx">sockets</span><span class="p">.</span><span class="nf">subscribe</span><span class="p">(</span><span class="dl">'</span><span class="s1">EVENT_NAME</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="k">this</span><span class="p">.</span><span class="nx">msg</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">message</span><span class="p">;</span> <span class="p">});</span> </code></pre> </div> <p>But Vue 3 Composition API is about to use <code>setup()</code> or <code>&lt;script setup&gt;</code> and there's no <code>this</code>.</p> <p>So you have to use socket.io directly, without Vue plugin:</p> <p><code>socket.io.js</code><br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="k">export</span> <span class="kd">const</span> <span class="nx">useSocketIO</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">socket</span> <span class="o">=</span> <span class="nf">io</span><span class="p">(</span><span class="dl">'</span><span class="s1">ws://localhost:3000</span><span class="dl">'</span><span class="p">)</span> <span class="k">return</span> <span class="p">{</span> <span class="nx">socket</span><span class="p">,</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p><code>MyComponent.vue</code><br> </p> <div class="highlight js-code-highlight"> <pre class="highlight vue"><code><span class="nt">&lt;</span><span class="k">script</span><span class="nt">&gt;</span> <span class="k">import</span> <span class="p">{</span> <span class="nx">defineComponent</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">vue</span><span class="dl">'</span> <span class="k">export</span> <span class="k">default</span> <span class="nf">defineComponent</span><span class="p">({</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span> <span class="kd">const</span> <span class="p">{</span> <span class="nx">socket</span> <span class="p">}</span> <span class="o">=</span> <span class="nf">useSocketIO</span><span class="p">()</span> <span class="nx">socket</span><span class="p">.</span><span class="nf">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">welcome</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">welcome</span><span class="dl">'</span><span class="p">)</span> <span class="p">})</span> <span class="p">}</span> <span class="p">})</span> <span class="nt">&lt;/</span><span class="k">script</span><span class="nt">&gt;</span> </code></pre> </div> <p>But why not just export <code>socket</code> from <code>socket.io.js</code> and import it in a component? If I do that, I can emit events but cannot subscribe on them. Maybe it's because I use Quasar 2 with SSR mode.</p> vue socketio javascript webdev Why you don't have to commit node_modules folder Даниил Пронин Mon, 04 Apr 2022 06:09:38 +0000 https://dev.to/grawl/why-you-dont-have-to-commit-nodemodules-folder-33nm https://dev.to/grawl/why-you-dont-have-to-commit-nodemodules-folder-33nm <p>English | <a href="proxy.php?url=https://dev.to/grawl/pochiemu-nie-nado-kommitit-papku-nodemodules-e37">Russian</a></p> <p>This note is an answer to questions you can guess reading <a href="proxy.php?url=https://www.jackfranklin.co.uk/blog/check-in-your-node-dependencies/" rel="noopener noreferrer">Jack Franklin blog post</a>.</p> <blockquote> <h1> No need for npm installs </h1> <p>Once you check your <code>node_modules</code> in, there's no need to run an install step before you can get up and running on the codebase</p> </blockquote> <ol> <li><p>git works bad with a lot of files in repository. You can search “git performance many files” in Google and see a lot of info about this. For example: <a href="proxy.php?url=https://git-annex.branchable.com/tips/Repositories_with_large_number_of_files/" rel="noopener noreferrer">Just as git does not scale well with large files, it can also become painful to work with when you have a large <em>number</em> of files</a></p></li> <li><p><a href="proxy.php?url=https://stackoverflow.com/questions/35238667/is-npm-dependent-on-the-os-of-a-computer" rel="noopener noreferrer">Some packages are platform dependent</a>. For example, development tools, such as <a href="proxy.php?url=https://github.com/sass/dart-sass/releases" rel="noopener noreferrer"><code>dart-sass</code></a>.</p></li> <li><p>If you commit <code>node_modules</code> it means any developer can change any dependency with ease (it's called “monkey patching”), and this definitely will lead to a problem: when you will update this changed dependency, old changes will be lost, and you have to solve that. You never will be sure that dependency of certain version have the same code that you got initially.</p></li> </ol> <blockquote> <p>This isn't just useful for developers locally, but a big boost for any bots you might have running on a Continuous Integration platform (e.g. CircleCI, GitHub Actions, and so on). That's now a step that the bots can miss out entirely.</p> </blockquote> <p>Usually, CI is configured to cache dependencies to not download them all each time. <br> You can google it with something like “ci node_modules cache”.</p> <blockquote> <h1> Guaranteed replicated builds </h1> <p>Having your <code>node_modules</code> checked in guarantees that two developers running the code are running the exact same code with the exact same set of dependencies</p> </blockquote> <p>This is a work for lock file — a file you have to commit in which your package manager (NPM/PNPM/Yarn) writes all needed info for each downloaded dependency for guaranteed replicated build.</p> <p>If you open <code>yarn.lock</code> you can see something like this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight yaml"><code><span class="s2">"</span><span class="s">@apideck/better-ajv-errors@^0.2.4"</span><span class="err">:</span> <span class="s">version "0.2.5"</span> <span class="s">resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.2.5.tgz#b9c0092b7f7f23c356a0a31600334f7b8958458b"</span> <span class="s">integrity sha512-Pm1fAqCT8OEfBVLddU3fWZ/URWpGGhkvlsBIgn9Y2jJlcNumo0gNzPsQswDJTiA8HcKpCjOhWQOgkA9kXR4Ghg==</span> <span class="s">dependencies</span><span class="err">:</span> <span class="s">json-schema "^0.3.0"</span> <span class="s">jsonpointer "^4.1.0"</span> <span class="s">leven "^3.1.0"</span> </code></pre> </div> <p>Yarn carefully recorded that package <code>@apideck/better-ajv-errors</code> is downloaded with:</p> <ul> <li>version <code>0.2.5</code> </li> <li>by address <code>resolved</code> (direct link to <code>.tgz</code>)</li> <li>hashsum was <code>sha512-Pm1fAqCT8OE...</code> </li> <li>there was 3 dependencies</li> </ul> <p>And so on for each dependency in <code>node_modules</code> folder. Next time while <code>yarn install</code> will run in project directory, all dependencies will be downloaded using <code>yarn.lock</code> information, not <code>package.json</code>. Therefore all development team and CI, regardless of platform (Linux/macOS/Windows) have the same files, the same code, with the same hashsums.</p> <blockquote> <p>Yes, this can be managed by a package-lock.json file, or other tools, but I've seen all of them slip up rarely or allow a slight variation in a minor version number that causes issues.</p> </blockquote> <p>This mistake is often made when, when deploying a project, the developer runs <code>npm install</code>, which installs packages based on information from <code>package.json</code>, not <code>package-lock.json</code>. To install packages from the lock file, you need to run <code>npm ci</code>.</p> <blockquote> <h1> Better awareness of the code you're shipping </h1> <p>I've been surprised at how more aware I am of adding dependencies when the git diff shows me the entirety of the code that is being added to the project. This has lead us to make contributions to tools to help reduce their file size on disk and have a better awareness of the impact a dependency will have on our bundle size.</p> </blockquote> <p>When choosing dependencies, you can use special tools, and not just read miles of code.</p> <ul> <li> <p><a href="proxy.php?url=https://bundlephobia.com" rel="noopener noreferrer">Bundlephobia</a></p> <p>It will show how much the dependency weighs, how much it will be with GZIP, how long it will be downloaded over slow 3G and medium 4G Internet, it will show the percentage of the composition of the sub-dependencies, what the dependency exports (if it is written in ES Modules), as well as what alternatives or neighboring packages it has. Here's <a href="proxy.php?url=https://bundlephobia.com/package/@stylable/[email protected]" rel="noopener noreferrer">example</a>.</p> </li> <li> <p><a href="proxy.php?url=https://bundlejs.com" rel="noopener noreferrer">bundlejs.com</a></p> <p>It will show exactly how many kilobytes of code will be added when importing like<br> </p> <pre class="highlight javascript"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">map</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">nanostores</span><span class="dl">"</span> </code></pre> <p><a href="proxy.php?url=https://bundlejs.com/?q=nanostores&amp;treeshake=[{+map+}]" rel="noopener noreferrer">Look at <code>nanostores</code> example</a>.</p> </li> <li> <p><a href="proxy.php?url=https://npm.anvaka.com" rel="noopener noreferrer">npm.anvaka.com</a></p> <p>It will show a graph of all dependencies in the form of a 2D or 3D graph. <a href="proxy.php?url=https://npm.anvaka.com/#/view/2d/vue" rel="noopener noreferrer">Look at Vue 3 example</a>.</p> </li> </ul> <blockquote> <h1> More consideration to adding a dependency because it's not invisible </h1> <p>I mentioned earlier that people see the noise in a git diff as a downside to adding dependencies to version control, and I do acknowledge that it can be a downside to this approach, but I've found that noise to often be a useful signal. Adding that one extra dependency because I don't want to write a few lines of code myself is something I used to do frequently - but now I'm much more considered because I can see the code that's being added and can reflect on if it's worth it.</p> </blockquote> <p>You can read the code befure it added as a dependency to your project. GitHub repository for example. I strongly advise you to at least briefly look at the dependencies, the adequacy of the code, the number of open issues and the date of the last commit.</p> <blockquote> <p><em>Note: this doesn't mean that we don't have dependencies!</em> There are times where it is worth it to add a dependency - but seeing the code in version control has made me more considered about doing it - the cost is no longer invisible.</p> </blockquote> <p>It was never been invisible.</p> <blockquote> <h1> You can manage the large diffs </h1> <p>There is no shying away from the fact that if a developer works on a change that adds a new dependency, there could be a lot of noise in the diff. One of our dependencies that we check in is TypeScript, and every time we update that, the git diff is huge and frankly not worth looking at (beyond the CHANGELOG). We've come up with a rule that helps us here: a change that updates node_modules may not touch any other code in the codebase. So if I update node_modules/typescript with its latest version, I will be warned by our tooling if any other folder outside of node_modules is changed.</p> </blockquote> <p>You lead to a workaround.</p> <blockquote> <p>This rule serves us well the majority of the time, because any work that relies on a new or updated dependency can be split into two changes:</p> <ol> <li>Update the dependency</li> <li>Use the dependency in the code</li> </ol> <p>There are times where this doesn't work; updating TypeScript may require us to update some code to fix errors that the new version of TypeScript is now detecting. In that case we have the ability to override the rule.</p> </blockquote> <p>And here are the consequences of using that workaround.</p> <blockquote> <h1> Protection from another left pad </h1> <p>The <a href="proxy.php?url=https://qz.com/646467/how-one-programmer-broke-the-internet-by-deleting-a-tiny-piece-of-code/" rel="noopener noreferrer">now infamous left_pad incident</a>, where a popular npm package was removed from the repository all of a sudden, causing builds everywhere to break, would not have impacted a team who checked all their dependencies into git. They would still have to deal with the long term impact of "what do we do with this now unsupported dependency", but in the short term their builds wouldn't break and they wouldn't be blocked on shipping new features.</p> </blockquote> <p>I remember that day when <code>left_pad</code> was removed from NPM. I worked in a digital agency on websites, and, of course, in all the projects for which I was responsible, <code>left_pad</code> was a sub-dependency. We solved this problem then in about half an hour when CI showed 404 when trying to download the package. I don't remember what exactly we did, but such a task should not be a challenge and a reason to make workarounds.</p> <p>In the end, to protect your projects against exactly such problems, you can raise your proxy registry, for example, using <a href="proxy.php?url=https://verdaccio.org/" rel="noopener noreferrer">Verdaccio</a>. It will keep all copies of all downloaded packages.</p> node git Почему не надо коммитить папку node_modules Даниил Пронин Mon, 04 Apr 2022 06:01:52 +0000 https://dev.to/grawl/pochiemu-nie-nado-kommitit-papku-nodemodules-e37 https://dev.to/grawl/pochiemu-nie-nado-kommitit-papku-nodemodules-e37 <p><a href="proxy.php?url=https://dev.to/grawl/why-you-dont-have-to-commit-nodemodules-folder-33nm">English</a> | Русский</p> <p>Эта заметка — ответы на вопросы, которые могут возникнуть при чтении <a href="proxy.php?url=https://forweb.dev/ru/blog/check-in-your-node-dependencies" rel="noopener noreferrer">статьи Джека Франклина в переводе For Web</a>.</p> <blockquote> <h1> Нет нужды в npm install </h1> <p>Если вы храните <code>node_modules</code> в git, вам не нужно отдельно устанавливать зависимости, чтобы запустить проект.</p> </blockquote> <ol> <li><p>git плохо работает с большим количеством файлов в репозитории. Поиск фразой “git performance many files” показывает много полезной информации об этом. Например, вот: <a href="proxy.php?url=https://git-annex.branchable.com/tips/Repositories_with_large_number_of_files/" rel="noopener noreferrer">Just as git does not scale well with large files, it can also become painful to work with when you have a large <em>number</em> of files</a></p></li> <li><p><a href="proxy.php?url=https://stackoverflow.com/questions/35238667/is-npm-dependent-on-the-os-of-a-computer" rel="noopener noreferrer">Некоторые пакеты зависят от платформы</a>. Например, инструменты для разработки, такие как <a href="proxy.php?url=https://github.com/sass/dart-sass/releases" rel="noopener noreferrer"><code>dart-sass</code></a>.</p></li> <li><p>Если вы закоммитили <code>node_modules</code>, это значит, что у любого разработчика теперь есть лёгкий способ что-либо исправить в любой из зависимостей (это называется “monkey patching”), и это определённо точно приведёт к тому, что после обновления этой “исправленной” зависимости прошлое исправление будет перетёрто, и с этой проблемой придётся как-то разбираться. Вы вообще не будете уверены в том, что зависимость определённой версии соответствует тому виду, в котором она была изначально получена.</p></li> </ol> <blockquote> <p>Это полезно не только для локальной разработки, но и для ботов на CI-платформах: они могут полностью пропустить шаг установки зависимостей.</p> </blockquote> <p>CI обычно настраивают так, чтобы зависимости кешировались, и не устанавливались каждый раз с нуля. Гуглить фразой “ci node_modules cache”.</p> <blockquote> <h1> Гарантированно воспроизводимые сборки </h1> <p>Хранение <code>node_modules</code> в git гарантирует, что два разработчика запускают один и тот же код с одним и тем же набором зависимостей.</p> </blockquote> <p>Эту проблему решает “лок-файл” — специальный файл, который нужно коммитить, в который пакетный менеджер (NPM/PNPM/Yarn) записывает о каждой скачанной зависимости все необходимые данные для гарантии воспроизводимой сборки.</p> <p>Если заглянуть в <code>yarn.lock</code>, можно увидеть следующее:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight yaml"><code><span class="s2">"</span><span class="s">@apideck/better-ajv-errors@^0.2.4"</span><span class="err">:</span> <span class="s">version "0.2.5"</span> <span class="s">resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.2.5.tgz#b9c0092b7f7f23c356a0a31600334f7b8958458b"</span> <span class="s">integrity sha512-Pm1fAqCT8OEfBVLddU3fWZ/URWpGGhkvlsBIgn9Y2jJlcNumo0gNzPsQswDJTiA8HcKpCjOhWQOgkA9kXR4Ghg==</span> <span class="s">dependencies</span><span class="err">:</span> <span class="s">json-schema "^0.3.0"</span> <span class="s">jsonpointer "^4.1.0"</span> <span class="s">leven "^3.1.0"</span> </code></pre> </div> <p>Yarn заботливо записал, что он скачал пакет <code>@apideck/better-ajv-errors</code>:</p> <ul> <li>версии <code>0.2.5</code> </li> <li>по адресу <code>resolved</code> (прямая ссылка на <code>.tgz</code>)</li> <li>хеш-сумма файла была <code>sha512-Pm1fAqCT8OE...</code> </li> <li>и у этого пакета было 3 зависимости</li> </ul> <p>И так для каждой зависимости, размещённой в папке <code>node_modules</code>. И в следующий раз, когда в папке проекта будет запущена команда <code>yarn install</code>, зависимости будут скачаны не тех версий, что указаны в <code>package.json</code>, а те, что записаны в <code>yarn.lock</code>. Следовательно, у всей команды и на CI независимо от платформы (Linux/macOS/Windows) будет один и тот же набор файлов, один и тот же код, с одними и теми же хеш-суммами.</p> <blockquote> <p>Да, этого можно добиться, используя локфайлы или другие инструменты, однако я встречал случаи, когда они не спасали от изменения минорной версии какой-либо зависимости.</p> </blockquote> <p>Эту ошибку часто допускают, когда при развёртывании проекта у разработчика запускается <code>npm install</code>, который устанавливает пакеты по информации из <code>package.json</code>, а не <code>package-lock.json</code>. Чтобы установить пакеты из лок-файла, нужно запускать <code>npm ci</code>.</p> <blockquote> <h1> Лучшая осведомлённость о поставляемом коде </h1> <p>Я был удивлён тем, насколько я стал осведомлённее касательно зависимостей, когда стал видеть в диффе git весь код, попадающий в проект при их подключении. Это побудило нас поработать над инструментами, помогающими оценить влияние зависимостей на размер бандла и оптимизировать занимаемое на диске место.</p> </blockquote> <p>При выборе зависимостей можно пользоваться специальными инструментами, а не просто читать километры кода.</p> <ul> <li> <p><a href="proxy.php?url=https://bundlephobia.com" rel="noopener noreferrer">Bundlephobia</a></p> <p>Покажет, сколько весит зависимость, сколько будет с GZIP, как долго она будет скачиваться по медленному 3G и по среднему 4G-интернету, покажет в процентном соотношении состав под-зависимостей, что зависимость экспортирует (если она написана на ES Modules), а также какие у неё есть альтернативы или соседние пакеты. Вот <a href="proxy.php?url=https://bundlephobia.com/package/@stylable/[email protected]" rel="noopener noreferrer">пример</a>.</p> </li> <li> <p><a href="proxy.php?url=https://bundlejs.com" rel="noopener noreferrer">bundlejs.com</a></p> <p>Покажет, сколько точно в килобайтах будет добавлено кода при импорте вроде<br> </p> <pre class="highlight javascript"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">map</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">nanostores</span><span class="dl">"</span> </code></pre> <p><a href="proxy.php?url=https://bundlejs.com/?q=nanostores&amp;treeshake=[{+map+}]" rel="noopener noreferrer">Посмотрите это на примере <code>nanostores</code></a>.</p> </li> <li> <p><a href="proxy.php?url=https://npm.anvaka.com" rel="noopener noreferrer">npm.anvaka.com</a></p> <p>Покажет график всех зависимостей в виде 2D или 3D-графика. <a href="proxy.php?url=https://npm.anvaka.com/#/view/2d/vue" rel="noopener noreferrer">Посмотрите на примере Vue 3</a></p> </li> </ul> <blockquote> <h1> Более вдумчивое добавление зависимостей, потому что они больше не скрыты </h1> <p>Я уже упоминал, что шум в диффах воспринимается людьми как недостаток хранения зависимостей в git, и я признаю, что это действительно может быть проблемой. Однако для меня этот шум оказался полезным знаком. Раньше я часто подключал новые зависимости, просто потому что не хотел сам писать несколько строчек кода. Теперь же я гораздо внимательнее отношусь к добавлению новых зависимостей, потому что я могу увидеть добавленный ими код и решить, стоит ли он того.</p> </blockquote> <p>Вы можете прочитать код и до того, как добавить зависимость в проект. Например, зайдя в репозиторий на GitHub. Крайне советую хотя бы мельком смотреть зависимости, адекватность кода, количество открытых issue и дату последнего коммита.</p> <blockquote> <p>Примечание: это не означает, что у нас нет зависимостей! Бывают ситуации, когда подключить зависимость выгодно, но видимость кода в системе контроля версий сделала меня более осознанным — цена добавления зависимостей больше не скрыта.</p> </blockquote> <p>Она никогда и не была скрыта.</p> <blockquote> <h1> C большими диффами можно справиться </h1> <p>Нельзя игнорировать тот факт, что добавление или обновление зависимостей может вызвать много шума в диффе. Одна из наших зависимостей — TypeScript, и каждое его обновление приносит огромный дифф в git, который, честно говоря, не стоит просмотра (за пределами CHANGELOG). Мы пришли к правилу, которое помогает в таких ситуациях: изменения в <code>node_modules</code> должны быть отделены от любых изменений в основной кодовой базе. Так что если я обновлю <code>node_modules/typescript</code> до свежей версии, наш инструментарий предупредит меня при обнаружении изменений за пределами <code>node_modules</code>.</p> </blockquote> <p>Вы пришли к костылю.</p> <blockquote> <p>Это правило помогает нам в большинстве случаев, потому что любая задача, требующая добавления или обновления зависимостей, может быть разделена на две части:</p> <ol> <li>Обновление или добавление зависимости</li> <li>Использование зависимости в коде</li> </ol> <p>Иногда это не работает: например, обновление TypeScript может потребовать от нас исправления в коде ошибок, которые теперь обнаруживает новая версия TypeScript. В таких случаях мы отменяем правило.</p> </blockquote> <p>И вот последствия хождения на костылях.</p> <blockquote> <h1> Защита от очередного left_pad </h1> <p>Печально известный <a href="proxy.php?url=https://qz.com/646467/how-one-programmer-broke-the-internet-by-deleting-a-tiny-piece-of-code/" rel="noopener noreferrer">инцидент с left_pad</a> (популярный npm-пакет был внезапно удалён, ломая сборки проектов по всему миру) не затронул бы команду, которая хранит зависимости в git. В долгосрочной перспективе команде всё ещё пришлось бы разбираться с вопросом «что теперь делать с более не поддерживаемой зависимостью», но в краткосрочной перспективе их сборки бы не сломались, а релизы бы не были заблокированы.</p> </blockquote> <p>Я помню тот день, когда <code>left_pad</code> был удалён с NPM. Я тогда работал в digital-агентстве на потоке сайтов, и, конечно же, во всех проектах, за которые я был ответственен, <code>left_pad</code> был под-зависимостью. Мы решили эту проблему тогда примерно за полчаса, когда CI показал 404 при попытке скачать пакет. Я уже не помню, что именно мы предприняли, но такая задача не должна быть вызовом и поводом городить костыли.</p> <p>В конце концов, для защиты от именно таких проблем, вы можете поднять у себя прокси-реестр, например, с помощью <a href="proxy.php?url=https://verdaccio.org/" rel="noopener noreferrer">Verdaccio</a>. Он будет хранить у себя все копии всех скачанных пакетов.</p> node git migrate from nvm to asdf Даниил Пронин Mon, 04 Apr 2022 06:00:42 +0000 https://dev.to/grawl/migrate-from-nvm-to-asdf-21kl https://dev.to/grawl/migrate-from-nvm-to-asdf-21kl <h1> TL;DR </h1> <p>With <a href="proxy.php?url=https://asdf-vm.com" rel="noopener noreferrer">ASDF</a>, you can manage version of Node, Yarn, PNPM, PHP, Python, and <a href="proxy.php?url=https://github.com/asdf-vm/asdf-plugins" rel="noopener noreferrer">more than 400 other tools</a>, languages and binaries.</p> <ol> <li>Uninstall <code>nvm</code> </li> <li>Install <code>asdf</code> </li> <li> <p>Install <a href="proxy.php?url=https://github.com/asdf-vm/asdf-nodejs" rel="noopener noreferrer"><code>nodejs</code> plugin</a> for <code>asdf</code></p> <p>Add <code>legacy_version_file = yes</code> to <code>~/.asdfrc</code> file</p> </li> <li><p>Install <code>gnupg</code></p></li> <li> <p>Install global Node version using <code>asdf install nodejs lts</code></p> <p>Set is as global default using <code>asdf global nodejs lts</code></p> </li> <li> <p>Open your project folder and install Node version mentioned in <code>.nvmrc</code> using <code>asdf install</code></p> <p>When you open this folder again, <code>asdf</code> will set this version automatically</p> </li> </ol> <h1> Detailed manual </h1> <h2> 1. Uninstall <code>nvm</code> </h2> <p>No need to remove all installed Node versions one-by-one. They all are placed in <code>~/.nvm</code> folder, so just remove it:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nv">$ </span><span class="nb">cd</span> ~ <span class="nv">$ </span><span class="nb">rm</span> <span class="nt">-rf</span> .nvm .nvmrc </code></pre> </div> <p>Then, remove NVM initiation scripts from your <code>.bashrc</code> / <code>.zshrc</code> / etc.</p> <p>Find this line:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">export </span><span class="nv">NVM_DIR</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="o">[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="k">${</span><span class="nv">XDG_CONFIG_HOME</span><span class="p">-</span><span class="k">}</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">printf</span> %s <span class="s2">"</span><span class="k">${</span><span class="nv">HOME</span><span class="k">}</span><span class="s2">/.nvm"</span> <span class="o">||</span> <span class="nb">printf</span> %s <span class="s2">"</span><span class="k">${</span><span class="nv">XDG_CONFIG_HOME</span><span class="k">}</span><span class="s2">/nvm"</span><span class="si">)</span><span class="s2">"</span> <span class="o">[</span> <span class="nt">-s</span> <span class="s2">"</span><span class="nv">$NVM_DIR</span><span class="s2">/nvm.sh"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="se">\.</span> <span class="s2">"</span><span class="nv">$NVM_DIR</span><span class="s2">/nvm.sh"</span> <span class="c"># This loads nvm</span> </code></pre> </div> <p>You may have a <a href="proxy.php?url=https://github.com/nvm-sh/nvm#deeper-shell-integration" rel="noopener noreferrer">Deeper Shell Integration</a> script to install Node version as you <code>cd</code> into a folder.</p> <p>To ensure NVM is successfully uninstalled, just find any <code>nvm</code> words into your run configurations.</p> <p>To test NVM is properly uninstalled, just open a new terminal session and you should do not have any errors or warnings related to NVM.</p> <p>Also, Node is not in your <code>$PATH</code> now, and you should see following in your command line:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nv">$ </span>node <span class="nt">-v</span> <span class="nb">command </span>not found: node </code></pre> </div> <h2> 2. Install <code>asdf</code> </h2> <p>Open <a href="proxy.php?url=https://asdf-vm.com/guide/getting-started.html#_2-download-asdf" rel="noopener noreferrer">"Download asdf" section of "Getting Started" page on asdf-vm.com</a> and copy installation line. When this instruction was written, there was the following:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>git clone https://github.com/asdf-vm/asdf.git ~/.asdf <span class="nt">--branch</span> v0.8.1 </code></pre> </div> <p>You may have a different version since <code>asdf</code> will be updated in future.</p> <p>Then, add initiating script to your <code>.bashrc</code> / <code>.zshrc</code>:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">.</span> <span class="nv">$HOME</span>/.asdf/asdf.sh </code></pre> </div> <h2> 3. Install <a href="proxy.php?url=https://github.com/asdf-vm/asdf-nodejs" rel="noopener noreferrer"><code>nodejs</code> plugin</a> for <code>asdf</code> </h2> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git </code></pre> </div> <p>To allow using old <code>.nvmrc</code> files, add <code>legacy_version_file = yes</code> to <code>~/.asdfrc</code> file</p> <h2> 4. To start downloading Node you have to install <code>gnupg</code> </h2> <p>For macOS, simplest way is to install it using <a href="proxy.php?url=https://brew.sh" rel="noopener noreferrer">Homebrew</a>, like this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nv">$ </span>/bin/bash <span class="nt">-c</span> <span class="s2">"</span><span class="si">$(</span>curl <span class="nt">-fsSL</span> https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="si">)</span><span class="s2">"</span> <span class="o">(</span>it takes some <span class="nb">time </span>to <span class="nb">install </span>Homebrew<span class="o">)</span> <span class="nv">$ </span>brew <span class="nb">install </span>gnupg <span class="o">(</span>it takes some <span class="nb">time </span>too<span class="o">)</span> </code></pre> </div> <p>For Ubuntu, you already have all requirements to use <code>asdf</code>.</p> <h2> 5. Install global Node version </h2> <p><code>asdf</code> syntax to install a tool versions is <code>asdf install &lt;plugin name&gt; &lt;version&gt;</code>, so run following:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>asdf <span class="nb">install </span>nodejs lts </code></pre> </div> <p>Then, set is as global default:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>asdf global nodejs lts </code></pre> </div> <p>After this, you can use Node again<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nv">$ </span>node <span class="nt">-v</span> v16.13.1 </code></pre> </div> <h2> 6. Install Node for your project </h2> <p>Open your project folder and run:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>asdf <span class="nb">install</span> </code></pre> </div> <p>Ready to go.</p> <p>When you open this folder again, <code>asdf</code> will set this version automatically.</p> <h1> Further Reading </h1> <p>ASDF has a lot of plugins to install and manage versions of many tools, check out <a href="proxy.php?url=https://github.com/asdf-vm/asdf-plugins" rel="noopener noreferrer">Central plugin repository for asdf</a></p> <p>Probably you want to use one of this plugins after installing Node:</p> <ul> <li> <a href="proxy.php?url=https://github.com/twuni/asdf-yarn" rel="noopener noreferrer">yarn</a> (yarn v1 only)</li> <li><a href="proxy.php?url=https://github.com/jonathanmorley/asdf-pnpm" rel="noopener noreferrer">pnpm</a></li> </ul> nvm asdf node How to Mock an API with random data from NodeJS Даниил Пронин Mon, 04 Apr 2022 05:58:44 +0000 https://dev.to/grawl/how-to-mock-an-api-with-random-data-from-nodejs-1j91 https://dev.to/grawl/how-to-mock-an-api-with-random-data-from-nodejs-1j91 <p>As a frontend developer, you often need data from an API. But sometimes the backend hasn't been set up by your team. In order for you to continue and mock your data, it's a good idea to not store your data structure on memory.</p> <p>It's a good idea to start as soon as possible to talk with an external API where your data comes from. In this tutorial, I want to go through a minimal setup for mocking your data. After this, you should be able to extend it with your own data as needed.</p> <h2> Dependencies </h2> <p>In order to work with Node you need to have it installed on your machine. For the mac users I highly recommend to install it with <a href="proxy.php?url=https://github.com/creationix/nvm#installation-and-update" rel="noopener noreferrer">NVM</a>, because it will make it easier to update NodeJS in the future. (There is also a <a href="proxy.php?url=https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows" rel="noopener noreferrer">version for Windows</a>).</p> <p>Create a new folder to start for this project. Run <code>npm init -y</code> to initialize the folder with Node and it will create automaticly a package.json for you.</p> <p>In order to create the mockserver we need 2 npm dependencies. <a href="proxy.php?url=https://www.npmjs.com/package/json-server" rel="noopener noreferrer"><code>json-server</code></a> and <a href="proxy.php?url=https://www.npmjs.com/package/casual" rel="noopener noreferrer"><code>casual</code></a> so we run <code>npm install json-server casual --save-dev</code> in our project.</p> <h2> Base for the mock-server </h2> <p>Create a <code>index.js</code> and paste this code in it.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">jsonServer</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">json-server</span><span class="dl">'</span><span class="p">)</span> <span class="kd">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="nx">jsonServer</span><span class="p">.</span><span class="nf">create</span><span class="p">()</span> <span class="kd">const</span> <span class="nx">middlewares</span> <span class="o">=</span> <span class="nx">jsonServer</span><span class="p">.</span><span class="nf">defaults</span><span class="p">()</span> <span class="kd">const</span> <span class="nx">port</span> <span class="o">=</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">PORT</span> <span class="o">||</span> <span class="mi">3000</span> <span class="nx">server</span><span class="p">.</span><span class="nf">use</span><span class="p">(</span><span class="nx">jsonServer</span><span class="p">.</span><span class="nx">bodyParser</span><span class="p">)</span> <span class="nx">server</span><span class="p">.</span><span class="nf">use</span><span class="p">(</span><span class="nx">middlewares</span><span class="p">)</span> <span class="nx">server</span><span class="p">.</span><span class="nf">listen</span><span class="p">(</span><span class="nx">port</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">JSON Server is running</span><span class="dl">'</span><span class="p">)</span> <span class="p">})</span> </code></pre> </div> <p>We include the <code>json-server</code> in order to use it. Then we create a server instance in the <code>const server</code>. With the middlewares we can set a few options like path to static files, CORS and few more. But here we just use it without and specific options.</p> <p>The port is very important. If you want this to run on a server it will first search if there is any default port set for a Node server, otherwise it will pick port <code>3000</code>.</p> <p>We include the bodyParser and middleswarses by using <code>server.use()</code>. And after that we do a console log so you know the mock-server is running.</p> <h2> Generate data for 100 users </h2> <p>Create a folder <code>/users</code> and create a <code>index.js</code> in it.</p> <p>First include the npm package casual in order to use it.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">casual</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">casual</span><span class="dl">'</span><span class="p">)</span> </code></pre> </div> <p>For specific language, if you don't want the english default:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">casual</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">casual</span><span class="dl">'</span><span class="p">).</span><span class="nx">nl_NL</span> </code></pre> </div> <p>Than below it we need to export a module in order for use it in de index.js in the root later.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">casual</span><span class="p">.</span><span class="nf">define</span><span class="p">(</span><span class="dl">'</span><span class="s1">user</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="p">{</span> <span class="na">name</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">first_name</span><span class="p">,</span> <span class="na">surname</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">last_name</span><span class="p">,</span> <span class="na">address</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">street</span><span class="p">,</span> <span class="na">phone</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">phone</span><span class="p">,</span> <span class="na">email</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">email</span><span class="p">,</span> <span class="na">postalCode</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">zip</span><span class="p">,</span> <span class="na">city</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">city</span><span class="p">,</span> <span class="na">number</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">building_number</span><span class="p">,</span> <span class="na">id</span><span class="p">:</span> <span class="nx">casual</span><span class="p">.</span><span class="nx">uuid</span><span class="p">,</span> <span class="p">}</span> <span class="p">})</span> <span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{</span> <span class="na">users</span><span class="p">:</span> <span class="p">[],</span> <span class="p">}</span> <span class="c1">// Create 100 users</span> <span class="k">for </span><span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="nx">data</span><span class="p">.</span><span class="nx">users</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="nx">casual</span><span class="p">.</span><span class="nx">user</span><span class="p">)</span> <span class="p">}</span> <span class="k">return</span> <span class="nx">data</span> <span class="p">}</span> </code></pre> </div> <p>With <code>casual.define</code> we define a object with a type <code>'user'</code>. So in order to create data for 100 users in 1 go, we create a for loop that will run 100 times and pushes a user in the user array in our data object.</p> <p>After that we return the whole object so we can use that in the root <code>index.js</code>.</p> <h2> Create a /user endpoint </h2> <p>In order to get the data for 100 users, we need to create an endpoint for the mock-server. Paste the code below in the root <code>index.js</code>, before the <code>server.listen()</code> function.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="nx">server</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/users</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">response</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="k">if </span><span class="p">(</span><span class="nx">request</span><span class="p">.</span><span class="nx">method</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">GET</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">users</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./users/index</span><span class="dl">'</span><span class="p">)</span> <span class="nx">response</span><span class="p">.</span><span class="nf">status</span><span class="p">(</span><span class="mi">200</span><span class="p">).</span><span class="nf">jsonp</span><span class="p">(</span><span class="nf">users</span><span class="p">())</span> <span class="p">}</span> <span class="p">})</span> </code></pre> </div> <p>In this case we use <code>server.get()</code> for a get request. But we also could choose <code>'post'</code>, <code>'put'</code>, <code>'delete'</code> and so on.</p> <h2> Run the mock-server </h2> <p>Now we are able to run that mock-server and get the data inside our frontend application.</p> <p>Run <code>node index.js</code> inside the root folder of the project. Visit <a href="proxy.php?url=http://localhost:3000/users" rel="noopener noreferrer">localhost:3000/users</a> and you will see 100 users in the <code>user</code> array.</p> <p>I hope this tutorial formed the base for you to generate more random data and expand your mock server. If you have any questions, please let me know in the comments.</p> <p>Inside we check if the request was a <code>'GET'</code> request. If so, we require our users script and call the function inside the response so you will see the array of random generate users.</p> <blockquote> <p>Source: <a href="proxy.php?url=https://mrfrontend.org/2019/05/how-to-mock-an-API-with-random-data-from-NodeJS" rel="noopener noreferrer">https://mrfrontend.org/2019/05/how-to-mock-an-API-with-random-data-from-NodeJS</a></p> <p>Source: <a href="proxy.php?url=https://dev.to/mrfrontend/how-to-mock-an-api-with-random-data-from-nodejs-dda">https://dev.to/mrfrontend/how-to-mock-an-api-with-random-data-from-nodejs-dda</a></p> <p>Source: <a href="proxy.php?url=https://medium.com/mr-frontend-community/build-a-nodejs-mock-server-api-with-random-data-86303db9156a" rel="noopener noreferrer">https://medium.com/mr-frontend-community/build-a-nodejs-mock-server-api-with-random-data-86303db9156a</a></p> </blockquote> javascript node Running Webpack Dev Server with HTTPS on developer machine using MKCERT Даниил Пронин Mon, 04 Apr 2022 05:51:23 +0000 https://dev.to/grawl/running-webpack-dev-server-with-https-on-developer-machine-using-mkcert-25ol https://dev.to/grawl/running-webpack-dev-server-with-https-on-developer-machine-using-mkcert-25ol <p>1) Add local domain to <code>/etc/hosts</code>:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>127.0.0.1 my-project.dev </code></pre> </div> <p>2) Install <a href="proxy.php?url=https://mkcert.dev" rel="noopener noreferrer">mkcert</a><br> 3) Create certificate for this domain:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>➜ mkcert my-project.dev Created a new certificate valid <span class="k">for </span>the following names 📜 - <span class="s2">"my-project.dev"</span> The certificate is at <span class="s2">"./my-project.dev.pem"</span> and the key at <span class="s2">"./my-project.dev-key.pem"</span> ✅ </code></pre> </div> <p>4) Copy certificate <code>.dev.pem</code> and the key <code>.dev-key.pem</code> to project folder:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cp </span>my-project.dev.pem path/to/my-project <span class="nb">cp </span>my-project.dev-key.pem path/to/my-project </code></pre> </div> <p>5) Add HTTPS options to Webpack Dev Server config:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="nx">devServer</span><span class="p">:</span> <span class="p">{</span> <span class="nl">host</span><span class="p">:</span> <span class="dl">'</span><span class="s1">my-project.dev</span><span class="dl">'</span><span class="p">,</span> <span class="nx">https</span><span class="p">:</span> <span class="p">{</span> <span class="nl">key</span><span class="p">:</span> <span class="nx">fs</span><span class="p">.</span><span class="nf">readFileSync</span><span class="p">(</span><span class="dl">'</span><span class="s1">./my-project.dev-key.pem</span><span class="dl">'</span><span class="p">),</span> <span class="nx">cert</span><span class="p">:</span> <span class="nx">fs</span><span class="p">.</span><span class="nf">readFileSync</span><span class="p">(</span><span class="dl">'</span><span class="s1">./my-project.dev.pem</span><span class="dl">'</span><span class="p">),</span> <span class="p">}</span> <span class="p">},</span> </code></pre> </div> <blockquote> <p>Tested with:</p> <ul> <li><code>webpack 4.28.4</code></li> <li><code>webpack-dev-server 3.2.1</code></li> <li><code>@vue/cli-service 3.5.3</code></li> <li> <code>mkcert 1.3.0</code> from Homebrew</li> <li><code>macOS Mojave 10.14.6 (18G84)</code></li> </ul> </blockquote> webpack https mkcert Working with Docker and other unix-things on Windows like on macOS or Linux Даниил Пронин Fri, 29 Jan 2021 04:14:38 +0000 https://dev.to/grawl/working-with-docker-and-other-unix-things-on-windows-like-on-macos-or-linux-4o6p https://dev.to/grawl/working-with-docker-and-other-unix-things-on-windows-like-on-macos-or-linux-4o6p <ol> <li><a href="proxy.php?url=https://docs.microsoft.com/en-us/windows/wsl/install-win10" rel="noopener noreferrer">Install WSL 2</a></li> <li><a href="proxy.php?url=https://docs.microsoft.com/en-us/windows/wsl/install-win10#step-6---install-your-linux-distribution-of-choice" rel="noopener noreferrer">Install Ubuntu (or other distro) into WSL</a></li> <li>Place your project files in Linux inside WSL using path like <code>\\wsl$\Ubuntu\home\username\Work</code>. You can access them from using Explorer since it's network location for Windows. Just Enter <code>\\wsl$\</code> into location bar and you will see available WSL locations. <img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fju0dml5w0ablmza0kw5w.png" alt="Windows Explorer location autocomplete hints for available WSL locations" width="800" height="443"> </li> <li>Open it in JetBrains IDE <img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F82brbmsbo0ziizo3fikn.png" alt="JejtBrains IDE Open dialog recognizing Linux filed installed in WSL" width="800" height="909"> </li> <li>Install <a href="proxy.php?url=https://www.docker.com/products/docker-desktop" rel="noopener noreferrer">Docker Desktop for Windows</a> </li> <li>Enable WSL 2 support in Docker Dashboard Settings <img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxc1f9awd4bwuq0mfnxj3.png" alt="Docker Dashboard Settings - Resources - WSL Integration" width="800" height="460"> </li> <li>Open WSL Command Line, go to project folder and initialize Docker configuration. For example: <code>docker-compose up -d</code>.</li> <li>Now you can see Docker Desktop give you access to containers you just build. <img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxlbsf1df8x872xmwolfs.png" alt="Docker Dashboard recognizing containers built in Linux installed in WSL" width="800" height="460"> </li> <li>Now you can work with containers into JetBrains IDE Services pane, connecting to Docker daemon using "Docker for Windows" option. <img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4ms07iq7g53m89zf96nw.png" alt="JetBrains IDE - connecting to Docker daemon using " width="800" height="891"> <img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc6gwb8j62jgd0k8arvzg.png" alt="Access to WSL Docker from JetBrains IDE Services pane" width="800" height="502"> </li> </ol> <p>TIP after installing Docker Desktop, you can notice you can open Docker frontend in browser, but not frontend from WSL (like <code>npm run start</code>). To fix that, create <a href="proxy.php?url=https://docs.microsoft.com/en-us/windows/wsl/wsl-config#configure-global-options-with-wslconfig" rel="noopener noreferrer"><code>.wslconfig</code> file</a> in your home folder (<code>C:\Users\username</code>) and fill it:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>[wsl2] memory=4GB swap=0 localhostForwarding=true </code></pre> </div> <p>The key you want to change is <code>localhostForwarding</code>.</p> <p>Found it <a href="proxy.php?url=https://github.com/microsoft/WSL/discussions/2471#discussioncomment-113621" rel="noopener noreferrer">here</a>.</p> windows wsl docker jetbrains How to start map with HEV suit on? Даниил Пронин Sun, 20 Jan 2019 11:26:44 +0000 https://dev.to/grawl/how-to-start-map-with-hev-suit-on-2nje https://dev.to/grawl/how-to-start-map-with-hev-suit-on-2nje <blockquote> <p>Quick guide using Hammer Editor 4.1, Build 6412, Source SDK Base 2013 Singleplayer [upcoming]</p> </blockquote> <p>If you just put <code>info_player_start</code> and start map, you will have no the HEV suit: you cannot run, you have not crosshair, no flashlight, and so on. It's good if you want to give HEV suit to player after map is started, but you may want to start map with a battle.</p> <p>The easiest and obvious way to do this is put <code>item_suit</code> entity right over the <code>info_player_start</code> entity, but you will start game with "logon sound" and hands animation, when Freeman takes HEV suit in the first time in Isaac Kleiner lab in City 17.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5q8hv28plnfi3eeylvwx.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5q8hv28plnfi3eeylvwx.png" alt="item_suit right over info_player_start" width="800" height="425"></a></p> <blockquote> <p>crook lvl 1</p> </blockquote> <p>If you want to start map without hands animation and "logon sound", here's a short guide:</p> <ol> <li>Create entity: <code>point_servercommand</code> </li> <li>Name: give it any name, <code>command</code> for example</li> <li>Create <code>logic_auto</code> entity</li> <li>On Outputs tab, add new with button in bottom of the window</li> <li>My output named: <code>OnMapSpawn</code> </li> <li>Targets entities named: name of <code>point_servercommand</code> entity you created before</li> <li>Via this input: <code>Command</code> </li> <li>With a parameter override of: <code>give item_suit</code> </li> </ol> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffee3qrlqbdrybijuszkt.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffee3qrlqbdrybijuszkt.png" alt="info_player_start point_servercommand logic_auto" width="800" height="530"></a></p> <blockquote> <p>lvl 35 boss</p> </blockquote> <p>In short, we create a trigger that runs when map is started, and it run console command to get a HEV. You can try type <code>give item_suit</code> in game console and will have the same.</p> sourcesdk hammereditor valvehammereditor halflife2