Backend Ready | IT
7.95K subscribers
1.25K photos
94 videos
6 files
1.02K links
По всем вопросам: @AdilNow
Download Telegram
🌐 Модуль wasi — запуск WebAssembly за пределами браузера

Технология WebAssembly (Wasm) изначально создавалась для того, чтобы запускать тяжелый скомпилированный код (на C, C++, Rust, Go) прямо в браузере на околонативной скорости. Модуль wasi (WebAssembly System Interface) расширяет эти возможности, позволяя Wasm-модулям выходить за рамки песочницы браузера и безопасно взаимодействовать с операционной системой: читать файлы, работать с сетью и системным временем.

wasi — мост между бинарным кодом и ОС

new WASI()
wasiImport
start()
initialize()

Что такое WASI? — Это стандартизованный API, который предоставляет коду WebAssembly доступ к системным вызовам (системным функциям ОС). Без WASI бинарный файл .wasm внутри Node.js изолирован и не может сделать даже элементарный console.log или прочитать файл с диска.

Изоляция и Безопасность — Главная фишка WASI — это безопасность на основе разрешений (capability-based security). Вы не просто даете Wasm-модулю доступ к файловой системе, а жестко прописываете в конфигурации (свойство preopens), к каким конкретно папкам на вашем компьютере этот модуль имеет доступ. К остальным директориям он дотянуться не сможет при всём желании.

const fs = require('fs');
const { WASI } = require('wasi');

const wasi = new WASI({
version: 'preview1',
args: process.argv,
env: process.env,
// Разрешаем модулю читать и писать только в локальную папку /sandbox
preopens: {
'/sandbox': './my-local-sandbox-folder'
}
});

(async () => {
// Загружаем скомпилированный Wasm-файл (например, написанный на Rust)
const wasmBuffer = fs.readFileSync('./optimized_algorithm.wasm');
const wasmModule = await WebAssembly.compile(wasmBuffer);

// Передаем системные интерфейсы WASI внутрь Wasm-модуля
const instance = await WebAssembly.instantiate(wasmModule, {
wasi_snapshot_preview1: wasi.wasiImport
});

// Запускаем исполнение
wasi.start(instance);
})();



Зачем это нужно веб-разработчику? — Чтобы переиспользовать сложную бизнес-логику или алгоритмы, написанные на других языках, без потери производительности. С помощью WASI можно запускать внутри Node.js готовые бинарные утилиты (например, парсеры видео, криптографические библиотеки или игровые движки), написанные на C++ или Rust, не боясь, что они сломают или заразят вашу основную систему.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
3
🛠️ Модуль util — швейцарский нож для разработчика

Когда стандартных возможностей JavaScript не хватает для решения повседневных задач (дебаг объектов, превращение колбэков в промисы или проверка типов), на помощь приходит встроенный модуль util. Это набор служебных утилит, которые делают жизнь разработчика намного проще.

util — вспомогательные инструменты и полифилы

promisify()
inspect()
format()
types

promisify() — легендарный метод, который берет старую функцию, работающую на колбэках (callback-style), и превращает её в современную функцию, возвращающую Promise. Это позволяет использовать async/await со старыми библиотеками.

const util = require('util');
const fs = require('fs');

// Превращаем fs.readFile в функцию на промисах
const readFile = util.promisify(fs.readFile);

async function getConfig() {
try {
const data = await readFile('./config.json', 'utf8');
console.log(data);
} catch (err) {
console.error('Ошибка чтения:', err);
}
}



inspect() — возвращает строковое представление объекта. В отличие от JSON.stringify(), этот метод умеет красиво подсвечивать синтаксис в консоли, не ломается на циклических ссылках (circular references) и позволяет настраивать глубину отображения вложенных объектов.

const complexObj = { a: 1, b: { c: { d: 'глубоко' } } };

console.log(util.inspect(complexObj, { depth: null, colors: true }));



format() — форматирует строку в стиле языка C (используя спецификаторы вроде %s для строк, %d для чисел). На базе этого метода построена привычная нам функция console.log().

const greeting = util.format('Привет, %s! У тебя %d новых сообщений.', 'Алексей', 5);
console.log(greeting); // Привет, Алексей! У тебя 5 новых сообщений.



util.types — встроенный валидатор типов данных, который заглядывает глубже обычного оператора typeof. С его помощью можно со 100% уверенностью проверить, является ли объект регулярным выражением, датой, Async-функцией или, например, Map/Set.

const types = require('util').types;

console.log(types.isRegExp(/abc/)); // true
console.log(types.isDate(new Date())); // true
console.log(types.isAsyncFunction(async () => {})); // true

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Модуль zlib — сжатие данных и архивация

Когда сервер отправляет пользователю огромные JSON-ответы, HTML-страницы или текстовые логи, это сильно нагружает сеть. Встроенный модуль zlib позволяет сжимать данные на лету с использованием популярных алгоритмов Gzip, Deflate и Brotli. Это уменьшает размер передаваемых файлов в несколько раз, ускоряя загрузку приложений и экономя трафик.

zlib — оптимизация трафика через сжатие

createGzip() / createGunzip()
createBrotliCompress() / createBrotliDecompress()
gzip() / gunzip()

Сжатие потоков (Streams) — Поскольку zlib полностью интегрирован со стримами Node.js, вы можете сжимать файлы или сетевые ответы буквально в одну строчку кода через .pipe(), не загружая весь файл в оперативную память.

const zlib = require('zlib');
const fs = require('fs');

const source = fs.createReadStream('large_log.txt');
const destination = fs.createWriteStream('large_log.txt.gz');
const gzip = zlib.createGzip();

// Читаем -> Сжимаем в Gzip -> Записываем на диск
source.pipe(gzip).pipe(destination);



Brotli против Gzip — Модуль поддерживает алгоритм Brotli (createBrotliCompress), который был разработан Google. Он сжимает текстовые данные (HTML, JS, CSS) на 15–20% эффективнее, чем старый добрый Gzip. В современном вебе это стандарт де-факто для отдачи статики.

Асинхронная работа с буферами — Если вам нужно сжать не поток, а конкретную строку или буфер в памяти (например, перед сохранением в базу данных), у модуля есть простые методы-колбэки (или их promisify-версии).

const { gzip, gunzip } = require('zlib');
const { promisify } = require('util');
const doGzip = promisify(gzip);

const input = 'Очень важная строка, которую нужно сильно сжать';
const compressedBuffer = await doGzip(input);

console.log('Размер до:', Buffer.byteLength(input), 'байт');
console.log('Размер после:', compressedBuffer.length, 'байт');



HTTP-сжатие — Именно с помощью zlib на чистом Node.js реализуется обработка заголовка Accept-Encoding: gzip, br. Сервер проверяет, что поддерживает браузер клиента, сжимает ответ и добавляет заголовок Content-Encoding.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Айтишники ловите сборник бесплатных курсов, полезных инструментов и книг

Проект «TERMINAL» стал крупнейшей библиотекой бесплатного образования. В одном канале собраны курсы, книги, полезные инструменты и практические тренажёры для всех разработчиков

🎓 Практические курсы и задания

🪽 Книги и статьи известных авторов

😮‍💨 Полезные инструменты и ресурсы

🌟 IT-новости и инсайды

Обучение по всем направлениям: SQL, Python, Frontend, PHP, C++, Golang, GIT, Linux, QA, Java, кибербезопасность и др.

Ценишь знания, подпишись: Terminal_tg
Please open Telegram to view this post
VIEW IN TELEGRAM
4
🖥️ Модуль os — информация об операционной системе

Когда твое приложение запускается на сервере, ему часто нужно подстраиваться под окружение. Модуль os предоставляет прямой доступ к операционной системе, позволяя узнать всё о процессоре, оперативной памяти, сетевых интерфейсах и системных папках устройства, на котором выполняется код.

os — аудит железа и системного окружения

cpus()
freemem() / totalmem()
networkInterfaces()
homedir() / tmpdir()

os.cpus() — возвращает массив объектов со сведениями о каждом ядре процессора: модель, скорость (в МГц) и время, проведенное в различных режимах. Это важнейший метод для настройки кластеризации (cluster), чтобы запускать ровно столько копий приложения, сколько ядер есть на сервере.

const os = require('os');
const cores = os.cpus().length;

console.log(`Твой сервер имеет ${cores} логических ядер.`);



Мониторинг памяти (freemem / totalmem) — позволяют в реальном времени оценивать загруженность сервера. totalmem показывает общий объем оперативной памяти в байтах, а freemem — сколько осталось свободно. На базе этих метрик строят системы алертов.

const freeGB = (os.freemem() / 1024 / 1024 / 1024).toFixed(2);
const totalGB = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2);

console.log(`Память: свободно ${freeGB} ГБ из ${totalGB} ГБ`);



os.networkInterfaces() — возвращает детальную информацию о сетевых адаптерах устройства (IP-адреса, MAC-адреса, маски подсети). Полезно, когда нужно программно определить локальный IP-адрес сервера в сети.

Кроссплатформенные пути (homedir / tmpdir) — спасают от ручной проверки системных путей. os.homedir() вернет путь к домашней директории текущего пользователя (C:\Users\... на Windows или /home/... на Linux), а os.tmpdir() — путь к системной временной папке для безопасного сохранения кэша или загружаемых файлов.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
📊 Модуль string_decoder — безопасное декодирование бинарных потоков

При работе с потоками данных (Streams) или буферами (Buffer) файлы и сетевые пакеты прилетают в приложение по частям (чанками) в виде сырых байт. Если текстовый файл сохранен в кодировке UTF-8, то некоторые символы (например, кириллица или эмодзи) могут занимать от 2 до 4 байт. Если чанк оборвется посреди такого многобайтового символа, обычный метод buffer.toString() превратит сломанный стык в нечитаемый знак вопроса ``. Модуль string_decoder решает эту проблему, бережно склеивая разорванные символы.

string_decoder — правильная конвертация байт в текст

new StringDecoder()
write()
end()

Проблема разбитых символов — Если передавать кириллический текст по кусочкам, есть огромный шанс, что один из байтов буквы «При» останется в первом куске, а второй байт уйдет в следующий. Buffer.concat() решает это постфактум, но если вам нужно обрабатывать текст *в процессе* чтения потока, стандартный .toString() выдаст брак.

Как работает StringDecoder — Он создает внутренний буфер для «остатков». Если на конце чанка обнаруживается неполный многобайтовый символ, декодер придерживает его у себя и склеивает с началом следующего чанка, гарантируя идеальный текст без артефактов.

const { StringDecoder } = require('string_decoder');
const decoder = new StringDecoder('utf8');

// Эмодзи 🔥 состоит из 4 байт: [0xf0, 0x9f, 0x94, 0xa5]
const chunk1 = Buffer.from([0xf0, 0x9f]); // Половинка эмодзи
const chunk2 = Buffer.from([0x94, 0xa5, 0x20]); // Вторая половина + пробел

// Обычный chunk1.toString() выдаст кракозябру, но декодер умнее:
console.log(decoder.write(chunk1)); // Выведет пустую строку (ждет продолжения)
console.log(decoder.write(chunk2)); // Выведет: 🔥



Метод end() — Если поток данных завершился, а в буфере декодера все еще лежат какие-то неопознанные байты (например, файл был изначально поврежден), вызов decoder.end() принудительно вернет их в виде символов замены, очистив память.

Зачем это знать? — Этот модуль лежит в основе работы всех текстовых стримов в Node.js (например, fs.createReadStream с указанной кодировкой). Понимание его работы необходимо, если вы пишете собственные кастомные парсеры протоколов, сетевые шлюзы или работаете со сложными бинарными потоками.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🤔 Чем отличается rebase от merge?

В Git команды rebase и merge используются для объединения изменений из разных веток, но делают это по-разному. Основное различие между ними заключается в том, как они сохраняют историю коммитов и как они влияют на структуру репозитория.

🚩Основные отличия

🟠Merge (Слияние)
Объединяет две ветки, создавая новый коммит слияния (merge commit), который имеет две родительских ветки. Сохраняет всю историю коммитов обеих веток без изменений. История ветвления и слияния сохраняется. Если есть конфликты, Git предложит их разрешить перед созданием коммита слияния.
git merge <branch>
git checkout main
git merge feature-branch


🟠Rebase (Перебазирование)
Переносит все коммиты текущей ветки на вершину целевой ветки. Это делает историю линейной, как если бы изменения были сделаны последовательно. Изменяет историю коммитов, создавая новые коммиты для каждого коммита из текущей ветки. История ветвления исчезает. Если есть конфликты, Git предложит их разрешить по мере переноса каждого коммита.
git rebase <branch>
git checkout feature-branch
git rebase main


🚩Плюсы и минусы

🟠Merge
Простота
Процесс слияния прост и понятен.
Сохранение истории
Вся история коммитов сохраняется, включая информацию о ветвлении и слиянии.
Коммиты слияния
Создаются дополнительные коммиты слияния, что может усложнить историю.

🟠Rebase
Чистая история
История линейная и более читабельная.
Упрощение навигации
Проще следить за последовательностью изменений.
Изменение истории
Изменение коммитов может привести к проблемам, если кто-то уже основывается на этих коммитах.
Конфликты
Может потребоваться больше усилий для разрешения конфликтов, особенно если коммитов много.

🚩Когда использовать

🟠Merge
Когда важно сохранить полную историю изменений, включая ветвление и слияние. В крупных командных проектах, где история изменений важна для отслеживания.

🟠Rebase
Когда важно иметь чистую и линейную историю изменений. Для интеграции изменений из основной ветки в текущую рабочую ветку перед отправкой изменений в основную ветку.
1
This media is not supported in your browser
VIEW IN TELEGRAM
🍿 Мультивселенная схлопнулась.
Please open Telegram to view this post
VIEW IN TELEGRAM
🍿 ИИ становится более контекстным: пользователям все реже нужны идеальные промпты

Руководитель группы продукта «Поиск и Рекомендации» Яндекс Маркета Любовь Горбунова считает, что необходимость в предельно точных формулировках снижается: нейросеть все лучше понимает запросы и в перспективе с ней можно будет общаться как с консультантом в магазине — в свободной форме и с уточнениями по ходу диалога.

Еще один тренд — использование ИИ вместе с VR/AR-технологиями. Уже сейчас такие решения улучшают сценарии виртуальной примерки одежды. А в будущем подход может распространиться и на другие категории, например, на «примерку» мебели в интерьере.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🎧 ИИ-музыку почти никто не слушает

В новом исследовании изучили Spotify и выяснили, что 93% нейротреков не набирают даже 1000 прослушиваний.

Авторы называют это music slop. Тысячи композиций заливают пачками в разные жанры, надеясь случайно попасть в рекомендации. Дистрибьюторы почти этому не мешают, а детекторы пока легко обходятся.

А как часто вам попадается в реках нейрохрючево?

Источник
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое миксины?

Это один из способов повторного использования кода в объектно-ориентированном программировании. Они представляют собой классы или функции, которые предоставляют методы для других классов, без необходимости быть основой для этих классов. Миксины позволяют «подмешивать» функциональность в другие классы, обеспечивая гибкость и модульность кода.

🚩Характеристики

🟠Повторное использование кода
Миксины позволяют избежать дублирования кода путем инкапсуляции общих методов и свойств, которые могут быть использованы в различных классах.
🟠Множественное наследование
В языках, поддерживающих множественное наследование (например, Python), миксины могут быть использованы как базовые классы для других классов, предоставляя дополнительные методы и свойства. Это позволяет создавать классы, комбинируя несколько миксинов для расширения функциональности.
🟠Композиция
В языках, где множественное наследование не поддерживается или нежелательно (например, в JavaScript), миксины могут быть применены через композицию, где функциональность миксина добавляется к целевому объекту или классу.
🟠Изоляция поведения
Миксины позволяют изолировать и инкапсулировать определенное поведение или функциональность, что упрощает тестирование и поддержку кода.

🚩Примеры использования

🟠Python
Миксины часто используются через множественное наследование.
class LoggableMixin:
def log(self, message):
print(f"Log: {message}")

class Database(LoggableMixin):
def save(self, data):
self.log("Saving data")
# Код для сохранения данных

db = Database()
db.save({"key": "value"})


🟠JavaScript
Миксины могут быть применены через композицию.
const loggableMixin = {
log(message) {
console.log(`Log: ${message}`);
}
};

class Database {
save(data) {
this.log("Saving data");
// Код для сохранения данных
}
}

Object.assign(Database.prototype, loggableMixin);

const db = new Database();
db.save({ key: 'value' });
2
Forwarded from 👇
This media is not supported in your browser
VIEW IN TELEGRAM
УРВАЛ ДОСТУП К ВПН'У ЗА КОПЕЙКИ 😱

Наконец нашел способ обходить белые списки и остальные ограничения за сущие копейки и с бесплатным доступом‼️

Anyport VPN — не даёт остаться мне без интернета

Забирай бесплатный пробный период:
Please open Telegram to view this post
VIEW IN TELEGRAM
👎2
Избегайте использования CASE в WHERE

Хотя SQL допускает использование выражений CASE внутри WHERE, они часто делают запросы менее читаемыми и усложняют понимание их логики. Логика фильтрации оказывается спрятана внутри условного выражения вместо того, чтобы быть выраженной напрямую через булевы предикаты. Кроме того, оборачивание условий в CASE может затруднить для оптимизатора запросов анализ предиката и эффективное использование индексов. Во многих случаях это делает запрос non-SARGable (Search ARGument Able), то есть база данных не может эффективно использовать индексы для поиска нужных строк.

Вот наивный вариант:

SELECT *
FROM Products
WHERE CASE
WHEN Category = 'Electronics' THEN Price < 500
ELSE Price < 100
END;


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

Лучший способ выразить такую логику, это использовать операторы AND и OR напрямую в условии фильтрации. Явно записанные булевы предикаты делают логику проще для чтения и понимания, потому что условия хорошо видны, а не спрятаны внутри CASE.

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

SELECT *
FROM Products
WHERE Price < 100
OR (Category = 'Electronics' AND Price < 500);