и как мы можем решить эту проблему.
Современные браузеры умеют многое, они понимают ES6, поддерживают ES модули, предоставляют удобные средства для разработки и отладки. Но достаточно ли этого и пользуемся ли мы всеми этими средствами эффективно?
Давайте выделим основные отличия между нашим исходным кодом и кодом который мы загружаем в наш браузер:
Код доставляется одним файлом — хотя все современные браузеры понимают формат ES модулей, большинство инструментов для разработки склеивает наш код в один большой файл.
Новые возможности javascript — согласно таблице совместимости только последние десктопные версии chrome поддерживают 100% новых свойств языка (и лишь часть экспериментальных свойств), другие браузеры нуждаются в транспиляции и полифилах для отсутствующих свойств.
@Component()
class Toolbar {}
Новые возможности css — cssdb содержит список поддерживаемых современными браузерами свойств css, остальные должны быть скомпилированы.
@media (480px <= width < 768px) {}
Commonjs модули — родной для node.js формат модулей не смотря на свою популярность и распространенность не поддерживается ни одним браузером и должен быть преобразован (ES модули поддерживаются новыми версиями node.js в экспериментальном режиме, большинство библиотек по прежнему поставляются в Commonjs формате).
const component = require('./component');
module.exports = function() {};
Простой импорт — (импорт начинающийся с имени пакета), браузерами не поддерживается, ведуться работы над черновиком стандарта (альтернативно уже сейчас можно консолидировать импорт в node.js и браузеры используя ES модули и переопределяя node.js загрузчик модулей для работы с абсолютными путями вида /node_modules/lodash/lib/get.js, но большинство библиотек этого не делает).
import get from 'lodash/get';
Импорт встроенных модулей — в браузерах также не поддерживается, требует замещение библиотеками.
import zlib from 'zlib';
Деструктуризация импорта — мы привыкли импортировать что угодно откуда угодно не заботясь о том, экспортируется ли требуемое нами значение:
import { Component } from 'react';
на самом деле библиотека экспортирует один объект React, который содержит свойство Component, а не набор свойств как можно было подумать.
Импорт сторонних форматов (css, json и т.д.) — браузерами не поддерживается и судя по всему не будет (за исключением импорта wasm).
import './style.css';
Декларации типов — typescript и flow стали очень популярны и помогают в разработке больших библиотек, но не имеют поддержки в браузерах.
const a: number = 1;
Метаязыки — scss, sass, less, typescript, coffeescript, pug не являются стандартными и требуют компиляции.
<style type=”text/scss”>
.logo {
color: white;
&.active {
color: red;
}
}
</style>
Шаблоны jsx — не являются стандартом и должны быть преобразованы используя createElement:
const element = <h1>Hello, world!</h1>;
Шаблоны vue — хотя и черпали вдохновение у веб компонентов, также не являются стандартом:
<template>
<div>This will be pre-compiled</div>
</template>
<script src="./my-component.js"></script>
<style src="./my-component.css"></style>
Относительные пути в веб компонентах — если вы привыкли разбивать ваши компоненты на скрипты шаблоны и стили, то вы знаете, что пути привязываются к корню проекта и компонент становится невозможно переносить и сложно переиспользовать в других проектах.
fetch('./my-button.html');
Если вы работаете с Angular:
Инъекция зависимостей — реализуется с помощью отражений и метаданных декораторов, требует компиляции.
Динамическая загрузка стилей по http — фреймворк не поддерживает эту возможность из коробки.
Как видим веб к которому мы привыкли далек от стандарта, хотя частично к нему и стремится. Задача hq сгладить эту разницу до тех пор пока многие вещи не войдут в стандарт, а другие не выйдут из обихода. hq это такой умный сервер, который делает ваш код чуть понятнее браузеру при этом преобразовывая только необходимый минимум и не склеивая все в одну кучу. Таким образом вне зависимости от выбранной технологии и фреймворка hq делает всю эту рутинную работу по обеспечению совместимости за вас и позволяет мгновенно приступить к разработке.
Какие еще преимущества дает hq?
- Отсутствие конфигурации
- Улучшенная отладка благодаря отсутствию бандлов
- Код в браузере максимально приближен к исходникам
- Простая структура проекта отраженная в браузере
- Видны все зависимости проекта, кто что грузит, почему и когда
- Полноценное использование инструментов браузера: загрузка / отладка / покрытие кода
- Очень быстрая работа сервера
- При использовании стандартов hq работает как обычный статический сервер
Попробуйте hq прямо сейчас:
npm i -g @hqjs/hq
и затем запустите в корне проекта:
hq
P.S.: Спасибо пользователю justboris за ценные замечания к предыдущей статье
Комментарии (27)
AxisPod
04.12.2018 15:46+1Не статья а франкенштейн, больше похоже на какую-нить страничку: Features.
Если уж писать подобную статью, то нужно как минимум сравнение с другими решениями, учитывая, что есть куда известнее и популярнее.Large Автор
04.12.2018 16:10Это не описание свойств конкретного решения. Статья о том какие преобразования нужно выполнить в исходном коде, чтоб он запустился в браузере. Это сравнение существующих стандартов с реальным кодом. Какое бы решение вы не использовали — вам прийдется настроить и сделать большинство из упомянутых преобразований. Понятно, что все новое воспринимается подозрительно, вы можете игнорировать предложенное решение и просто смотреть часть про стандарты (это большая часть статьи).
Если хотите сравнение hq с существующими решениями, то различия такие:
1. Не требует конфигурации
2. Не занимается бандлингом
3. Работает очень быстро
4. Спроектирована специально для комфортной разработкиJustDont
04.12.2018 18:45Это сравнение существующих стандартов с реальным кодом. Какое бы решение вы не использовали — вам прийдется настроить и сделать большинство из упомянутых преобразований.
Если вы говорите А, то не забывайте далее говорить и Б:
«А если вы используете некое zero-configuration решение, то большинство упомянутых преобразований всё равно должны быть (и будут) сделаны, но не вами, а магическим инструментом.»
А потом в особо запущеных случаях ваши попытки как-то это всё донастроить разобьются об идеологию магического инстумента о том, что у него всё «само».
В общем, нестареющая классика: the customers can have their Ford-T in any color, as long as it's black.Large Автор
04.12.2018 18:54Без конкретики это сложно обсуждать. Инструмент не преобразовывает вещи которые имеют неоднозначную трактовку, такие случаи возможно донастроить с помощью привычного всем .babelrc (пример — импорт svg как реакт компонента), но в подавляющем большинстве случаев нужен лишь перечисленный список который необходимо рутинно настраивать практически на каждом проекте. И тут как видите нет никакой магии, все достаточно просто.
JustDont
04.12.2018 19:12Магии нигде нет. Я не о чем-то сложном, а о просто неочевидном. Когда разработчик сидит и пишет билд-конфиги — билд-процесс для него очевиден. Когда разработчик накатывает инструмент, который всё делает «сам» — уже неочевиден. Если затем это всё требуется как-либо подкручивать (а если мы говорим про реальные проекты — то вероятность этого стремится к 100%) — полезность инструмента в лучшем случае равна примерно нулю: надо будет разобраться с билд-процессом, что практически эквивалентно самостоятельному написанию оного. А в худшем — ниже нуля: если то, что наворочено внутри инструмента — перегружено деталями и вариациями настолько, что разборки с этим займут больше времени, чем самостоятельно написанный билд-процесс.
Large Автор
04.12.2018 19:26Ну это тоже без конкретики очень сложно обсуждать. Я не думаю, что у вас проекты реальнее, чем у нас и могу сказать, что «подкручивать» как раз в основном не приходится. Если пишите стандарт, то и преобразований у вас не будет. Инструмент работает как полифил и сглаживает разницу между стандартом и привычкой (которая либо изменится либо войдет в стандарт). Все как раз прозрачно и очевидно, я не думаю, что вы можете оценить инструмент даже не попробовав. Подкрутка это добавление плагинов в привычный .babelrc, в этом нет ничего не очевидного или сложного, и это в большинстве наших реальных проектов не нужно.
JustDont
04.12.2018 20:21Я не думаю, что у вас проекты реальнее, чем у нас и могу сказать, что «подкручивать» как раз в основном не приходится.
Конечно, это зависит от масштаба, уровня, и времени жизни проектов. Что-то типовое и мелкое, что всю жизнь типовым и мелким и останется — может и не придётся подкручивать. Растущее в масштабе — придётся. Нетипичное — придётся.
Вам надо конкретику? Моя личная конкретика на текущий момент — например, такая: разработка модулей, внедряемых в определенное окружение. Необязательно через iframe (отсутствие фреймовости позволяет очень-очень многое сэкономить через общие ресурсы). Могут ли с такими вещами работать zero-configuration песочницы? Абсолютно нет. В большинстве случаев истерика уже случится тогда, когда выяснится, что в проекте нет ни одного .html, да и быть не может (если без iframe). А если даже и не случится — то мне нужен очень определенный список зависимостей (что очень логично, ресурсы-то общие), в то время как у инструментов, даже и не только zero-configuration — порой существуют очень даже особые мнения насчёт зависимостей.Large Автор
04.12.2018 20:55От масштаба и сложности и времени не зависит. Зависит от конкретного случая. У нас прекрасно работает проект на веб компонентах — которые как раз то, что вы описали. Суть в том, что не зависимо от того, что вы делаете, вы грузите это в браузер. Браузер понимает стандарты и с ними работает. hq умеет прозрачно преобразовывать разнообразие стилей к стандарту и делает это пофайлово, а зависимостями рулит сам браузер. В целом все, что делается при бандлинге можно делать и без бандлинга. Я могу представить ситуацию когда решение настолько далеко от веб стандарта, что пофайловая сборка вам не подойдет, но сложно сказать наилучшее ли это решение и нет ли альтернативы, где зависимостями может управлять сам браузер (у нас это так и происходит).
В целом решение проектировалось для разработки проектов, для того, чтоб можно было быстро начать и легко попробовать что-то. Так же оно оказалось полезным в старых проектах с большой кодовой базой и долгим сроком жизни так как позволило улучшить опыт дебага. Скажем, сделали вы, или лучше враги, библиотеку на тайпскрипте и хотите ее попробовать, а тестов нет и документации нет. С hq одной командой можно начинать пробовать, с остальными решениями — нужна сборка и пляски с бубном.
Я верю, что можно выдумать что-то совершенно сложное где hq работать не сможет, но так же верю, что можно и не выдумать, а ограничится решением близким к стандарту. Я так же не буду спорить, что вам hq не подойдет, но не стоит кричать, что у всех проекты стандартные и мелкие, и вот только для такого hq и хорош, это не правда.JustDont
05.12.2018 00:45У нас прекрасно работает проект на веб компонентах — которые как раз то, что вы описали.
У нас соль не в том, что мы подключаем куски без ифреймов, а в том, что эти куски пишутся разными конторами на разных технологиях. Одни в ангуляре, другие в реакте, третьи в vue, а четвертые вообще фиг пойми в чем. Или вообще не пишутся, а извлекаются из дремучего легаси лохматых годов (кто в энтерпрайзе работал, тот знает, что в ранних нулевых вебразработка не только была, но её иногда еще и до сих пор поддерживать надо, в 2018 году). И это всё надо по-максимуму дружить друг с другом, потому что через ифреймы это вообще будет абсолютно неподъемно по объемам загружаемого кода и ресурсов.
Бандлинг или не бандлинг — это вообще неважно на самом деле. Вебпак можно при желании заставить ничего не бандлить и оставлять всё как есть (правда тогда и вебпак не нужен, но тем не менее). Или бандлить только то, что бандлится хорошо (мелкие ресурсы, картинки, и тэ пэ, например).
Да и вообще я «наезжал» на zero-configuration, всё остальное тут не имеет особого значения. Zero-configuration на мой опыт создаёт гораздо больше проблем, чем решает, и даже когда люди считают, что их это не коснётся — это аналогично пословице про бекапы: есть те, которые делают, а есть те, которые еще пока не делают. Вот и тут, если проект живой и растущий, то неизбежная необходимость переконфигурёжки у кого-то уже наступила, а у кого-то еще пока нет.
Что до hq в продакшене, так это они сами, если чо, пишут:
Is it good for production?
It might help to serve small projects with very little dependencies. But general the answer is no, not yet.Large Автор
05.12.2018 00:49Так это ведь dev server, а не замена вебпаку или средство для продакшена, он для разработки и сделан и там тонкая реконфигурация как правило не нужна.
vintage
04.12.2018 21:34+2А автоматически устанавливать модули оно умеет? А резолвить циклические зависимости? А на прод тоже hq ставить? А в кордове как запускать? А под IE11 заведётся? А предзагрузить скрипты в кеш, чтобы в оффлайне работать, сможет?
Large Автор
04.12.2018 21:44-2Зависимостями занимается браузер. Средство для разработки, потому ответ на остальные вопросы — нет. Все что вы описали важно и нужно, но hq не для этого. Hq делает процес разработки и отладки комфортнее, для остального есть другие решения.
vintage
05.12.2018 02:29+2Зависимостями занимается браузер.
Вы не ответили на вопрос. Что там с циклическими зависимостями?
Hq делает процес разработки и отладки комфортнее, для остального есть другие решения.
И зачем он такой нужен, если для прода всё-равно надо всё перечисленное настраивать отдельно и огребать проблем от того, что для прода и дева код процессится абсолютно по разному?
Large Автор
05.12.2018 02:47-2В браузере с циклическими зависимостями все в порядке, они разрешаются согласно спецификации (условно импорты кешируются), hq разрешением зависимостей не занимается.
Нужен для комфортной разработки, без бандлинга оно бывает намного проще и приятней, видно что в проекте лежит, очень просто что-то пробовать и прототипировать, да много для чего. Как минимум не нужно все настраивать для разработки, это все-таки отдельные конфиги. Уже обсуждали разницу прода и дева — вас разработка в хроме не спасет от потенциальных проблем в условном ИЕ, тестированием нужно заниматься отдельно. Процессится оно должно одинаково, просто одно бандлится, другое — нет.
На сколько я знаю, есть планы сделать решение для прода, но пока это все специализированный dev server и решает он именно эту проблему.vintage
05.12.2018 03:56+2В браузере с циклическими зависимостями все в порядке
// a.js import B from './b.js' export default class A { b() { return new B } } // b.js import A from './a.js' export default class B extends A {} // index1.js import A from './a.js' // Uncaught ReferenceError: A is not defined // index2.js import B from './b.js' // All right
Ну такое себе "всё в порядке". Больше похоже на "счастливой отладки".
без бандлинга оно бывает намного проще и приятней
А что у вас за проблемы с бандлингом? Почему мне он не мешает? Я что-то делаю не так?
видно что в проекте лежит
Где видно? А почему с бандлами не видно?
очень просто что-то пробовать и прототипировать
А, ну если только поиграться и выбросить и никуда не выкладывать, то да, наверно удобно. Хотя, если б ещё и писать бесконечные импорты/экспорты не приходилось — было бы вообще чудесно. А то бывает список импортов чуть ли не больше собственно полезного кода.
Как минимум не нужно все настраивать для разработки, это все-таки отдельные конфиги.
Зачем отдельные? У меня вот они одинаковые. Я профнепригоден?
разработка в хроме не спасет от потенциальных проблем в условном ИЕ
Так я и спрашиваю заведётся ли это счастье в условном ИЕ? Или для ИЕ надо будет настраивать прод сборку?
Процессится оно должно одинаково
Вы предлагаете вручную подбирать конфиги идентичные
натуральнымhq?Large Автор
05.12.2018 04:17-2Ну такое себе «всё в порядке». Больше похоже на «счастливой отладки».
Ну так оно ожидаемо валится в таком случае, класс А ведь не определен в момент определения B.
А что у вас за проблемы с бандлингом? Почему мне он не мешает? Я что-то делаю не так?
У меня проблемы с постановкой брекпойнтов, а в особо запущеных случаях и вообще с отладкой в консоли так как имена внутри библиотек могут быть обфусцированы, покрытие кода работает криво, это навскидку.
Где видно? А почему с бандлами не видно?
Ну потому, что с бандлами вам нужен бандл аналайзер или еще что-то в этом роде, а без них у вас структура проекта видна во вкладке нетворк.
А, ну если только поиграться и выбросить и никуда не выкладывать
Можно не выбрасывать, а потом собрать и выложить. Не понимаю в чем тут проблема. Быстрый эксперимент бывает очень ценным оружием. Неужели вы никогда не запускали simpleHTTPServer, вот достойная замена как по мне.
Зачем отдельные? У меня вот они одинаковые. Я профнепригоден?
Это не ко мне вопрос. В вашей ситуации это может быть и подходящий вариант, но многие фреймворки имеют переменные окружения которые дают больше возможностей для отладки, для ускорения сборки на дев версии не нужна обфускация и не нужны все оптимизации как для прода, это может требовать разной конфигурации.
Или для ИЕ надо будет настраивать прод сборку?
Под сборку нужно настраивать в любом случае.
Вы предлагаете вручную подбирать конфиги идентичные натуральным hq?
Нет, я перевожу статью и ничего не предлагаю. В вашем случае я думаю вам этот инструмент не подойдет так как вы не испытываете боли от текущих dev серверов.vintage
05.12.2018 05:05Ну так оно ожидаемо валится в таком случае, класс А ведь не определен в момент определения B.
Проблема в том, что в зависимости от точки входа в цикл — он либо будет определён, либо не будет. И если с бандлом хотя бы можно посмотреть что он там насобирал, и увидеть, что порядок не верный, то тут это просто мистика — то работает, то не работает.
У меня проблемы с постановкой брекпойнтов, а в особо запущеных случаях и вообще с отладкой в консоли так как имена внутри библиотек могут быть обфусцированы, покрытие кода работает криво, это навскидку.
Бандлинг-то тут при чём? Описанные вами проблемы — следствие транспиляции языков, которая будет независимо от бандлинга.
а без них у вас структура проекта видна во вкладке нетворк.
Да какая структура? Сотни одновременных запросов, по которым даже не понятно сколько привнесла дополнительного кода подключённая новая библиотека ибо она будет нарезана на сотни файлов. Так что бандл-аналайзер вкладка нетворк никак не заменит. А структура проекта отлично видна на вкладке "sources", независимо от бандлинга.
Можно не выбрасывать, а потом собрать и выложить. Не понимаю в чем тут проблема.
В том, что сначала используется один инструмент, потом другой, когда можно было бы сразу использовать один инструмент.
фреймворки имеют переменные окружения которые дают больше возможностей для отладки
Каких, например?
для ускорения сборки на дев версии не нужна обфускация
Она и на проде не особо нужна как правило. В любом случае, добавить обфускацию отдельным шагом деплоя — не сложно. Зато весь остальной пайплайн останется единым.
не нужны все оптимизации как для прода
Какие ещё оптимизации?
Под сборку нужно настраивать в любом случае.
Некоторые инструменты позволяют этого не делать.
вы не испытываете боли от текущих dev серверов
Поэтому я запилил свой собственный :-D
Large Автор
05.12.2018 11:53тут это просто мистика — то работает, то не работает.
Да нет никакой мистики у вас сообщение об ошибке говорит в чем проблема. Точно так же можно посмотреть как выглядит сборка без бандла.
Описанные вами проблемы — следствие транспиляции языков, которая будет независимо от бандлинга.
При пофайловой транспиляции сорсмапы в разы аккуратнее. Если мы говорим про js -> js то вообще проблем не будет, а в случае с бандлом, попробуйте поставить брейкпоинт на выражение, попробуйте подебажить зависимость внутри нод-модулей, это все не так просто как вы описываете.
Да какая структура? Сотни одновременных запросов
Структура запросов, видно кто сделал запрос и зачем. и вы тактично опустили часть про код кавередж.
когда можно было бы сразу использовать один инструмент.
Да это ваша личная проблема и боязнь инструментов, не используйте, кто ж вам мешает то.
Каких, например?
Например реакт
Какие ещё оптимизации?
Оптимизация изображений, генерация сервис воркера, да мало ли что. Если это отдельная часть сборки — так это уже вторая сборка и у вас все равно 2 конфига.
Некоторые инструменты позволяют этого не делать.
Так не делайте, это не для вас инструмент, это мы уже выяснили. У нас прекрасно работает комбинация hq + parcel и нет никаких проблем.
Поэтому я запилил свой собственный :-D
Ну хорошо, что сделали что-то свое. Но я не совсем понимаю смысл всей этой полемики. Вы хотите узнать о преимуществах hq, так это можно сделать просто попробовав. Больше похоже на то, что вы хотите доказать, что инструмент отстой даже не пробовав и переубедить меня им не пользоваться. Я не думаю, что стоит продолжать.vintage
05.12.2018 16:43Да нет никакой мистики у вас сообщение об ошибке говорит в чем проблема.
Импорт есть, а класса нет. Никакой мистики, да.
При пофайловой транспиляции сорсмапы в разы аккуратнее.
Что там не аккуратного при склеивании исходников? Давайте сразу пример, а не голословных утверждений про "не поставить брейкпоинт в выражении".
Структура запросов, видно кто сделал запрос и зачем.
Видно лишь первого зависимого. Остальные зависимые сразу получают из кеша. Ну, такое себе "видно структуру".
Например реакт
Реакт — это возможность для отладки?
Оптимизация изображений
При каждой сборке? Зачем? Соптимизировали, закоммитили, всё, лежит, кушать не просит.
генерация сервис воркера
Это что за оптимизация такая? Тем более, которая включится только на проде и чёрт его знает как поведёт себя приложение.
да мало ли что
Мне вот как раз и интересно, что там может быть полезного, не высосанного из пальца.
это не для вас инструмент, это мы уже выяснили
Больше похоже на то, что вы хотите доказать, что инструмент отстой даже не пробовав и переубедить меня им не пользоваться.Вам стоит поработать над восприятием негативной обратной связи. Если всем так говорить, то ни популярность инструмент не обретёт, ни лучше не станет.
У нас прекрасно работает комбинация hq + parcel и нет никаких проблем.
Какую проблему решает hq, которую не решает parcel?
Вы хотите узнать о преимуществах hq, так это можно сделать просто попробовав.
Вместо того, чтобы наглядно показать эти преимущества (перед кем, кстати?) вы предлагаете читателям поставить себе кую-то тулзу и самим выискивать чем она может быть лучше? Ну, такое себе предложение.
Large Автор
05.12.2018 17:38Я вам ничего не предлагаю и не хочу спорить, вы даете фидбек не попробовав, я hq использую но поддержкой не занимаюсь. Так что это едва ли обратная связь. Вы делаете безапиляционные заявления, которые я бы назвал спорными, а многие из ни вообще чушь. Тон ваших заявлений мне не нравится потому обсуждать что-либо не вижу смысла. Вы не пользователь, проходите мимо, зачем поливать все помоями? Вам интересно — разбирайтесь сами, меня общение с вами лично утомляет.
justboris
04.12.2018 23:45А автоматически устанавливать модули оно умеет?
А должен? Я знаю, что такая фича есть в Parcel и мне она очень не понравилась. Решил попробовать сборщик в новом проекте: Parcel попытался установить новый модуль, используя Yarn (хотя я пользуюсь npm в основном). В package.json был модуль из приватного репозитория. Yarn ругнулся на то, что не может найти такой пакет (потому что про приватный репозиторий не знает) и уронил dev-server целиком. Удалил Parcel, вернулся на Webpack, который такими "умностями" не страдает.
По поводу остальных вопросов не знаю, но делать супер-комбайн из простого сервера не стоит.
justboris
04.12.2018 23:49+3Смешанный импорт — не является стандартом
Почему вы так решили? Вот же он в описании на MDN, безо всяких примечаний, а значит — стандарт: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Syntax
Large Автор
04.12.2018 23:51-2Вы правы, он действительно в стандартах, но у меня такое чувство, что он не работает во всех браузерах. Спасибо, разберусь — поправлю.
Large Автор
05.12.2018 00:00-2Работает видимо везде и это преобразование нужно для корректной обработки деструктуризации импорта, убираю из статьи. Спасибо!
justboris
05.12.2018 00:08+2Кстати, еще один пример сервера, который превращает старые модули в современные – это unpkg.com. При добавлении в конец url параметра
?module
там включается специальный препроцессинг для обработки bare-импортов.
Вот пример с
@angular/core
: https://unpkg.com/@angular/core@7.1.1/fesm2015/core.js?module Обратите внимание на импорты, они перезаписаны. Имплементация лежит вот здесь. Кроме того, unpkg хостит все npm-модули, так что с его помощью можно собрать любую онлайн демку где-нибудь в jsfiddle, просто используя import-синтаксис.
Может, кому-то пригодится.
Large Автор
05.12.2018 00:13Интересный проект, по сравнению с hq он занимается только преобразованием модулей и не помогает преобразовывать другие различия. С модулями к сожалению справляется не всегда пример unpkg.com/react@16.6.3/index.js?module
Это видимо потому, что модули cjs в данном случае.
dimoff66
Раньше остановка была у поликлиники, а теперь ее перенесли на 500 метров, и двери открывают только передние. А ходят автобусы раз в сорок минут, совсем о людях не думают, а мне пересаживаться потом с двойки на четверку и идти с сумками до остановки, а там еще светофор не сделали...(с) Бабушка вчера на автобусной остановке возмущалась. Не знаю почему вдруг вспомнилось.