Жабаскрипт (веде Віктор Турський)
4.62K subscribers
22 photos
2 videos
273 links
Авторський контент для JavaScript розробників, але не завжди про JS:). Пишу про архітектуру, best practices, продуктивність, безпеку, інструментарій.

Viktor Turskyi (@koorchik), Cofounder at Webbylab, SWE at Google

Рекламу не розміщую!
Download Telegram
Жабысриптеры, привет) Я буду скидывать сюда ссылки на классные статьи про JavaScript и JavaScript библиотеки 💩
ИМХО, Kitze один из лучших спикеров прошедшего React Day Berlin. "Navigating the Hype-Driven Frontend Development World Without Going Insane" очень легкий и позитивный доклад. Возможно, доклад не сильно технический, но видно, что Kitze очень крутой жабаскриптер и все по делу.
Отличное видео, чтобы расслабиться в воскресенье :)
https://www.youtube.com/watch?v=QZ6aC6G0ufg
Много лет я писал на Perl и там огромное количество удобных библиотек для написания тестов. В случае с JS все не так хорошо и много лет использую mocha + chai, но недостатков у этих библиотек хватает.

Недавно нашел AVA и понял, что в JS тоже случаются замечательные вещи :)

AVA - это новый инструмент, который решает большинство этих проблем.
1. Не опирается на глобальную доступность тестовых утилит.
2. Позволяет запускать тесты параллельно.
3. Простой и удобный API и очень простая конфигурация (например, даже с mocha использовал qunit интерфейс. Имхо, более читабельны). В случае с AVA сетап всего очень прост.
4. Современный ES из коробки. Я могу писать тесты с использованием всех самых современных фич JS, включая import и тд. Что более важно, тестируемый код будет работать как есть (без транспайлинга). Это позволяет мне быть уверенным, что мой код работает на конкретной версии ноды.
5. Основные ассерты из коробки. Часто нужна только AVA и ничего больше.
6. Ну и поддержка TAP, как крассплатформеный формат репортинга для тестов. Кстати, TAP пришел из Perl, в Perl - это аутпут всех библиотек для тестирования :)

Перевел несколько своих библиотек на AVA (к примеру, тесты на AVA для LIVR js), результатом очень доволен.

AVA - https://www.npmjs.com/package/ava
Channel name was changed to «Жабаскрипт»
В JavaScript не так давно добавили тип данных Symbol. Обычно говорят, что Symbol дает возможность хранить метаданные в объекте или возможность реализации условно приватных свойств объекта. Но есть и другая сторона, Symbol решает ряд проблем и безопасностью приложения.

Отличный пост от Дэна Абрамова на эту тему. Основная идея в том, что React узлы внутри представлены в виде JSON объектов. И код, который вы считаете безопасным <p>{message.text}</p>,
на самом деле, содержит XSS уязвимость. Если message.text содержит пользовательский ввод и мы рендерим React на сервере, то злоумышленик может вставить в message.text JSON объект, который описует любую React ноду. Для того, чтобы от этого защититься, в JSON объекте должно быть свойство $$typeof и Symbol в качестве значения. В таком случае, злоумышленик не сможет заранее предсказать Symbol.

Статья - https://overreacted.io/why-do-react-elements-have-typeof-property/

Еще отличный пример - это Sequalize. Для описания запроса раньше использовались строковые операторы

Post.findAll({
where: { 'or': [{authorId: 12}, {authorId: 13}] }
});

сейчас это:

Post.findAll({
where: { [Op.or]: [{authorId: 12}, {authorId: 13}] }
});

где Op.or это Symbol, что не позволяет злоумышленику так просто сделать ORM Injection.
Есть IoT платформа написанная на JS. Необходимо предоставить сторонним условно доверенным вендорам возможность писать сценарии и заливать их на наши устройства. То есть нужна безопасная песочница для выполнения сторонних скриптов. Есть различные варианты для решения этой задачи:

* Embedded lua. Но, поскольку плагины пишутся вендорами на JS, то и сценарии хочется писать на JS. И остается вопрос, можно ли создать с lua безопасную песочницу.
* Docker контейнеры. Они и так везде на проекте и для этой задачи они будут использоваться, но в контейнерах будет крутиться целый движок и все сценарии. Свой контейнер для каждого отдельного сценария слишком ресурсоёмко. Сценариев будет тысячи.
* Воркеры на WebAssembly - хороший вариант. То есть можно разрешить использовать в теории любой язык. Это отлично для Rust, по поводу JS (с тем же Duktape) не уверен.

В результате остановились на модуле vm2. Это как стандартный нодовский модуль vm, только для безопасного выполнения.

VM2 позволяет вам запустить чужой JavaScript код в безопасной пеcочнице. Вы можете разрешить доступ к определенным модулям или даже к опредленным методам определенных модулей. VM2 использует Proxy объекты, чтобы нельзя было вырваться из песочницы. Конечно любая такая песочница не даёт 100% гарантий, но в нашем случае это отличное решение, особенно в связке с docker.

Если вдруг будет стоять такая задача, рекомендую посмотреть на этот модуль.

VM2 - https://www.npmjs.com/package/vm2
Тред от Yehuda Katz про проблемы с кроссплатформенностью NodeJs модулей. Многие разработчики забивают на Windows. В этом нет большой проблемы, пока ты не публикуешь свой модуль на NPM.

Яхуда озвучивает 2 основные проблемы при работе под Windows:
1. Практически каждый package.json содержит команды в секции scripts, которые не работают в Windows. Основная причина - использование && и другого bash синтаксиса. От себя добавлю, часто вижу, что устанавливаются переменные окружения без использования crossenv, к примеру.
2. Это пути на файловой системе. Разработчики ожидают, что разделитель "/" - это валидный разделитель в Windows разделитель "\" ("\\"). Это создает ряд багов связанных с обработкой путей (например, когда мы обабатываем пути регулярками и тд).

Как делать правильно, можно найти в треде
https://twitter.com/wycats/status/1090307478254829569

Делайте свои модули кроссплатформенными, Micsrosoft сделала же VSCode под Linux и Mac :)
В догонку к позавчерашнему сообщению про vm статья о том, как Cloudflare начала использовать изоляты V8 для serverless вычислений. Идея дать возможность пользователям заливать свой код и выполнять его в безопасной песочнице (по примеру AWS Lambda или Google Cloud Functions)

Что мы имеем, в сравнение с классическим подходом, когда лямбды крутятся в docker контейнерах:
1. Холодный старт 5 ms, вместо от 500ms.
2. Потребление памяти 3mb вместо минимальных 35mb необходимых при механизме с контейнерами.
3. Стоимость в 3 раза ниже, чем AWS Lambda. Правда код нужно писать на жабаскрипте :)

СТАТЬЯ: https://blog.cloudflare.com/cloud-computing-without-containers/

После прочтения поста возникает вопрос, что такое "Isolate"? В интернете практически нет информации. Можно найти, что это deprecated фича, но на самом деле это не так.
Если посмотреть в исходники NodeJs, то можно увидеть, NodeJs workers используют изоляты -
https://github.com/nodejs/node/blob/master/src/node_worker.cc , а поверх node_worker, в свою очередь, построены новые worker_threads.

Isolate - это, по сути, отдельный экземпляр V8, со своим состоянием. Важно не перепутать:
1. Изоляты это фича v8, а не nodejs. worker_threads и тот же vm - это уже модули nodejs.
2. Cloudflare не использует NodeJs, а использует именно v8 (и изоляты).
Многие спрашивают про Test Coverage, каким он должен быть? Нужно ли стремится к 100% покрытию кода тестами?

Основная проблема, что уровень покрытия кода тестами ничего не говорит о качестве тестов. Помню мне рассказывали историю, когда покрытие было недостаточным и не могли принять реквест от разработчика. Разработчик не долго думая добавил просто вызовы функций в тесты (без проверки результата), чтобы увеличить покрытие до требуего уровня :).

Если вы стремитесь к 100% покрытию, то скорее всего тратите время не на то, что действительно важно (покрыть более сложные сценарии или граничные случаи). Главный критерий достаточного количества тестов - это количество багов на продакшене и насколько вы боитесь вносить изменения в код в связи с ожиданием дополнительных багов на продакшене.

Нужно ли использовать test coverage? Да, мы используем по следующим причинам:
1. Test coverage не позволяет быть увереным в наличие хороших тестов, но низкий test coverage явно говорит об отсутствии тестов вообще. Для бекенда для нас 80% покрытия всегда достаточно. С nyc (istanbul) отслеживать покрытие очень легко. Для фронтенда у нас нет требований по покрытию.
2. Поиск мертвых кусков кода. Про это в статье не говорится, но при помощи анализа покрытия это очень удобно делать. nyc (istanbul) позволяет в качестве репортера указать html и вы очень легко можете найти код, который никогда не вызывается и никогда не будет вызываться. Поиск мертвых кусков кода сложно переоценить. Часто этого кода бывает много и он сильно мешает потом новым разработчикам разбираться в проекте.
3. Поиск подсистем, которые вообще не покрыты тестами. Бывают ситуации, когда просто не написали тесты к какой-то функциональности по какой-то причине.

Более детально про покрытие кода тестами можно почитать у Мартина Фаулера в статье "Test Coverage" https://martinfowler.com/bliki/TestCoverage.html

Статья уже старая, но вопрос актуальный :)
Отличный пост от Дэна Абрамова про то, как концептуально работает React - https://overreacted.io/react-as-a-ui-runtime/
Пост не перегружен исходниками, просто понятное краткое описание каждого аспекта работы React.
Eсли вы используете React (независимо от вашего уровня junior, middle, senior, architect, guru, js ninja, js samurai etc) и хотите чуть лучше его понимать, то очень рекомендую.
К примеру, я никогда не задумывался про Lazy Evaluation.
Интересно, что в посте ни одного примера на классах, все на компонентах-функциях с использованием хуков. Фейбук делает хуки своим основным API, классы, я думаю, останутся только для соместимости.
Решил продолжить про тестирование.
Когда в Jest добавили снапшпоты и возможность тестировать React компоненты при помощи снапшотов, все ринулись их использовать и писать насколько жизнь стала лучше :). Но снапшот тестирование может принести больше проблем, чем пользы:
1. Снапшот тесты хрупкие. Один assert проверяет все, вместо конктетной функциональности.
2. Нарушают инкапсуляцию. На один компонент Button может опираться масса других компонентов. Его поменяли и все посыпалось (особенно, если без shallow render)
3. Возникает антипаттерн "Guru Checks Output". Когда все посыпется, джун просто запустит jest -u && git commit. То есть, всегда должен быть человек ("Гуру", который знает детали реализации), который проверит, весь вывод и опираясь на свои знания деталей реализации, скажет это мы что-то сломали или тесты посыпались, но мы ничего не сломали и можно комитить.

На самом деле, снапшот тесты отличный инструмент (главное их правильно использовать), но они не слепая замена обычным тестам. К примеру, снапшоты хороши для контроля регресии в легаси коде.

Хороший пост на эту тему https://randycoulman.com/blog/2016/09/06/snapshot-testing-use-with-care/
И про "Guru Checks Output" https://wiki.c2.com/?GuruChecksOutput.
Мы пишем на JavaScript, но бывают случаи, когда нужная нам библиотека есть только на Java. В моей практике была такая ситуация. Мне нужна была библиотека Semgrex со стендфордского NLP парсера. Semgrex - эта библиотека, которая позволяет применять регулярки для выбора узлов с дерева разбора предложения (гуглить dependency tree nlp).
Конечно, можно писать весь код на Java, но не сильно хочется. Другой вариант - это вызывать Java из NodeJs.
Java предоставляет JNI (Java Native Interface), что дает нам возможность вызывать методы Java с другого языка и под NodeJs есть отличный модуль https://www.npmjs.com/package/java, который является мостом к JNI.
В результате, вы без особых проблем можете использовать классы Java внутри вашего NodeJs приложения, как если бы они были классами JavaScript.

В качестве примера, можете глянуть на исходники nodejs обертки вокруг java Semgrex https://www.npmjs.com/package/semgrex
Хочу поделиться отличным постом моего коллеги из WebbyLab. В названии звучит "Redux на бекенде". На самом деле, статья про то, как удалось переиспользовать одни и те же редьюсеры в веб, в мобильном и в бекенд приложениях, автоматически получить полноценную оффлайн работу приложения практически без дополнительных усилий. Статья рассказывает про event sourcing, показывает общее и различное между Redux и event sourcing, демонстрирует необычное, но эффектинове решение на базе совмещения Redux и event sourcing.

Мы привыкли к классическим схемам с React и Redux, но этот пост расширяет кругозор и предлагает другой подход.

https://hackernoon.com/how-we-used-redux-on-backend-and-got-offline-first-mobile-app-as-a-result-b8ab5e7f7a4
Попалась мне сегодня на глаза статья "Using TensorFlow.js to Automate the Chrome Dinosaur Game (part 1)". Да, это неплохой тьюториал, но ничего особенного для тех, кто уже работает с Tensorflow (а так можете почитать), но интересна она по другой причине.

Считается, что ML/AI существует только в Python. А что же с другими языками, в том числе с JavaScript? JavaScript используется для всего сегодня и странно, если бы не началось ML движение на JS. По факту, так и происходит.

К примеру, в прошлом году мы делали проект связанный с интеллектуальным поиском, вся эта история с различными алгоритмами word embedding и тд. Изначально мы начали все делать на python, а потом переключились на JS ввиду того, что на npm есть отличные врапперы вокруг C/C++ реализаций этих алгоритмов (сейчас пишем про это статью). Зачастую эти библиотеки работа комьюнити, но в случае с TensorFlow.js - это официальная библиотека от Google.

Сначала Google выпустил deeplearn.js - библиотека для ML с аппартным ускорением, которая работает в браузере. Браузер не поддерживает CUDA, но все равно можно использовать WebGL и шейдеры для математический расчетов. Вкратце, библиотека создает шейдер, который расчитывает цвет пикселя, а число, которое описывает цвет пикселя, по сути, и есть результат нашей математической операции (еще один костыль в мире веб :)). Эта библиотека и стала ядром для TensorFlow.js и была переименована в "TensorFlow.js Core".
Это очень круто и открывает много возможностей, но это про браузер. Как же работает TensorFlow.js в NodeJS? На самом деле, достаточно долго TensorFlow.js не работал в NodeJs (только недавно добавили поддержку). В NodeJs TensorFlow.js является байндингом к C/C++ имплементации (аналогично, как работает Python версия).

Также важно, что Keras API уже давно есть частью TensorFlow и поддерживается JS версией ( правда небольшие отличия все же есть) и вы можете работать с привычным высокоуровневым API.

Осталось дождаться порта scikit-learn на JS 😁

СТАТЬЯ: https://heartbeat.fritz.ai/automating-chrome-dinosaur-game-part-1-290578f13907
👍1
Отличная статья про микросовервисную архитектуру в Medium. Это тот случай, когда все сделано опираясь на здравый смысл. Изначально, у медиум был монолит на NodeJS, но ввиду ряда ограничений в 2018 они перехали на микросервисы.

Из ключевого:
1. Не делайте микросервисы ради микросервисов. Выносите в микросервисы только то, что имеет смысл выносить.
2. Микросервисы это не про количество строк кода. Микросервисы могут быть большими, главное чтобы они решали одну конкретную задачу.
3. Каждый микросервис имеет свой набор данных (разные способы достижения этого описаны в статье). Использование одной общей базы плохая идея.
4. RPC больше подходит чем REST для коммуникации между микросервисами. Medium использует gRPC.
5. Не обязательно делать микросервисы с нуля. Можно взять часть кода вашего монолита и вынести в отдельный сервис.
6. Плохо сконструированные микросервисы могут быть хуже монолита. Если вы не можете построить рабочий монолит, то с чего вы взяли, что сможете построить микросервисную архитектуру 😁
7. Микросервисы это еще не повод втянуть максимальное количество различных технологий, поскольку это может увеличить стоимость поддержки и фрагментировать команду.
8. Для небольших команд монолит будет лучшим решением, просто делайте его модульным.

СТАТЬЯ: https://medium.engineering/microservice-architecture-at-medium-9c33805eb74f
"The TypeScript Tax: A Cost vs Benefit Analysis" от Эрика Эллиота - пост, который поднимает вопрос дает ли на самом деле TypeScript выигрыш на крупных проектах. Если вы его не читали еще, то очень советую прочитать. К тому же, 11 февраля он был расширен кейсом от AirBnB.

Эрик правильно говорит, что нельзя сравнивать просто TypeScript против JavaScript. Нужно сравнивать JavaScript+tooling+процессы против TypeScript+tooling+процессы. И в таком случае TypeScript дает слишком мало преимуществ.
Когда у вас есть инструменты, отстроены процессы разработки, то из 1000 багов вы находите 900, с остатка максимум 20% вам позволит найти TypeScript. То есть это 20 багов из 1000, и сразу возникает вопрос возврата вложений в технологию. Стоит ли оно того?

Мы попробовали TypeScript и Flow.js у себя на нескольких проектах и вот, что получили:
1. VSCode умеет делать автокомплит и для чистого JavaScript без аннотаций. Иногда удивляет, когда есть фабричный метод, который возвращает объект, в котором экземпляр класса, в котором есть свойства, которые отлично автокомплитятся :)
2. Мы по максимуму используем eslint для статического анализа и это покрывает основную часть проблем. Если нет нужного плагина, то мы пишем свои "eslint-plugin-more"
3. Я согласен с Эриком, что для перехода на TypeScript, разработчику нужно 2-3 месяца и 6-8 месяцев, чтобы им овладеть полностью.
4. Описание аннотаций занимает достаточно большое количество времени и при тех же временных затратах тесты более эффективны. Кроме того, после тестов, типизация дает не настолько существенный выигрыш.
5. Типы можно описывать по разному и достичь какого-то стандарта кросс-проектно достаточно тяжело. Кто-то считает, что нужно выжать все с TypeScript, кто-то - что нужно минимум аннотаций.
6. Далеко не всем JavaScript разработчикам нравится TypeScript

Я не против TypeScript, мне нравится идея статической типизации, считаю TypeScript отличным продуктом, но всегда нужно взвешивать за и против от использования той или иной технологии. Для меня чистый JavaScript это выбор по умолчанию, а TypeScript/Flow уже опция. И для полноты картины, могу привести случай, когда статическая типизация дала нам большой выигрыш. Мы использовали GTK байндинг к Spidermonkey и аргументы неправильного типа приводили к крашу всего приложения. Статическая типизация позволяла избежать этих ситуаций.

В целом, эти же аргументы описывает Эрик в своей статье, но еще он затрагивает вопросы рекрутинга, обучения, рефакторинга кода и тд.
1
Наткнулся на интересный тред в твиттере.
Чувак увидел, что кто-то форкнул его проект, не только форкнул, но и поменял авторство. В результате оказалось, что есть ребята, которые форкают известные репозитарии, называют их по другому, меняют авторство на свое, переписывают историю коммитов на свои аккаунты на Github. В результате, аккаунт, который был создан недавно имеет отличную историю коммитов, красивые графики, море активности и тд. И таких аккаунтов не один, они друг друга фоловят и тд. Зачастую это проекты на JavaScript.
Остается вопрос зачем они это делают. Может это какой-то бот-нет и подготовка к атаке на npm, а может кому-то нужен красивый акк, чтобы получить проект на upwork :). Гипотезы можете найти в Twitter треде.