BigInt и работа с числовыми значениями в JavaScript — в шестой серии открытого курса по JS
Это курс от инженеров AvitoTech — вместе с фронтендером Василием Новиковым разбираемся в базовых технологиях веб-разработки в JavaScript.
В новой серии изучаем, как проводить разные операции с помощью BigInt, на какие особенности нужно обращать внимание в полученных результатах, как определить безопасные целые числа и что делать, если числа оказались вне безопасного диапазона.
Всем привет. Тестирую формат постов и, заодно, делюсь подсмотренной идеей трекинга пользователей «без палева», который прямо-таки очень тяжело отловить (если не делать отладку HTTP-запросов) и очень технически сложно заблокировать.
Разработчики [CENSORED], придумали практически безотказный способ отправлять логи, даже если пользователь использует блокировщики. Схема простая:
Случилось событие, которое нужно затрекать.
С помощью JavaScript создаётся кука, имя которой соответствует определённому формату + рандомная строка-суффикс, а в значении содержится urlencoded-набор-параметров-значений.
Любой следующий запрос к сервису содержит эту куку. Сервис в ответе в хэдерах пишет, что куку нужно удалить. Кука отправилась и удалилась, никто ничего не заметил, никаких лишних запросов, трекинг-данные доставлены.
PROFIT.
Я читал много разных новостей про экзотические способы трекинга, но конкретно этот обнаружил самостоятельно. Буду рад, если покормил чью-то паранойю.
Работа с данными в JavaScript — в пятой серии открытого курса по JS
Это новый курс от инженеров AvitoTech — вместе с фронтендером Василием Новиковым разбираемся в базовых технологиях веб-разработки в JavaScript.
В этой серии изучаем проблемные числа, разбираемся с мантиссой, экспонентой и сдвигом, пытаемся понять арифметику стандарта IEEE 754. Знаете, почему 0,1 и 0,2 в сумме не дают 0,3? Смотрите, и всё поймёте!
А если знаете — всё равно смотрите, вспоминать базу всегда полезно!
Страница демонстрирует, как изображение разбивается на блоки 8×8 пикселей, каждый из которых затем подвергается алгоритму дискретного косинусного преобразования. Упрощённо можно сказать, что каждый из блоков математически преобразуется из двумерного изображения в сигнал, а затем представляется как сумма синусоид. Интересно в инструменте Омара то, что он допускает ручное редактирование преобразования каждого из блоков 8×8 пикселей.
Также Омар рекомендует свою статью про алгоритмы сжатия JPEG, в которой он применил схожие инструменты.
Разработчик Мишан Пудель представил открытое локальное приложение в виде клона интерфейса Windows 11 на React.js с некоторыми компонентами ОС, включая работающий браузер Chrome, инструментарий VS Code, игру Emoji Tic-Tac-Toe, клиент Spotify в качестве музыкального проигрывателя и калькулятор.
React.js: для создания интерактивного пользовательского интерфейса.
Tailwind CSS: для стилизации компонентов и создания дескопного окружения.
React Router DOM: для управления навигацией и маршрутизацией в приложении.
Framer Motion: для добавления анимации и переходов.
React Draggable: для создания элементов, которые можно перетаскивать.
Страница входа в ОС: можно ввести что угодно на странице входа, чтобы получить доступ к приложению. Фактические учётные данные не нужны. Щёлкните по значкам на рабочем столе, чтобы открыть различные приложения. Используйте панель задач для переключения между открытыми приложениями. Взаимодействуйте с приложениями, чтобы изучить их функции и возможности.
Установка проекта локально:
Clone the repository: git clone https://github.com/MishanPoudel/Windows11-3.0;
Navigate to the project directory: cd Windows11-3.0;
1. All-in подход. Подключение компонента вместе со стилями или без них. Здесь любой компонент — это самостоятельная единица, которая уже содержит всё нужное. Внутри этого подхода можно выделить два подвида:
Инлайн-стили через Styled Components (возможно, добавить просто подключение стилей внутри компонента). Этот метод позволяет писать стили непосредственно в компоненте. При этом стили изолированы, что уменьшает возможность конфликтов между стилями разных компонентов.
Без добавления стилей (Headless). В этом случае компоненты предоставляют только логику без UI, что позволяет самостоятельно управлять стилями. Для создания подобной библиотеки нужно также ознакомиться с паттерном Compound component.
2. Dependency CSS & Bundle CSS подход. Второй большой подход — когда стили и компонент подключаются по отдельности. В этом случае стили и логика компонента отделены друг от друга.
Dependency CSS: этот способ подключения улучшает модульность и позволяет загружать стили только тогда, когда они действительно необходимы.
Bundle CSS предполагает подключение всех стилей сразу и отдельно — компонента. По сути, в этом случае все стили объединены в общий бандл и импортируются в корне проекта.
Но при написании они схожи, и стили к компоненту подключаются как модули.
В кодовую базу Node.js принятоизменение, добавляющее возможность выполнения файлов с кодом на TypeScript.
Поддержка TypeScript включается при помощи опции "--experimental-strip-types" и сводится к очистке специфичных для данного языка определений типов, то есть преобразованию перед выполнением исходного кода в JavaScript.
Не связанные с описанием типов возможности TypeScript пространства имён, декораторы, свойства параметров и перечисляемые типы (enum) пока не поддерживаются. Протестировать новую опцию можно в ночных сборках Node.js 23.
Для трансляции задействован компилятор SWC (Speedy Web Compiler), написанный на языке Rust. Чтобы не добавлять дополнительные зависимости к Node.js, задействовано представление компилятора swc/wasm-typescript в промежуточном коде WebAssembly и уже применяемое для тех же целей в платформе Deno.
Это изменение добавлено в ответ на просьбы пользователей реализовать возможность запуска кода на TypeScript без установки внешних загрузчиков и дополнительных зависимостей. В проектах Deno и Bun поддержка TypeScript реализована изначально.
Ключевым отличием TypeScript от JavaScript является явное определение типов. Статическая типизация позволяет избежать многих ошибок в процессе разработки, даёт возможность задействовать дополнительные техники оптимизации и упрощает отладку.
В добавленной в Node.js реализации данные возможности TypeScript теряются, в процессе трансляции исходных текстов в JavaScript проверка типов не осуществляется.
Код приложения - здесь, описание - здесь (на англ.).
Отдельное спасибо @SuperCat911 за комменты про importmap - без них бы не получилось юзать OpenAI-библиотеку :)
Кстати, до 4-версии у OpenAI не было браузерной версии API-клиента (только для nodejs). И несмотря на то, что библиотека написана на TS, для браузера они сделали ES-модули, а не UMD-бандл.
Неожиданный факт о JavaScript всплыл, и снова стал актуален, при разработке приложения с генеративными нейросетями.. Оказывается, в языке нет поддержки 64-битных целых. По сути, доступно только 53-бита!
JavaScript Numbers are represented as IEEE 754 double-precision floats. Unfortunately, this means they lose integer precision for values beyond +/- 2^^53.
Факт давно известный, но от того не менее неприятный. Казалось бы, ну ничего страшного -- ведь есть, вроде бы, уже поддержка встроенного объекта BigInt и она добавлена во все современные браузеры.
Но если речь идет о работе с API (как в случае с параметром seed для StableDiffusion, например) и вы хотите использовать весь диапазон (а не его половину, как в automatic1111) -- то вы неизбежно сталкиваетесь с де/сериализацией объектом JSON, который для целочисленных значений использует стандартный тип Number.
И вуаля -- кроме обходного пути с передачей числа в виде строки, решения не видно! Ни на первый, ни на второй взгляд)
Если у кого-то есть идеи как этого избежать, или я что-то недопонял -- буду признателен за комментарий!) Проект давно закончен, но хотелось бы найти "красивое" решение.
Команда react.js во всю готовится к предстоящей конференции и видимо, несмотря на большие сомнения, именно на ней они представят React 19. На сайте уже была опубликована страница релиза.
В релизе всё то, о чём рассказывала команда next.js - action для формы, новые хуки, серверные компоненты и серверные действия, метаданные страницы и предзагрузка ресурсов из коробки. Из нового (или упущенного мной) - для передачи ref больше не нужно использовать forwardRef, обновлённое API контекстов и продвинутая поддержка таблиц стилей.
Вместе с релизом был опубликован и гайд на обновление до 19 версии для библиотек. В гайде можно отметить значительные удаления функционала помеченного в последние годы как устаревший.
Также вчера вышел React 18.3.0, а уже сегодня вышла минорка - React 18.3.1. Это промежуточные релизы, в которых добавили предупреждения о том, что будет помечено как устаревшее или удалено. Так можно подготовить проекты к предстоящему обновлению.
Отображения работают с моделями через посредников, которые трансформируют абстракции предметной области в абстракции отображения и обратно. ViewModel также выступает хранилищем состояния отображения, не связанного с предметной областью.
MVVM
// View
<li class="User_card" model="User_card_model">
<img src={ image } />
<p>{ message }</p>
</li>
// ViewModel
class User_card_model {
user = User.current
get image() {
return this.user.avatar
}
get message() {
return this.user.nickname
}
}
// Model
class User {
avatar: string
nickname: string
static current = new User
}
✅ Отображение может использовать произвольные вьюмодели. ✅ Легко добавлять новые отображения, не меняя ни модели, ни вьюмодели. ✅ Изменение интерфейса модели или отображения требует изменения только лишь вьюмодели. ✅ Одну и ту же вьюмодель можно шарить между несколькими отображениями. ❌ Для отображения разных моделей необходимо дублировать код отображения и вьюмодели. ❌ Трёх слоёв слишком мало на больших масштабах.
Код работы с моделями пишется прямо в отображении.
// View
function Task_list() {
return <ul>{
Task.list.map( task =>
<li><Task_row {task} /></li>
)
}</ul>
}
// Model
class Task {
static list = [] as Task[]
}
✅ Отображение может использовать произвольные модели. ✅ Легко добавлять новые отображения, не меняя модели. ❌ Для отображения разных моделей необходимо дублировать код отображения. ❌ Изменение интерфейса модели требует обновления всех использующих её отображений. ❌ Двух слоёв слишком мало на больших масштабах.
✅ Удобно из модели получать любые отображения. ❌ Добавление нового отображения требует изменения модели. ❌ Отображение полностью определяется одной основной моделью. ❌ Загрузка модели вытягивает по зависимостям и все её отображения. ❌ Двух слоёв слишком мало на больших масштабах.
Команда Honeypot выпустила документальный фильм об истории Node.js. В часовом видео подробно рассказали о том, как создавали популярную среду выполнения кода на JavaScript. Фильм продолжает серию, в которой уже есть следующие документальные картины:
Одна из самых серьезных проблем в разработке программных средств — их тучность, или раздутость. Программы просто становятся слишком большими. Это может быть связано с неразумным выбором функций, но чаще всего становится следствием плохой архитектуры. Популярное средство повторного использования кода — наследование, но его работа оставляет желать лучшего, поэтому вместо него зачастую применяются копирование и вставка кода. Не следует сбрасывать со счетов и чрезмерную зависимость от библиотек, платформ и пакетов, тесно связанных со многими другими библиотеками, платформами и пакетами. Раздутость может быть побочным эффектом приемов гибкой разработки. Чтобы справиться с ней, увеличивают численность команды разработчиков, но это порождает еще большую раздутость. … Лучший способ справиться с раздуванием программ — не допускать его. Приоритетом при разработке и реализации программы нужно сделать ее «худобу». Следует избегать внедрения в практику раздутых пакетов и инструментов, способствующих раздуванию. Обходитесь без классов. Нанимайте небольшие квалифицированные команды разработчиков. И активно практикуйте удаление кода. Создайте резерв из нескольких циклов разработки с целью удаления ненужного кода и избавления от проблемных пакетов. Радуйтесь, когда количество строк кода в проекте уменьшается. Придерживайтесь принципа наименьшей раздутости.
Дуглас Крокфорд, программист, автор формата JSON и книги "How JavaScript Works"
useOptimistic — новый хук, который позволяет отобразить “оптимистичное” состояние. Оно называется “оптимистичным”, потому что мы надеемся, что запрос не свалится с ошибкой и после его выполнения состояние будет выглядеть именно так.
❓Как используется
В useOptimistic передаётся реальное состояние и функцию-reducer
Компонент использует “оптимистичное” состояние для рендера
Перед выполнением запроса обновляется “оптимистичное” состояние
Когда запрос завершился, нужно обновить реальное состояние
Как только реальное состояние обновилось, оптимистичное состояние обновится автоматически, так как оно передано в useOptimistic первым параметром.
Если запрос упал с ошибкой, нужно откатить изменения в оптимистичном состоянии.
ℹ️ Первый вопрос, которым я задался, а в чём отличие от обычного setState, путём экспериментов, вот что удалось найти:
useOptimistic работает с формами. Работать с обычной кнопкой в SPA мне не удалось, обновление происходило только после завершения запроса
useOptimistic работает только внутри асинхронного обработчика, что логично. Если убрать async/await, обновление произойдёт только после завершения запроса
Параметр в useState используется только для инициализации, и игнорируется в последующих рендерах. useOptimistic будет сихронизироваться со значением со значением переданным первым параметром.
В любом случае, пока useOptimistic выглядит каким-то низкоуровневым API. Надеюсь скоро появится больше Best Practices.
use — новый хук, который позволяет считывать данные из промиса и при этом интегрирован с Suspense и ErrorBoundary.
Основные моменты:
На этот хук не распространяются правила хуков — его можно использовать внутри циклов и условных операторов.
Если мы используем хук use(Promise), то где-то в родительском компоненте мы должны положить сам промис (не данные как мы делали раньше) в стейт (useState). Это позволяет избавиться от useEffect’а, который был нужен, чтобы запросить данные при первом рендере.
Хук интегрирован с Suspense, поэтому пока промис не разрезолвится — будет показан fallback объявленный в ближайшем Suspense.
Если промис зареджектился, то будет показан fallback объявленный в ближайшем ErrorBoundary.
Состоялся релиз системы для создания отказоустойчивых рабочих процессов Restate 0.8. Код проекта опубликован на GitHub под лицензией Put Restate under Business Source License от Restate Software.
Согласно пояснению разработчиков проекта, Restate отлично подходит для создания:
рабочих процессов типа Lambda как код (Lambda Workflows as Code);
транзакционных обработчиков RPC;
обработки событий с помощью Kafka.
В версии Restate 0.8 разработчики уделили большое внимание доработке API, учтя отзывы пользователей, чтобы уменьшить трудности при создании сервисов Restate. Также там добавлены комбинаторы промисов (Promise combinators), которые позволяют детерминированно комбинировать промисы. Например, если вы хотите дождаться вызова службы A или вызова службы B, то Restate позаботится о записи того, какой из промисов был выполнен первым, и в конечном итоге воспроизведёт этот выбор, когда это необходимо. В новой версии проекта доступны все комбинаторы стандартной библиотеки JavaScript.