Здравствуйте, коллеги.

В последнее время мы эпизодически возвращаемся к теме JavaScript. Нас особенно заинтересовала очередная книга из серии «You Don't Know JS», посвященная стандарту ES6 (Кайл Симпсон):



Кстати, может быть кто-то уже присматривался к новой книге Адама Бодуха "JavaScript at Scale" и хотел бы увидеть ее на русском языке?



Об этом в опросе. А под катом — критическая (январская) статья мистера Коди Линдли, помогающая задуматься о том, насколько мир JavaScript готов к переменам.



В мире веб-разработки на JavaScript для больших предприятий создаются такие решения и применяются такие инструменты, которые должны хотя бы в минимальном объеме функционировать в условиях ECMAScript 3 (стандарт ES3). Вы вправе удивиться – а как такое может быть? В конце концов, ECMAScript 5 был готов еще в июне 2011 года и поддерживается всеми современными браузерами, в том числе, IE 9 (если не считать строгого режима).

В этой статье мы поговорим о том, почему многие, если не все JavaScript-разработчики с больших предприятий по-прежнему должны учитывать ES3, а также обсудим ряд стратегий для тех, кто хочет сегодня пользоваться возможностями ES5/ES6. Наконец, я расскажу, почему сам так не делаю.

IE8 никуда не делся. Привыкните к этому.

Поддержка IE 8, 7 и даже 6 по-прежнему может оставаться актуальным требованием на предприятии. Хотите вы того или нет, согласны ли с этим — так есть. Иными словами, использование возможностей JavaScript ES5 или ES6 в боевом коде — во многих корпоративных окружениях по-прежнему остается делом будущего.

Код, создаваемый корпоративными разработчиками, и инструменты, с которыми они работают, в принципе должны поддерживать ES3-окружения. Например, большинство виджетов в Kendo UI (не считая мобильных) тестируются и поддерживаются в IE7+. Даже бегло изучив практически любое JavaScript-решение, написанное для корпоративных разработчиков, убеждаешься, что большинство таких решений создаются с учетом стандартов ES3.

Это не должно удивлять никого, кто набил руку на корпоративной разработке. Однако порой трудно смириться с тем, что многие новейшие инструменты JavaScript (например, Angular 1.3) тестируются и разрабатываются без всякой оглядки на идеальную работу в чистых ES3-средах, да и могут вообще там не прижиться. Как минимум, там они могут спровоцировать серьезные неприятности, потребовать обходных маневров и полифиллов.

В настоящее время корпоративные инструменты зачастую воспринимаются и превозносятся как исключительно надежные, первоклассные, проверенные временем, заточенные на решение только самых сложных задач, какие могут вставать перед программистом. Но реальность такова, что большая часть enterprise-кода на JavaScript и соответствующих инструментов написаны и стандартизированы под спецификацию, которая была окончательно доработана 16 лет назад.

Бесспорно, стандарт ES3 проверен временем, но вот насчет его высокой надежности и пригодности для большого предприятия, думаю, многие нынешние JavaScript-разработчики могли бы поспорить. В конце концов, возможности из новых спецификаций ES5 и ES6 по определению создавались именно для исправления огрехов ES3 и для того, чтобы современный JavaScript позволял решать столь сложные задачи, какие сегодня перед ним ставятся. Причем можно не сомневаться, что одних лишь возможностей, реализованных 16 лет назад, недостаточно для современной JavaScript-разработки.

Каков план действий для разработчика?

Представляю, насколько мрачно все это звучит для среднестатистического JavaScript-разработчика из большой корпорации. Я, как специалист по JavaScript, сам хотел бы, чтобы все мои коллеги уже могли приступать к работе с новыми возможностями JavaScript, не дожидаясь их окончательной доработки и реализации. Браузеры и корпорации, будьте вы прокляты!

Но между желаемым и действительным большая разница. Думаю, именно поэтому и делаются полифиллы для имитации новых возможностей, люди компилируют JavaScript для старых браузеров или вообще забрасывают клиентский код и осваивают Node. Не смейтесь, так бывает. Клиент и браузер в самом деле могут настолько достать разработчика, что он очертя голову кинется на поиски более качественной среды выполнения для JavaScript.

Серьезно, самое разумное для корпоративного разработчика, использующего инструментарий ES3 и пишущего код, работающий в среде ES3 — просто делать свое дело. Думаю, вам никто не мешает мечтать, что когда-нибудь можно будет забыть о поддержке старых браузеров (ES3) и создавать только современный нативный код под ES5 или ES6. Разумеется, enterprise-разработчикам придется ждать отмирания старых браузеров — прямо скажем, на большом предприятии это произойдет не скоро.

ПОЧЕМУ Я НЕ ПОЛЬЗУЮСЬ ПОЛИФИЛЛАМИ ИЛИ КОМПИЛЯЦИЕЙ

Лично я никогда не пытался использовать масштабные полифиллы и не прибегал к компиляции, чтобы сделать рабочий ES3-код из ES5 или ES6. Да, я эпизодически прибегал к полифиллам, но мне никогда не удавалось справиться с теми сложностями и издержками, которые сопряжены со всесторонним применением полифиллов или процедурой компиляции (то есть, создать рабочий ES3-код из исходного кода ES5 или ES6). Подводные камни, дополнительные полифиллы, ограничения в использовании и неполноценные возможности — вот что удерживало меня от этого. Например, попробуйте просто почитать обо всех деталях, связанных с использованием возможностей ES6 при применении нового компилятора 6to5.

Это не означает, что я не смаковал, не программировал и не использовал новые возможности JavaScript, когда у меня появлялся такой шанс. Тоже так поступайте. Дело в том, что когда от меня требуется поддержка среды ES3, я избираю путь наименьшего сопротивления, заключающийся в следующем: обходиться такими инструментами и писать такой код, который максимально близок к «металлу» ES3. Наконец, тот лишь факт, что инструмент требует ES5+, еще не означает, что он сможет работать в условиях ограничений, присущих другому стороннему решению, связанному с полифиллами или компиляцией – конечно, если это решение не будет заранее тестироваться и поставляться с необходимыми полифиллами, что по понятным причинам (размер файла, синхронизация, дублирование и т.д.) обычно не делается.

Итак, я почти не прибегал ни к полифиллам, ни к компиляции. Я считаю, что создание приложения на JavaScript — само по себе безумно сложное предприятие. Малейшие усложнения большого корпоративного проекта, издержки или бюрократия (тем более — сторонняя бюрократия) оправданны лишь в том случае, если дают принципиальный выигрыш в разработке. В моей практике такого выигрыша ни разу не удалось бы достичь, добавив новые возможности JavaScript в базу кода, рассчитанную на ES3 — настолько это сложно.

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

Стратегии использования новых возможностей ES6+ JavaScript на предприятии

В оставшейся части этой статьи мы исследуем 3 стратегии использования новых возможностей ES6+ JavaScript на предприятии.

СТРАТЕГИЯ 1. ПРИМЕНЕНИЕ ВСТАВНЫХ ПОЛИФИЛЛОВ

До отказа полизаполнить среду ES3 возможностями из стандартов ES5 и ES6 (и даже из ES7) очень просто — достаточно включить файл shim.js из проекта core.js в HTML-документ.

shim.js включается в HTML-документ в качестве первого JavaScript-файла для запуска/синтаксического разбора, и весь остальной код JavaScript, следующий за ним, можно задействовать возможности полифиллов как нативные (ниже приведены примеры кода из core.js).

console.log(Array.from(new Set([1, 2, 3, 2, 1]))); // => [1, 2, 3]
console.log('*'.repeat(10));                       // => '**********'
Promise.resolve(32).then(console.log);             // => 32
setImmediate(console.log, 42);                     // => 42


Учтите, что в core.js не только предоставляется полный набор ECMAScript-совместимых полифиллов, но и следующие нестандартные возможности JavaScript, доступные при использовании core.js вместо shim.js.



СТРАТЕГИЯ 2. ИСПОЛЬЗОВАНИЕ ПОЛИФИЛЛОВ ПО ПРИНЦИПУ OPT-IN

Хотим мы того или нет, рассмотренные выше вставные полифиллы добавляют в ES-среду новые возможности во время исполнения. Любой ценой. Если вас это не устраивает, то есть другой вариант. В проекте core.js также предлагаются явно подключаемые (opt-in) полизаполнения, реализующие новые возможности, но эти возможности можно использовать и выборочно, активируя каждую из них по отдельности. Подобная практика применяется в библиотеках наподобие lodash, предлагающих одно глобальное значение (например _), на которое завязаны все возможности.

Чтобы явно подключать возможности ES5 и ES6 в вашем коде, можно включить файл library.js из core.js. Затем можно применять новые возможности ECMAScript по мере необходимости, написав код, обращающийся к тем возможностям метода, которые завязаны на глобальном значении ‘core’. Подобная ситуация реализована в следующем образце кода (пример взят из core.js).

var log  = core.console.log;
log(core.Array.from(new core.Set([1, 2, 3, 2, 1]))); // => [1, 2, 3]
log(core.String.repeat('*', 10));                    // => '**********'
core.Promise.resolve(32).then(log);                  // => 32
core.setImmediate(log, 42);                          // => 42


СТРАТЕГИЯ 3. ПРЕДВАРИТЕЛЬНАЯ КОМПИЛЯЦИЯ ES6+ В ES5 С ПОСЛЕДУЮЩИМ ПРИМЕНЕНИЕМ ПОЛИФИЛЛОВ ДЛЯ ES3

Стандартные возможности ES5 и ES6 нельзя напрямую компилировать в код ES3 (например, использовать старые возможности для написания более новых, эквивалентных им). В противном случае вы серьезно ограничите те возможности. которые можно было бы транслировать. Было бы реально использовать этап предварительной компиляции, на котором код ES6 компилируется в ES5, а затем задействовать вставной полифилл shim.js, чтобы преодолеть последний перегон до ES3.

Для этого можно воспользоваться новым транспилятором 6to5 и создать предварительную задачу сборки, в которой используется gulp, преобразующий ES6 в немодифицированный (ванильный) ES5. Затем, согласно документации 6to5, чтобы получить полноценную среду времени исполнения для ES6, также потребуется подготовить эту среду при помощи полифиллов regenerate runtime, shim.js и ES6 module loader (обратите внимание: я использую client/shim.js из core.js, где обеспечивается поддержка ES3).

HTML-файл, содержащий код, скомпилированный при помощи 6to5, может выглядеть примерно так:

<!DOCTYPE html>
<html>
<body>

<script src="runtime.js"></script>
<script src="client/shim.js"></script>
<script src="es6-module-loader.js"></script>

<script>
    System.parser = '6to5'; // задать es6-module-loader.js для работы с 6to5
    // далее идет код, скомпилированный с 6to5 
</script>
</body>
</html>


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

Что насчет стороннего кода?

Теоретически, если вы полизаполнили или полизаполнили + предварительно скомпилировали код, чтобы обеспечить использование новых возможностей JavaScript в среде ES3, то сможете смело задействовать сторонние инструменты, работающие только в средах ES5+, верно? Нет!

Практически единственный вариант, позволяющий безопасно использовать в среде ES3 сторонний инструмент – это прямая поддержка вашего конкретного полифилла/компилятора на уровне стороннего кода. В противном случае посылка из первого абзаца этого раздела остается весьма стремной и временной. Помните, все это запиливание новых возможностей в старые окружения связано с теми или иными подводными камнями, сложными уловками и личными мнениями. Не следует рассчитывать, что сторонний разработчик имел дело с подобными деталями, если только вы лично не убедились, что эти разработчики в точности ориентируются на вашу среду. Если вы не вполне меня понимаете, просто учтите, что сторонние разработчики вряд ли будут тестировать полифиллы и скомпилированный вывод. Как правило, если для синтаксического разбора стороннего кода требуется среда ES5+, то имеется в виду реальная среда ES5+.
Книги по JavaScript

Проголосовало 112 человек. Воздержалось 60 человек.

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

Комментарии (15)


  1. VasilioRuzanni
    21.08.2015 13:21
    +7

    «Полизаполнения»? Серьезно? :D


    1. ph_piter
      21.08.2015 13:55
      -2

      Вы-таки считаете, что это полифиллы? mattweb.ru/component/k2/item/74-kratko-o-polizapolnenii


      1. VasilioRuzanni
        21.08.2015 14:01
        +10

        Конечно, «полифиллы» — или же polyfills (без перевода). Но «полизаполнения» очень уж слух/глаза режет. Думаю, я не один такой :)


      1. SelenIT2
        21.08.2015 14:02
        +4

        На мой взгляд, уж всяко лучше прижившееся заимствование «полифил(л)», чем нелепая и нелогичная механическая полуадаптация чужого слова, вызывающая совершенно не те ассоциации (у меня, например, первая ассоциация с «полизаполнением» — скрипт автоматического заполнения форм, а вовсе не «костыль»/«подпорка» для недостающей системной функциональности).

        Не говоря о том, что «полизаполнение» почти невозможно выговорить, а при чтении не сразу понятно, кто тут чего полизал:)


        1. ph_piter
          21.08.2015 14:12
          +5

          Окей, полифиллы


          1. stas404
            21.08.2015 19:59

            Я извиняюсь за вопрос не в тему — хотел поинтересоваться по поводу книги «Exploring ES6» за авторством Axel Rauschmayer.
            Не светит ли?


      1. batyrmastyr
        21.08.2015 16:44

        Я хоть и не люблю тупую транслитерацию, но полизаполнения это недоперевод. Если уж на то пошло, то лучше выкинуть «поли» (совсем не тот смысл придаёт) и оставить только «заполнитель». Можно ещё из переводов shim на «прокладку» / «компенсатор» покрутить, но уж лучше как SelenIT2 «подпоркой» назвать.


        1. SelenIT2
          21.08.2015 17:05

          Да вот и с «заполнителем» сомнения. В англоязычном мире для таких решений сложилась метафора «замазки» или «шпаклевки», которой «заполняют/заделывают щели и выбоины в стене» (получая ровную поверхность, с которой приятно работать). Но у нас, насколько я в курсе, такая метафора вообще не в ходу, у нас, по-моему, недостающую функциональность принято скорее «подпирать костылем». «Прокладка», в принципе, тоже вариант…


      1. MTonly
        21.08.2015 22:35
        +1

        Как вариант, скриптовая реализация, эмулирующий скрипт или эмуляция.


        1. SelenIT2
          22.08.2015 00:13

          Вот да, пожалуй, скрипт-эмулятор вообще идеально попадает в точку. Даже если речь об эмуляции самих скриптов (напр. новых методов Array, не работающих в IE8). Просто «эмуляция», имхо, слегка слишком общо, но тоже может подойти…


        1. batyrmastyr
          24.08.2015 09:33
          +3

          Наполовину в шутку, наполовину всерьёз предлагаю назвать соломой — только представьте «Вась, ты молодец конечно, но ослику соломки подстелить не судьба?» )


  1. rock
    21.08.2015 14:05
    +6

    Старенькая статья. Какбэ 6to5 давно в babel переименован, да и ссылочки на core-js поправить не мешало бы, например, форматирование даты давно в отдельную библиотеку вынесено, а абстрактные ссылки (по ссылке ES7) удалены (вернее, разделены) как из предложений для ES7, так и из babel и core-js.


    1. trikadin
      30.08.2015 02:55

      И дело не только в устаревании названий/ссылок — бабель сильно вырос как инструмент, и вполне спокойно можно компилить код даже для IE8 (если нужно ниже, то сложнее, да) с ограничениями по геттерам, разве что.


      1. rock
        30.08.2015 04:38

        Извините, но я не совсем понимаю как связано у вас «сильно вырос как инструмент» и «можно компилить код даже для IE8», хоть, вроде, я и ответственен здесь за обеспечение кроссплатформенной совместимости — читай, полифилы. Код и на момент написания статьи, и сейчас, прекрасно работает как в IE8, так и, например, в IE6 — с точки зрения JavaScript разница между ними минимальна, что нельзя был реализовать тогда — нельзя реализовать и сейчас, например, те же дескрипторы. Разве что до определенного момента (апреля, если не ошибаюсь) полифилы ES5 из core-js не были включены в babel/polyfill по умолчанию, только ES6+.


        1. trikadin
          30.08.2015 15:44

          Меньше багов и больше возможностей. Возможно, да, моё сообщение несколько необдуманное. В целом — я просто хотел выразить согласие с тем, что статья устарела, и сказать, что писать код даже для старых браузеров на ES6+ (с ограничениями, опять же) вполне реально.