Size: a a a

Иван Акулов про разработку

2017 July 31
Иван Акулов про разработку
Подсказали, что не во всех приложениях есть «Forwarded from <другой канал>» ¯\_(ツ)_/¯ Держите прямую ссылку: https://t.me/teamleading/10

(И не стесняйтесь писать любые комментарии в @iamakulov)
Telegram
Про руководство разработчиками
Очень частый вопрос: как из разработчика стать управленцем? Если коротко, то ответ такой: никак.

Для начала бывают технические лидеры (или техлиды), а бывают руководители. Техлиды ведут техническую часть проекта. Они ответственны за качество кода, но не ответственны за продукт. Они управляют кодом, который пишут участники проекта, но не вмешиваются в процесс создания продукта. Технические лидеры – это старшие товарищи на проекте, с богатым багажом опыта. Во многих компаниях совершается одинаковая «классическая» ошибка – это назначение руководителем техлида (или старшего разработчика). Я называю это «убийством разработчика», но почему-то многие считают это логичным продолжением карьеры: разработчик – старший разработчик – техлид. Нет, не делайте так, техлид – это тот кто принимает технические решения, ревьюит код, менторит джунов и новеньких, но он не занимается руководством командой. Многие техлиды не хотят руководить, им нравится писать код и они эффективны именно в этом, но будут не эффективны как руководители…
источник
Иван Акулов про разработку
А Денис Довгань собрал кучу странных примеров из JavaScript-а и объяснил каждый со ссылками на спецификацию: https://github.com/denysdovhan/wtfjs

Я когда-то пробовал читать спецификацию JS. Из-за кучи перекрёстных ссылок это было сложно, но зато, когда ты разбирался наконец во всех нюансах и выстраивал в голове чёткую аккуратную картинку происходящего, понимание повышалось в разы. Попробуйте, в общем, если ещё не.
источник
2017 August 02
Иван Акулов про разработку
В npm нашли поддельные пакеты, которые при установке собирают и отправляют на сторонний сервер всё окружение процесса (в том числе секретные токены, если они есть). Названия пакетов очень похожи на настоящие (crossenv, babelcli, d3.js и т.п.).

Собрал всё, что известно об этом. Вот что делать, если вы пользователь или автор библиотек (+ весь список пакетов): https://iamakulov.com/notes/npm-malicious-packages/
источник
Иван Акулов про разработку
iamakulov_channel
В npm нашли поддельные пакеты, которые при установке собирают и отправляют на сторонний сервер всё окружение процесса (в том числе секретные токены, если они есть). Названия пакетов очень похожи на настоящие (crossenv, babelcli, d3.js и т.п.).

Собрал всё, что известно об этом. Вот что делать, если вы пользователь или автор библиотек (+ весь список пакетов): https://iamakulov.com/notes/npm-malicious-packages/
В одном предложении: проверьте список (в статье) и перегенерируйте секретные токены, если вы устанавливали эти пакеты как зависимости. Это важно.
источник
Иван Акулов про разработку
One-liner, чтобы проверить, есть ли у вас в дереве зависимостей эти пакеты:

npm ls | grep -E "babelcli|crossenv|cross-env.js|d3.js|fabric-js|ffmepg|gruntcli|http-proxy.js|jquery.js|mariadb|mongose|mssql.js|mssql-node|mysqljs|nodecaffe|nodefabric|node-fabric|nodeffmpeg|nodemailer-js|nodemailer.js|nodemssql|node-opencv|node-opensl|node-openssl|noderequest|nodesass|nodesqlite|node-sqlite|node-tkinter|opencv.js|openssl.js|proxy.js|shadowsock|smb|sqlite.js|sqliter|sqlserver|tkinter"
источник
Иван Акулов про разработку
iamakulov_channel
Когда слушатели событий с passive: true действительно помогают: https://gist.github.com/iamakulov/45803e89db2eb44a7a6be33a80ffcab7
Перепроверил с событием wheel вместо депрекейтнутого mousewheel. Добавились данные для Firefox: https://gist.github.com/iamakulov/45803e89db2eb44a7a6be33a80ffcab7
источник
2017 August 03
Иван Акулов про разработку
источник
Иван Акулов про разработку
🎉 Я запускаю консалтинг по производительности фронтенда!

— Оптимизирую ваше приложение или сайт, чтобы пользователи любили его ещё больше (и увеличилась конверсия)
— Сделаю это сам — вам не придётся отвлекать вашу команду от разработки новых фич
— Могу делать это регулярно, чтобы вы вообще перестали думать о проблемах производительности

Посмотрите сами и покажите тимлиду (или не показывайте, если тимлид — вы :–)

iamakulov.com/perf-consulting
источник
2017 August 07
Иван Акулов про разработку
📐 Мортен Рэнд-Хедриксен рассказывает, как использовать CSS-гриды на практике. Статья не про свойства, а про более высокоуровневые вещи.

Ключевое:
— Чтобы верстать с гридами, нужно поменять мышление. Раньше, чтобы сверстать что-то, я смотрел на страницу, разбивал её в голове на контейнеры, которые потом разбивал на другие контейнеры и т.д. С гридами нужно по-другому: разбить в голове страничку на сетку — как в графредакторе — и раскладывать блоки по элементам сетки. Пришлось немного сломать мозг.

— С обратной совместимостью у гридов не очень. Мортен предлагает не пытаться повторить нужный лэйаут для старых браузеров, а сделать самый простой (но корректно выглядящий) одноколоночный макет и прогрессивно улучшать его помощью гридов. Тогда в старых браузерах будет одна базовая колонка, а в новых — более богатый грид.

В конце статьи — поэтапный пример вёрстки темы для WordPress.

Перевод на CSS-Live: http://css-live.ru/articles/vyorstka-realnyx-proektov-na-gridax-css-grid-layout-uzhe-sejchas.html
CSS-LIVE
Вёрстка реальных проектов на гридах (CSS Grid Layout) уже сейчас
Перевод статьи Building Production-Ready CSS Grid Layouts Today с сайта smashingmagazine.com для CSS-live.ru, автор — Мортен Рэнд-Хедриксен Эволюция многих отраслей выглядит не как постепенное улучшение понемногу, а скорее как перевороты в самых основах, меняющие общепринятые подходы и методологии будто в одночасье. Для веб-фронтенда это верно как никогда. Наша отрасль процветает благодаря постоянному активному развитию, и с регулярностью возникают новые технологии, в корне меняющие наш подход к работе. Сегодня мы в самом начале такой вот революции, которую несут с собой CSS-гриды. Многое из того, что мы знали о возможностях, ограничениях и общепризнанных подходах, с этим новым раскладочным модулем станет неактуальным, а взамен мы найдем новые возможности, ограничения и удачные решения, которые приведут нас в новую эру веб-дизайна. О технических аспектах CSS-гридов и их одномерных родственников — флексбоксов — уже немало сказано более знающими людьми. В этой статье я хочу применить эти
источник
Иван Акулов про разработку
источник
Иван Акулов про разработку
И вот ещё один важный кусочек из статьи. Мало кто, к сожалению, хорошо заботится о доступности в интерфейсах (я сам чаще нет, чем да), но, может, если ПОСТОЯННО НАПОМИНАТЬ, мы наконец начнём это делать. Поэтому напоминаю всем и себе.

(А чтобы знать, как надо делать, почитайте это введение в доступность)
источник
2017 August 08
Иван Акулов про разработку
Рубрика #TodayILearned

В Реакте при рендеринге элементов из массива принято использовать атрибут key={some unique ID}. Этот атрибут помогает Реакту реиспользовать DOM-узлы, если вы переставляете элементы массива местами. Выглядит он так:

<div>
 {articles.map(article =>
   <ArticlePreview key={article.id} article={article} />
 )}
</div>

Так вот. Основная польза key — это помочь Реакту избежать удаления и пересоздания элементов. Оказывается, его можно использовать с прямо противоположной целью — заставить Реакт лишний раз перемонтировать один и тот же элемент. Чтобы сделать это, нужно задать элементу одно значение key:

<Image key="image-foo" />

а потом изменить его на другое:

<Image key="image-bar" />

Когда вы изменяете key, Реакт считает, что изменяется сам компонент. Поэтому вместо просто передачи пропов в уже существующий компонент он отмонтирует старый экземпляр, а затем примонтирует новый. У старого экземпляра при этом вызовутся колбеки componentWillUnmout(), а у нового — конструктор и componentWillMount().

Когда это полезно? В каких-то частных случаях при работе со сторонними компонентами, когда вам нужно заставить их примонтироваться заново (мне это, например, помогло с react-table). Подход с key немного удобнее, чем с заменой компонента на null и обратно — для него нужен только один вызов render, а не два.

Когда это вредно? Практически всегда — передача новых пропов дешевле, чем полное перемонтирование компонента. Используйте это только в крайнем случае, когда без перемонтирования не обойтись. Ещё не стоит применять этот подход со своим кодом — лучше изменить код так, чтобы обойтись без него.
источник
2017 August 09
Иван Акулов про разработку
Мой хороший друг Джеймс пишет ежедневные короткие заметки-советы, где делится знаниями. У него интересно — я, например, не знал, что Node.js можно дебажить напрямую из Chrome или что в браузерах можно сделать нативную плавную прокрутку (которая, правда, пока работает не везде). А сейчас Джеймс в двух частях рассказал, как сделать плагин для ESLint-а (раз, два).

Почитайте его заметки, в общем: https://github.com/jakwuh/dailytip
И подписывайтесь на канал с ними: https://t.me/dailytip
источник
Иван Акулов про разработку
В статье про поддельные пакеты в npm (https://t.me/iamakulov_channel/53) я некорректно указал, что можно обезопасить свои пакеты, если поместить их в скоупы. Это не так:
источник
Иван Акулов про разработку
источник
2017 August 12
Иван Акулов про разработку
Как компилировать импорты в Node.js на лету

Джон Далтон и Матиас Байненс выпустили пакет @std/esm. Он позволяет использовать ES-импорты и экспорты в Node.js уже сейчас. Вы реквайрите этот пакет один раз, а потом во всех других файлах используете стандартные import и export:

// index.js
require("@std/esm")
module.exports = require("./main.mjs").default

// main.mjs
export default function() {
 // ...
}


Я разобрался, как это вообще работает:

1. Node.js по умолчанию воспринимает все файлы как обычный JavaScript. Но есть исключение: если вы реквайрите файл с окончанием .json, Node.js парсит его именно как JSON. Оказывается, это не зашито где-то в глубине Node.js, а находится близко к поверхности и даже конфигурируется.

2. Обработка расширений настраивается через require.extensions. Чтобы добавить новый обработчик, нужно добавить в этот объект новое функцию с полем, соответствующим расширению:

require.extensions['.es'] = function (module, filename) {
 // ...
}

На самом деле, даже сама Node.js устанавливает обработчики .js- и .json-файлов точно так же (только с немного другим API).

3. Функция, которую вы добавите в require.extensions, будет вызываться каждый раз, когда вы зареквайрите новый файл с соответствующим расширением. Что делать дальше, зависит от того, как вы хотите обработать файл.

▫️ 3а. Вы можете хотеть загрузить ESNext-код, скомпилировать его в стандартный JavaScript и передать его в нормальный обработчик JavaScript-а. Это то, что нужно в @std/esm. Это делается вот так:

require.extensions['.mjs'] = function (module, filename) {
   var content = fs.readFileSync(filename, 'utf8');
   var transpiledContent = transpileImportsExports(content);
   module._compile(transpiledContent, filename);
}


(module._compile — это метод, который интерпретирует JS-код стандартным образом — парсит его, сохраняет экспорты и передаёт экспорты наружу. Сама Node.js использует его же для загрузки обычных .js-файлов.)

▫️ 3б. А если вам нужно загрузить не JS-код, а вообще какой-то другое содержимое, вы можете присвоить результат импорта в module.exports. Вот так, например, можно импортировать текстовый файл как строку:

require.extensions['.txt'] = function (module, filename) {
   const text = fs.readFileSync(filename, 'utf8');
   module.exports = text;
}


➡️ Итого:
— добавляете расширение и функцию в require.extensions
— в функции загружаете содержимое файла → трансформируете → а дальше либо передаёте JS-компилятору, либо записываете своё значение в module.exports

🙅‍ Дисклеймер. require.extensions в реальных проектах лучше не использовать, потому что это замедляет загрузку файлов — и тех, которые вы конвертируете на лету, и остальных. Это подходит только для определённых библиотек — вроде этого @std/esm или babel-register. Если вам нужно компилировать код в обычном проекте, воспользуйтесь сборщиками кода вроде babel или webpack.
источник
Иван Акулов про разработку
iamakulov_channel
Как компилировать импорты в Node.js на лету

Джон Далтон и Матиас Байненс выпустили пакет @std/esm. Он позволяет использовать ES-импорты и экспорты в Node.js уже сейчас. Вы реквайрите этот пакет один раз, а потом во всех других файлах используете стандартные import и export:

// index.js
require("@std/esm")
module.exports = require("./main.mjs").default

// main.mjs
export default function() {
 // ...
}


Я разобрался, как это вообще работает:

1. Node.js по умолчанию воспринимает все файлы как обычный JavaScript. Но есть исключение: если вы реквайрите файл с окончанием .json, Node.js парсит его именно как JSON. Оказывается, это не зашито где-то в глубине Node.js, а находится близко к поверхности и даже конфигурируется.

2. Обработка расширений настраивается через require.extensions. Чтобы добавить новый обработчик, нужно добавить в этот объект новое функцию с полем, соответствующим расширению:

require.extensions['.es'] = function (module, filename) {
 // ...
}

На самом деле, даже сама Node.js устанавливает обработчики .js- и .json-файлов точно так же (только с немного другим API).

3. Функция, которую вы добавите в require.extensions, будет вызываться каждый раз, когда вы зареквайрите новый файл с соответствующим расширением. Что делать дальше, зависит от того, как вы хотите обработать файл.

▫️ 3а. Вы можете хотеть загрузить ESNext-код, скомпилировать его в стандартный JavaScript и передать его в нормальный обработчик JavaScript-а. Это то, что нужно в @std/esm. Это делается вот так:

require.extensions['.mjs'] = function (module, filename) {
   var content = fs.readFileSync(filename, 'utf8');
   var transpiledContent = transpileImportsExports(content);
   module._compile(transpiledContent, filename);
}


(module._compile — это метод, который интерпретирует JS-код стандартным образом — парсит его, сохраняет экспорты и передаёт экспорты наружу. Сама Node.js использует его же для загрузки обычных .js-файлов.)

▫️ 3б. А если вам нужно загрузить не JS-код, а вообще какой-то другое содержимое, вы можете присвоить результат импорта в module.exports. Вот так, например, можно импортировать текстовый файл как строку:

require.extensions['.txt'] = function (module, filename) {
   const text = fs.readFileSync(filename, 'utf8');
   module.exports = text;
}


➡️ Итого:
— добавляете расширение и функцию в require.extensions
— в функции загружаете содержимое файла → трансформируете → а дальше либо передаёте JS-компилятору, либо записываете своё значение в module.exports

🙅‍ Дисклеймер. require.extensions в реальных проектах лучше не использовать, потому что это замедляет загрузку файлов — и тех, которые вы конвертируете на лету, и остальных. Это подходит только для определённых библиотек — вроде этого @std/esm или babel-register. Если вам нужно компилировать код в обычном проекте, воспользуйтесь сборщиками кода вроде babel или webpack.
Кстати, Ингвар Степанян в фейсбуке упомянул, что @std/esm использует более сложный подход. Этот пакет не просто добавляет обработчики для новых типов файлов, но и оборачивает их в свои функции (и обработчики для старых типов файлов тоже). Насколько я понимаю, это используется для большей гибкости: https://web.facebook.com/notes/ivan-akulov-about-frontend/how-to-compile-require-in-nodejs-on-the-fly/845823175583544/?comment_id=845865748912620
источник
2017 August 14
Иван Акулов про разработку
💡 #Совет

element.getBoundingClientRect() — медленный вызов. Не используйте его в часто вызываемых функциях — откладывайте его вызовы с помощью _.debounce или избавьтесь от него совсем.

element.getBoundingClientRect() медленный, потому что при каждом вызове он заставляет браузер пересчитывать лэйаут страницы. Вот другие браузерные АПИ, которые тоже вызывают такой эффект: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
источник
Иван Акулов про разработку
Переслано от Vasily Polovnyov
Привет! А почему getBoundingClientRect вызывает лейаут при каждом вызове? Разве там не такая же история, как и с остальными триггерами лейаута: медленные вычисления произойдут, если ДОМ «грязный»?
источник
Иван Акулов про разработку
Василий уточнил, что getBoundingClientRect() на самом деле перевычисляет лэйаут не прямо при каждом вызове, а только если он изменился.

Да, похоже, это так и есть! Я не нашёл никакой спецификации, которая это задаёт — и вряд ли она есть, это скорее особенности реализации браузеров — но в списке АПИ Паула Ойриша написано вот это:
источник