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

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

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

Сегодня расскажем об опыте миграции с npm на pnpm на одном из проектов и преимуществах такого решения.

pnpm отличается от пакетных менеджеров npm и yarn двумя ключевыми преимуществами — скоростью работы и безопасностью.

Скорость установки пакетов с pnpm значительно выше, чем в npm и yarn. Это достигается за счет использования специальных hard links, с помощью которых один и тот же npm-пакет не копируется многократно, а извлекается из кэша, если он был ранее загружен. Также pnpm способен устанавливать несколько пакетов параллельно, что отражается на скорости установки.

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

Проект должен был работать в docker-окружении, поэтому задачу с внедрением pnpm с помощью docker мы решили следующим образом:

Собрали образ с помощью Dockerfile. За основу взяли Node.js 18 версию alpine

FROM node:18.16-alpine3.18

# Install pnpm
RUN apk add curl \
&& curl -fsSL "https://github.com/pnpm/pnpm/releases/download/v8.6.1/pnpm-linuxstatic-x64" -o /bin/pnpm; chmod +x /bin/pnpm;

Собрали образ с именем Node.js:18-pnpm-8.6.1, который загрузили в свой gitlab registry

Подготовили docker-compose файл для запуска frontend-приложения

services:
# Nextjs applicaton container
app:
image: gitlab.com/images/nodejs:18-pnpm-8.6.1
logging:
driver: 'json-file'
options:
max-file: '2'
max-size: '5m'
container_name: app
restart: always
environment:
PORT: 3000
HOST_URL: "${HOST_URL}"
command: [ "pnpm", "start" ]
working_dir: "/app"
volumes:
- ./../../src:/app:rw
networks:
- network_name

Пакетный менеджер pnpm может быть особенно полезен разработчикам JavaScript или TypeScript проектов. В нашем случае его использование помогло значительно ускорить установку пакетов и обеспечить безопасность выполнения кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2273🔥2👏1🤯1
Всем привет!

Хотим поделиться с вами древней JS мудростью. Если кто-то вам скажет, что классы — это «синтаксический сахар» для функций-конструкторов, то смело опровергайте это заявление, потому что у вас есть как минимум 3 веские причины утверждать обратное.

Сегодня рассмотрим первую из них.

↪️ При создании объекта через класс его внутренний флаг [[isClassConstructor]] будет равен true, в отличие от создания через функцию-конструктор. Это означает, что конструктор, вызванный как обычная функция, немедленно выбросит ошибку. Другими словами, конструктор класса не является классическим функциональным объектом.

➡️ В целом, этот пункт не столько про экземпляры объектов, сколько про сравнение конструкторов. Но важно понимать, что «синтаксический сахар» подразумевает изменение синтаксиса без изменения функционала, а здесь мы наблюдаем и то, и другое.

function UserFn(name, age) {
this.name = name;
this.age = age;
}


class UserClass {
constructor(name, age) {
this.name = name;
this.age = age;
}
}


console.log(UserFn('John', 25)) // выполняется

console.log(UserClass('John', 25)) // Error: Class constructor UserClass cannot be invoked without "new"

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

➡️ Остальные причины разберем в следующих постах, не пропустите!

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥286👍52😁2
Привет, друзья!

В пятницу мы писали про то, что классы — это не «синтаксический сахар» для функций-конструкторов и назвали первую причину, почему это так.

Сегодня разбираем вторую причину.

Методы класса не являются его свойствами, а значит, не могут быть использованы как ключи в цикле for-in.

function UserFn(name, age) {
this.name = name;
this.age = age;

return {
name,
age,
greet() {
console.log('Hi!');
},
};
}

class UserClass {
constructor(name, age) {
this.name = name;
this.age = age;
}

greet() {
console.log('Hi!');
}
}

const UserFromFunction = new UserFn('John', 25);

const UserFromClass = new UserClass('John', 25);

for (const key in UserFromFunction) {
console.log(key); // name, age, greet
}

for (const key in UserFromClass) {
console.log(key); // name, age
}

Также мы можем это проверить с помощью метода Object.getOwnPropertyDenoscriptor, который возвращает информацию обо всех дескрипторах свойства объекта. У метода класса их нет, а это доказывает, что метод класса технически не является его свойством.

console.log(Object.getOwnPropertyDenoscriptor(UserFromFunction, 'greet')) // Объект с дескрипторами
console.log(Object.getOwnPropertyDenoscriptor(UserFromClass, 'greet')) // undefined

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

Осталось разобрать последнюю особенность классов — следите за постами в канале 🕓.

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥26👍711
Всем привет!

Завершаем тему с классами. Итак, третья причина, по которой классы нельзя назвать «синтаксическим сахаром».

📌 Код класса всегда выполняется в strict mode, и нет ни одного способа выполнить его иначе, в отличие от функции-конструктора. Как мы можем доказать это?

Первое, что приходит на ум — вспомнить, что this в строгом режиме всегда равен undefined. Поэтому нам необходимо использовать его так, чтобы он не являлся методом объекта. Для этого достаточно указать его внутри колбэка какой-либо функции, которая будет внутри метода. Оператор цикла forEach — отличный помощник в нашем примере.

function UserFn(name, age) {
this.name = name;
this.age = age;

return {
name,
age,
greet() {
[0].forEach(function () {
console.log(this);
});
},
};
}

class UserClass {
constructor(name, age) {
this.name = name;
this.age = age;
}

greet() {
[0].forEach(function () {
console.log(this);
});
}
}

const UserFromFunction = new UserFn('John', 25);

const UserFromClass = new UserClass('John', 25);

console.log(UserFromFunction.greet()); // object Window

console.log(UserFromClass.greet()); // undefined

Теперь вы знаете чуть больше о классах — эта информация пригодится вам на пути становления JS-сэнсэями.

Если остались вопросы или просто хотите поболтать о сахаре, пишите в комментарии⬇️.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥22👍62🤩2
Всем привет!

Сегодня поговорим о важном аспекте разработки приложений — обеспечении взаимодействия между backend- и frontend-приложениями в режиме реального времени. Речь пойдет о технологии Centrifugo.

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

Читать про Centrifugo

Centrifugo — ценный инструмент при разработке современных приложений. Главное, не забывать про принцип YAGNI (You Ain't Gonna Need It) и использовать его с умом.

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
12🔥8👍21
Друзья, привет!

Сегодня предлагаем немного пошевелить 🧠 и проверить свои знания. Интересно, кто решит задачку первым?)

Пишите свои варианты ответа в комментарии.

Ниже правильный ответ👇🏻
Только давайте по-честному! Пишем свой вариант, потом проверяем себя.

Правильный ответ — false

1. typeof [] возвращает строку "object"
2. "object" instanceof Array — false, так как строка не инстанс массива.

@chulakov_dev
👍15🔥6🤔1🤯1
Всем привет!

CSS стремительно развивается, появляются новые возможности визуального оформления страниц.

Сегодня давайте обсудим плюсы и минусы разных инструментов для работы со стилями и выберем самый удобный.

Читать о стилях

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥621🤔1
Привет, друзья!

Что такое временная мертвая зона, и какое отношение она имеет к разработке? ☠️ Давайте разбираться!

Временная мертвая зона, или Temporal Dead Zone (TDZ), — это временной промежуток, в течение которого let- и const-переменные не могут быть использованы. Это происходит, когда переменная была инициализирована после попытки обращения к ней.

Как и hoisting, такого понятия, как TDZ, в спецификации ECMAScript не существует. Все это является теоретической базой для понимания того, как работает доступ к определенным сущностям и что тем более ничего не «поднимается наверх», как многие любят об этом рассказывать, упоминая hoisting.

Итак, var-переменные, а также Function Declaration и Generator Declaration доступны из любой точки кода, вне зависимости от их объявления. В отличие от них, let- и const-переменные ведут себя иначе. При попытке обратиться к ним до их инициализации рантайм выбросит ошибку, так как эти переменные находятся во временной мертвой зоне. То же самое касается Function Expression и Generator Expression.

При разработке очень важно понимать теорию о TDZ, так как она позволяет определять, в каких случаях можно или нельзя обращаться к переменным. Более того, выброс ошибки в случае обращения к переменным, когда они находятся в TDZ, может предостеречь нас от ошибок проектирования и нестабильности скрипта/модуля. Напомним, что var-переменная доступна сразу со значением undefined, пока ей не будет присвоено какое-либо значение.

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👍82
Всем привет!

Подготовили для вас очередную задачку ⚙️ Есть тут те, кто разбирается в Event Loop?

console.log('start');

const promise1 = Promise.resolve().then(() => {
console.log('promise1');
const timer2 = setTimeout(() => {
console.log('timer2');
}, 0);
});

const timer1 = setTimeout(() => {
console.log('timer1');
const promise2 = Promise.resolve().then(() => {
console.log('promise2');
});
}, 0);

console.log('end');

Ниже вопрос и варианты ответа👇🏻
Завтра пошагово разберем правильный!
🔥11👍71
Привет, друзья!

Итак, правильный ответ на вчерашнюю задачу — вариант №1: start -> end -> promise1 -> timer1 -> promise2 -> timer2

Объясняем, почему.

1. Выполняем синхронную задачу console.log("start").

2. Далее идет промис. Это асинхронная операция, и поэтому она помещается в стек микротасок. Она исполнится, как только вернется со статусом fulfilled/rejected.

3. Далее — setTimeout. Он выходит из Main Thread, поэтому также не выполняется.

4. Выполняем синхронную задачу console.log("end"), т.к. в предыдущем тике микротаска еще не была исполнена.

5. В этом же тике у нас готова микротаска. Выводим promise1 и выпускаем setTimeout из основного потока.

6. У нас вернулся timer1. В нем выводится такая же строка и запускается выполнение промиса. Тут очень важный момент — в текущем тике у нас нет синхронных задач (timer2 еще гуляет вне потока), а значит, можно сразу выполнить микротаску с выводом promise2.

7. Возвращается timer2 и выводится в консоль.

🤔 Если у вас остались вопросы — задавайте, будем разбираться вместе.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥42👌2
Наши эксперты всегда с радостью делятся знаниями и опытом — не только в профессиональной сфере, но и в построении внутренних процессов Студии.

Не так давно Team Lead отдела разработки Студии Альберт Рыбалко рассказал участникам People&&Culture Meetup о преимуществах нашего подхода к аттестации сотрудников.

На митапе обсудили с аудиторией:
⚫️зачем нужна аттестация, что она дает сотрудникам и бизнесу;
⚫️как мы усовершенствовали процесс аттестации, какие изменения внедрили;
⚫️какие результаты в итоге получили (спойлер: меньше стресса — больше пользы)

➡️ Смотреть запись

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥29👍73😍2
Привет, друзья!

В этом посте мы хотим развеять несколько мифов относительно Event Loop и рассказать про некоторые его особенности.

Event Loop — обычный агент, который не является частью ядра V8. Тот цикл событий, который вы привыкли видеть, — Event Loop спецификации HTML5, который, помимо JS, работает также и с DOM, и с Web API. В конце концов, у Node.js реализован свой Event Loop, который отличается от клиентского.

Циклов событий может быть несколько. Когда мы создаем Web Worker, внутри него находится такой же агент, который тоже выполняет код. Не путайте воркеры с многопоточностью.

Код может выходить из Main Thread, даже если вы не создавали воркер. Например, функции setTimeout или setInterval. Но стоит помнить, что любая функция, которая осуществляет подобное, является частью Web API, включая воркеры, так как ни одна сущность, реализуемая ядром V8, не дает сделать ничего подобного.

А какие особенности Event Loop знаете вы?

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍52
Всем привет!

В новой статье на Хабре мы углубились в тему Kotlin Coroutines — разобрали их основные концепции, способы работы с асинхронными операциями, управление потоком выполнения, обработку ошибок и исключений, а также многое другое. Получился очень полезный лонгрид.

Приятного чтения.
🔥15👍3😱2
Всем привет!

Как правильно ответить на вопрос «Что такое чистая функция?», если различные источники дают разные трактовки? Кажется, мы нашли лучшее определение этому понятию. Следите за ходом мысли.

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

Почему только по одной точке на вход и выход?

Абсолютно любой другой вход в функцию — это использование внешних переменных, функций и т.д. — побочное действие.
Абсолютно любой другой выход из функции — присвоение значений внешним переменным, операции ввода/вывода, HTTP-запросы — побочное действие.

В итоге мы имеем следующее определение:

Чистая функция — это функция, которая имеет только одну ординарную точку входа (ее аргументы) и одну ординарную точку выхода (оператор return).

+1 понятие в вашу копилку.

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍21
Привет, друзья!

На прошлой неделе многие из вас справились с задачей по Event Loop 💪🏼 Сможете ли вы правильно ответить на сегодняшний вопрос?

Он ниже вместе с вариантами ответа👇🏻 Выбирайте.
👍102🤔1