Состояние JavaScript в 2018 году

Tags: JavaScript

Три года назад я написал «Состояние JavaScript» в 2015 году. В нем я утверждал, что быстрые темпы изменений в нашей отрасли требовали от нас принятия «микробиблиотек» - замены монолитных фреймов небольшими, тонкими, одноцелевыми библиотеками. Но теперь я хотел бы убедить вас вернуться.

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

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

Но сперва разберемся в обстановке.

Состояние JavaScript в 2015 году

Когда я в последний раз писал, Google только что объявила, что Angular 2 будет обратно несовместимой перезаписью всей структуры. Если бы вы были NG-convert 2013 года,  это означало, что вы только что вложили год работы в технологию, которая внезапно устарела. Это отошло так же быстро, как можно было ожидать.

В этом контексте я сделал два (довольно осторожных) предсказания:

Первое: скорость изменения в экосистеме JavaScript была неустойчивой, и разработчики могли бы противостоять ей, и -

Второе: чтобы защитить себя от устаревания структуры, разработчики инвестировали бы в микробиблиотеки - небольшие, одноцелевые библиотеки с простыми API-интерфейсами, которые не требовали бы «частных» знаний, специфичных для конкретной инфраструктуры.

И хотя я льщу себе, я думаю, что это в той или иной степени произошло. Во-первых, сообщество webdev начало пересматривать JavaScript ; во-вторых, они приняли React, который, как оказалось, действительно был микробиблиотекой.

Это может показаться странным, учитывая, насколько велика база кода React. Но, будучи микробиблиотекой, React заботится о том, чтобы решить только одну проблему, хорошо: писать представления как функции. Он сделал это с чрезвычайно тонким языком шаблонов (JSX), который вводит малый синтаксис шаблона, поскольку он может преуспеть. Поскольку React является «в точности JavaScript», разработчики тратят минимальную энергию на концепции, специфичные для библиотеки. Это может быть не «микро» в условиях «байтов до упора», но это, безусловно, инвестиции с низким уровнем риска, которые имеют смысл во время пересмотра.

Почти все проекты React следуют этой архитектуре микробиблиотеки: задействуют разнообразные плагины и утилиты для поддержки состояния (Redux, Sagas), маршрутизации (React-Router), коллекций (Lodash), неизменяемости (Immutable.js) и, без сомнения, других которые выпали из моей памяти. Аналогично, сценарии сборки этих проектов основаны на корзине плагинов Webpack и Babel, тщательно продуманных вместе с файлами конфигурации.

До сих пор  React служил нам довольно хорошо. Отдельные компоненты были протестированы и заменены по мере развития практики, как различные воплощения Flux, или нескольких итераций React-Router, но без необходимости перезаписывать проекты. Точно так же Webpack позволил нам быстро принять новые методы, такие как транспиляция, экспериментальное JS, разделенное связывание и облачный CSS, просто добавив плагины NPM по мере их создания (по крайней мере, это теория).

Проблема в том, что мир изменился, но наш стек приложений все еще застрял в 2015 году. И это удерживает нас.

Стоимость микробиблиотек в 2018 году

Когда мы приняли архитектуру microlib, мы пошли на определенные компромиссы.

Во-первых, использование множества зависимостей означает принятие множества зависимых решений. То, что раньше выполнялось за один проект, теперь стало тем, что мы должны делать каждую неделю.

Легко выбрать библиотеку JavaScript, но сложно выбрать одну хорошую. Большинство разработчиков используют популярность как прокси для качества. Они надеются, что если проект будет иметь тысячи звезд в Github, он никогда не будет заменен, никогда не будет вводить переломные изменения и никогда не будет делать уязвимым ваш проект.

Однако этого не может быть гарантировано, и мне не нужно вспоминать о фиаско с левой панелью, чтобы напомнить вам об этом. Просто посмотрите на свои собственные проекты и подсчитайте зависимости. Сколько из них вы подвергли аудиту безопасности? Сколько вы тестировали производительность? Как много из них имеют стабильное лидерство? С таким количеством, как вы могли?

Дэвид Гилбертсон написал очень хорошую статью  на Hackernoon несколько недель тому назад: Я собираю номера кредитных карт и пароли с вашего сайта. Вот как. Это фрагмент фантазии о том, что кусок вредоносного ПО попал в популярный пакет NPM. Вы не можете обнаружить его в своих сетевых инструментах, поскольку он обнаруживает Chrome devtools. Вы не можете обнаружить через осмотр своего пакета, потому что HTTP-запрос запутан. Вы даже не можете посмотреть пакет на Github, потому что версия NPM немного отличается.  Тебе не повезло, и даже если кто-то его вычислит, будет слишком поздно: разработчики «устанавливали пакеты npm, как будто они вызывают болеутоляющие средства», к тому времени, когда появится какое-либо предупреждение, вредоносное ПО уже будет упаковано в тысячи и тысячи последующих сайтов.

Мораль этой истории - якобы не устанавливать сторонний код на важные страницы, но у меня есть другой подход. Дело не в том, что люди небрежны или ленивы, так что системы, которые мы построили для поддержки нашего стека microrolibrary, усложняют создание надежных и безопасных систем. Комбинация технологий: NPM, Github, прекрасные READMEs - деформируют наше принятие решений, позволяют поспешным решениям и побуждают нас сначала устанавливать npm, задавать вопросы позже.

И это реальное состояние JavaScript в 2018 году: отсутствие должной осмотрительности и хрупких деревьев зависимостей, а не потому, что разработчики немыслимы, а потому, что микролибы требуют тщательного принятия решений, что противоречит темпам большинства технологических компаний.

Стереотипный код - неправильное решение правильной проблемы

Сегодня есть одно нововведение - и потенциальное решение - это было почему-то не замечено в последние несколько лет, - это рост стереотипных кодов JavaScript. Эти проекты, обычно размещенные на Github, предоставляют примерный код для создания веб-проекта архитектуры микробиблиотек. Они объединят стек React с системой сборки Webpack / Babel и, как правило, с каким-то предварительным сервером. Они очень, очень популярны: оригинальная реакционная плита имеет около 17 000 звезд Github.

Я никогда не был поклонником этого подхода. Мне нравится понимать все компоненты моего приложения, чтобы я знал, что всегда могу выйти из кризиса. Это особенно важно для создания скриптов: я тоже работал со слишком многими командами, которые не знают, как их функции Webpack или Gulp действительно функционируют, как их код фактически упакован для развертывания. Дела идут гладко ... до поры, до времени, и это заканчивается, как правило, в разгар какого-то кошмара производительности.

Но они действительно демонстрируют настоящую необходимость: разработчики не хотят тратить первые недели своих проектов на сбор микробиблиотек и написание связующего кода. Они бы скорее установили среду, такую как Create-React-App, которая обеспечивает не только стереотипный код приложения, но и инструменты для подстройки проекта, форматирования кода и даже настройки процесса непрерывной интеграции.

Тем не менее, такие мощные системы, как CRA, им всегда будет препятствовать, поскольку они действительно не могут контролировать свои зависимости. Если React-Router-5 выдает новый список нарушений, CRA должен передать их своим пользователям. Если зависимость изъята из-за спора юридической или интеллектуальной собственности (как в случае с левой панелью), CRA в конечном итоге также должен отказаться от нее. Авторы стереотипного кода не могут полностью изолировать своих пользователей от затрат на микробиблиотеки.

Преимущества монолитов

До сих пор я писал в основном о расходах на строительство проекта из небольших одноцелевых библиотек. Но я не объяснил, что конкретно монолиты могут дать нам.

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

Например, в оригинале Angular разработчики пишут представления на языке шаблонов, специфичных для Angular. Было бы разумно подключить представление к объекту состояния в фоновом режиме, известному как контроллер:

1
2
3
4
5
6
7
8
9
10
<label>Click me:
<input type="checkbox" ng-model="checked" ng-init="checked=true" />
</label>
<br/>
Show when checked:
<span ng-if="checked">
This is removed when the checkbox is unchecked.
</span>

Магия происходит в ng- атрибутов, которые, конечно, чужды HTML. Я называю их «волшебными», потому что несмотря на то, что они сильны, о них довольно сложно рассуждать. Что именно делает Angular, когда сталкивается с этим заклинанием? И, как со всеми магическими заклинаниями, - это то, чему я должен научиться и запомнить. Если структура устаревает, то обучение тратится впустую.

Сравните это с эквивалентным JSX:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
onChange(e) {
this.setState({checked: e.target.checked});
}
render() {
return (<div>
<label>Click me:
<input
type="checkbox"
onChange={this.onChange.bind(this)}
checked={this.state.checked}
/>
</label>
<br/>
Show when checked:
{this.state.checked &&
<span>
This is removed when the checkbox is unchecked.
</span>
}
</div>
);
}

(Извиняюсь перед разработчиками React, если я это исказил - прошло довольно много времени, так как я много писал JSX изо дня в день).

Как вы можете видеть, JSX гораздо более прозрачен - он намного ближе к реальному JavaScript, и он почти не имеет специального синтаксиса HTML, кроме фигурных скобок, используемых для выражений ({}).  Но - и это весомое “но” - то, что он убавляет, так это производительность. Это более значимо. Вы должны иметь дело с такими функциями, как привязка функций JavaScript и необработанные API-интерфейсы DOM (e.target и др.). Он не может делать никаких предположений о том, как управлять структурой глобально, за пределами отдельного компонента.

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

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

Разве я не сгорю от пересмотра?

Нет, потому что, несмотря на вездесущее фоновое излучение мемов r / программирования и жалоб на Hacker News, экосистема JavaScript на самом деле сильно охладилась за последние два года.

Рассмотрим этот слайд из опроса State of JS 2017 (случайное совпадение названий):



Предполагая, что опрос является репрезентативным, это наиболее распространенные front-end библиотеки JavaScript, которые в настоящее время используются. Лишь одному из них меньше двух лет:

  • React,  выпущен в марте 2015 года
  • Angular 1, выпущен в октябре 2010 года
  • Angular 2, выпущен в декабре 2015 года
  • Vue, выпущенный в октябре 2015 года
  • Backbone, выпущен в октябре 2010 года
  • Ember, выпущен в декабре 2011 года
  • Aurelia, выпущен в июне 2016 года

Здесь сходились не только технологии, но и парадигмы. Ежедневные практики веб-разработчиков больше просто не меняются. Практически все проекты запускают код ES6 через транспиляционную машину Webpack-Babel. Они выводят разделенные пакеты с общим файлом поставщика. Файлы имеют хеши в своих именах для кэширования. Компиляция JSX или Vuefile является стандартом.

И все же все эти проекты поддерживают одни и те же неуклюжие беспорядки конфигурационных файлов webpack, объединяя множество микрозависимостей. Наш инструментарий предоставляет нам эту удивительную гибкость и головокружительный выбор, но действительно ли они нам нужны?

Но здесь есть еще один, более холодный фактор: сама сеть застопорилась. Мы были так взволнованы всеми новшествами на земле JavaScript, что мы не заметили, как пришли гомогенные веб-приложения.

Под этим я подразумеваю, что типы сайтов, которые мы создаем, не очень разнообразны. Мой опыт в том, что в моей карьере я только строил два вида JavaScript-приложений: контент-сайты, финансируемые рекламными объявлениями, или SPA-центры, которые располагают некоторым физическим сервисом. Последние всегда содержат страницы списков, большие таблицы с сортируемыми столбцами и картами. Если мне повезет я анимирую кольцевую диаграмму. Довольно странно, насколько похожи эти приложения, несмотря на то, что они созданы для совершенно разных компаний, работающих в совершенно разных отраслях.

Могло бы быть несколько причин, почему это произошло. Во-первых, сейчас очень сложно монетизировать чистый веб-контент - статьи, медиа или настольные приложения - потому что доход от рекламы, который всегда был низким, был подхвачен Google и Facebook, между которыми потребляется почти 65% рекламных расходов ,

Другая возможная причина заключается в том, что новые веб-API не принимаются разработчиками браузеров согласованным образом, что в конечном итоге сдерживает то, что могут делать даже JS-приложения. Apple, в частности, сопротивляется изменениям, отчасти потому, что чем более ценными становятся веб-приложения, тем меньше стимулов для развития App Store.

И это преимущество монолитов. Большие структуры могут делать предположения о типах приложений, которые мы создаем, и создавать эти варианты использования по умолчанию. Они могут предоставить множество учебных пособий и пример кода для общих веб-проектов. Дефляция,  как это может показаться: то, что сейчас нужно нашим проектам, - это не гибкость, а способ сократить чрезмерные затраты на разработку для Интернета.

Что это значит?

Прежде чем завершить, я хотел бы остановиться, чтобы сказать, что это за пост.

Это не прямой отказ от микробиблиотек. Напротив, если вы создаете контент-сайт, который нужно визуализировать за одну секунду на мобильном телефоне, а микролибы доставят вас в золотое окно 14Kb SYN / ACK, вы будете использовать их. Никаких возражений нет.

Это также не нападение на  React. Я думаю, что чистые компоненты и виртуальный DOM - очень важные идеи. Я просто думаю, что в будущем мы будем использовать более толстые абстракции, чем «ванильный реактив». Это могут быть фреймворки оболочки, которые абстрагируются от маршрутизации и управления состоянием, или они могут быть чем-то более простым, ближе к Create-React-App.

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

Я, конечно, могу ошибаться. Более разочаровывающе то, что я могу быть прав по совершенно неправильным причинам. Что-то может радикально «сорвать» Интернет и то, как мы его строим. Возможно, WebVR может включить новую эпоху игр HTML5. Или веб-сайты могут начать конкурировать с производительностью и временем рендеринга, то есть мы не будем использовать какие-либо библиотеки JavaScript вообще, микро или другие.

Что бы ни случилось, я уверен, что веб-разработчики никуда не денутся. Наша община процветает, энергична и украшена богатым пулом талантливых и изобретательных людей. У нас больше возможностей решать наши задачи, чем когда-либо прежде. Будем ли мы использовать React или Vue или что-то совершенно новое через три года, у меня нет ни капли сомнения в том, что мы это обсудим.


Джимми Брек МакКай

No Comments

Add a Comment