Comments 38
На мой взгляд самый неочевидный момент с модулями, после common.js:
То есть:
Это можно понять и по спекам и по вашей статье, но просто это немного необычно, после common.js, так скажем не ожидаемо. Но это легко исправить:
export const foo = bar;
!==
exports.foo = bar;
То есть:
// lib.js
export function foo() {}
// app.js
import lib from './lib';
console.log(lib.foo); // undefined
Это можно понять и по спекам и по вашей статье, но просто это немного необычно, после common.js, так скажем не ожидаемо. Но это легко исправить:
import * as lib from './lib';
Ну так common Modules !== es6))
Для этого есть export default, а не *. А вы превели именованый экспорт, разумеется, что там будет undef, что же еще?
Для этого есть export default, а не *. А вы превели именованый экспорт, разумеется, что там будет undef, что же еще?
Честно говоря, мне тоже дефолт экспорт кажется местами нелогичным, но уж как сделали — так сделали. Бабель сейчас такое поведение фолбэчит — модулям, которые изначально написаны на ES6, он ставит не-enumerable экспортируемое свойство __esModule = true, и если потом при импорте модуля он видит, что такое свойство не импортируется, то он смотрит: если есть с именем default, то вернёт default, если нету — вернёт exports того модуля целиком. Но гораздо правильней и безопасней делать вот так:
Хотя и непривычно, конечно))
import * as fs from 'fs';
Хотя и непривычно, конечно))
А нет ли способов реэкспортировать нужные объекты прямо из под имени директории?
Например есть папка components в ней есть файлы Email.js и Inbox.js в которых есть классы Email и Inbox соответсвенно. Мне бы хотелось чтоб я мог их импортировать с помощью
import Components
ну или import Components from 'components'
В python это возможно сделать с помощью создания __init__.py файла в папке components и импорта нужных вещей туда. Нет ли в JS какого нибудь такого файла в стиле index.js который автоматически читается если сделать import этой папке?
Например есть папка components в ней есть файлы Email.js и Inbox.js в которых есть классы Email и Inbox соответсвенно. Мне бы хотелось чтоб я мог их импортировать с помощью
import Components
ну или import Components from 'components'
В python это возможно сделать с помощью создания __init__.py файла в папке components и импорта нужных вещей туда. Нет ли в JS какого нибудь такого файла в стиле index.js который автоматически читается если сделать import этой папке?
Commonjs в ноде при указании дерриктории действительно пытается заимпортить index.js, import в babel как раз делает фолбэк для импорта через require, но вот как и во что это выльется на клиенте зависит уже от библиотеки\сборщика который вы используете.
Плюс в отличие от питона нет никакой явной нотации на то как должен выглядеть index.js в таком случае. Не натыкался на то как бы это выглядело в спеках, если кто-то знает хотел бы прочитать про подобный вариант. Но в целом с реэкспортом можно весьма удобно собирать такие компоненты.
Плюс в отличие от питона нет никакой явной нотации на то как должен выглядеть index.js в таком случае. Не натыкался на то как бы это выглядело в спеках, если кто-то знает хотел бы прочитать про подобный вариант. Но в целом с реэкспортом можно весьма удобно собирать такие компоненты.
Не совсем понял, что в таком случае делает babel. Использую именно его с browserify. Могу ли я пользоваться вариантом с index.js в этом случае? Пишу для браузера (Reactjs), но всё склеиваю в один файл.
Можете.
Поведение импорта в ноде и в ES6 отличается, бабель делает так, чтобы вы этого не заметили. Лучший вариант, чтобы понять, как — это посмотреть на результат работы бабеля)
Поведение импорта в ноде и в ES6 отличается, бабель делает так, чтобы вы этого не заметили. Лучший вариант, чтобы понять, как — это посмотреть на результат работы бабеля)
Только мне до сих пор не понятно как в браузер будут приходить сотни и миллионы маленьких файликов-модулей. Сколько лет разными средствами от этого убегали, и вот вам :(
Service workers для этих задач поднимать как-то странно. Вещи не совсем связанные.
Service workers для этих задач поднимать как-то странно. Вещи не совсем связанные.
HTTP/2 должен решить эту проблему
Мне кажется, что помимо накладных расходов на сами запросы, есть ещё накладные расходы на использование файловой системы. Так что вопрос объединения модулей в 1 файл, всё же стоит и с HTTP/2. IMHO
Мне кажется, тут все очень зависит от проекта. В каких-то проектах необходимо все объединять в один файл, в каких-то лучше все как-то хранить модульно. Например, на прошлой работе все сжималось в один (или два, точно не помню) файла, общий размер которого около 2мб (одного ExtJS фиг знает сколько было). В проекте были разные тарифные планы, и, например, фришный пользователь мог видеть только 20% от всего приложения. Получается, что для него грузилась куча ненужного кода.
А расходы на использование файловой системы в обычном среднестатистическом проекте — микроскопические. Картинок всяких грузится обычно в разы больше, чем скриптов. Да и никто ведь разом не будет загружать все 100 модулей. А вот если будет — то да, лучше в один файл все :)
А расходы на использование файловой системы в обычном среднестатистическом проекте — микроскопические. Картинок всяких грузится обычно в разы больше, чем скриптов. Да и никто ведь разом не будет загружать все 100 модулей. А вот если будет — то да, лучше в один файл все :)
Пример — АПИ Яндекс.Карт состоит из нескольких тысяч модулей.
Вообще проекты следующие KISS и вообще правилам декомпозиции любят состоять из кучи маленьких «reusable» кусочков.
Вообще проекты следующие KISS и вообще правилам декомпозиции любят состоять из кучи маленьких «reusable» кусочков.
например, фришный пользователь мог видеть только 20% от всего приложения. Получается, что для него грузилась куча ненужного кода.Не понимаю, причём тут это. Что мешало сделать несколько bundle's, самый простой из которых загружал только нужное обычному посетителю, в обычных ситуациях, а менее популярные зависимости раскидать по другим bundle-ам?
А расходы на использование файловой системы в обычном среднестатистическом проекте — микроскопические. Картинок всяких грузится обычно в разы больше, чем скриптов.Почему же? Если речь идёт о вёрстке, то разработчики, зачастую, используют спрайты или base64 dataurl, и число запростов уменьшается многократно (вплоть до 1-го запроса к CSS файлу, где всякая мелочь лежит как base64). А картинок связанных с контентом web-сайта может и не быть вовсе. Или быть мало, не всё же новостные порталы.
Да и никто ведь разом не будет загружать все 100 модулей.Ну у меня в проектах обычно только SCSS файлов около 100-ни, если не больше (import-ы). да и JS-ов на данный момент порядка 80-и.
Не понимаю, причём тут это. Что мешало сделать несколько bundle's, самый простой из которых загружал только нужное обычному посетителю, в обычных ситуациях, а менее популярные зависимости раскидать по другим bundle-ам?
Я привел пример, когда подход «все в одном файле» был неоправдан. Мешало то, что проект очень древний (перепиленный ExtJS 3.4) и как такового загрузчика, вроде RequireJS, не было. И не было нормального разбиения по модулям, все друг с другом было очень связано. Переписывать и переделывать — очень дорого для бизнеса + получился бы велосипед с треугольными колесами (хотя, на мой взгляд, поддерживать все эту хрень стоит еще дороже, чем переписать).
Почему же? Если речь идёт о вёрстке, то разработчики, зачастую, используют спрайты или base64 dataurl, и число запростов уменьшается многократно (вплоть до 1-го запроса к CSS файлу, где всякая мелочь лежит как base64). А картинок связанных с контентом web-сайта может и не быть вовсе. Или быть мало, не всё же новостные порталы.
Тут не про верстку имелось в виду. Не обязательно бть новостным порталом, чтобы грузить много изображений. Возьмите тот же Яндекс.Диск, Flickr, Pinterest, какая-нибудь CRM-ка (например, какие-нибудь аватары пользователей). Ну 30-40 картинок может быть легко, и на этом фоне загрузка 5-10 скриптов — мелочь, тем более Вы же знаете про кэширование?
Ну у меня в проектах обычно только SCSS файлов около 100-ни, если не больше (import-ы). да и JS-ов на данный момент порядка 80-и.
SCSS тут причем? И вы разом загружаете пользователю все эти 80 js-модулей? Вы же сами утверждали, что необходимо загружать только нужное сначала. Сколько у Вас критически важных модулей из этих 80?
загрузка 5-10 скриптов — мелочь, тем более Вы же знаете про кэшированиеЛегко может стоить вам от 500ms до 5000ms (например, GPRS) при загрузке страницы. Это очень много. К тому же JS-функциональность всё чаще является не «рюшечками» а острой необходимостью.
Не понимаю, что вы мне пытаетесь доказать. В то время когда некоторые разработчики заранее подготавливают gzip-ы для nginx_gzip_static, вы говорите о +-10 скриптах? :) Во frontende-е уже давно борьба идёт на уровне «спичек», а не «брёвен».
SCSS тут причем?Технология позволяет использовать импорты не задумываясь о последствиях, т.к. компилятор сам всё соберёт в 1 файл. Это удобство легко приводит к тому, что SCSS-файлы плодятся в огромном количестве (просто потому что декомпозиция это очень удобно). Привёл в качестве примера, сколько может быть мини-файлов в рядовом проекте.
И вы разом загружаете пользователю все эти 80 js-модулей? Вы же сами утверждали, что необходимо загружать только нужное сначала. Сколько у Вас критически важных модулей из этих 80?Пользователь загружает 1 минифицированный файл со всем необходимым. Администратор загружает 2 файла. Некоторые страницы сайта могут потребовать загрузку 3 файла (например в нём может быть огромный Ckeditor и плагины к нему).
И всё это работает автоматически. Вы просто определяет в конфигурации сборки какие файлы в какой бандл дожны попасть. Всю чёрную работу возьмёт на себя requireJS или его аналог (да хоть самописный, какая разница). Система зависимостей в действии. Вам больше нигде не потребуется писать <script type=«text/javascript src=»..."></script> указывая требуемые файлы вручную.
Вас куда-то не туда понесло. Мы обсуждали, в данном контексте, насколько я понял, что если не склеивать все JS в один / несколько файлов, то будет расти нагрузка на сервере, т.к. будет много операций на чтение каждого файла.
Причем тут вообще GPRS? Разговор у нас шел вообще о, цитирую, «ещё накладные расходы на использование файловой системы». И все, о чем, я говорил, было связано именно с этой темой. Я не утверждал, что плохо или хорошо склеивать все в один файл — все зависит от проекта, где-то это нужно, где-то нет. А вы тут препроцессоры еще приплели :)
Легко может стоить вам от 500ms до 5000ms (например, GPRS) при загрузке страницы. Это очень много. К тому же JS-функциональность всё чаще является не «рюшечками» а острой необходимостью.
Причем тут вообще GPRS? Разговор у нас шел вообще о, цитирую, «ещё накладные расходы на использование файловой системы». И все, о чем, я говорил, было связано именно с этой темой. Я не утверждал, что плохо или хорошо склеивать все в один файл — все зависит от проекта, где-то это нужно, где-то нет. А вы тут препроцессоры еще приплели :)
Нас обоих куда-то не туда понесло. Попробую заново. Модульная система располагает к тому, что число модулей. т.е. файлов, может быть очень большим. 100, 200, 1000, 10'000. Если их никак не склеивать, то нагрузка на файловую систему будет. Если отдавать их разом тем более. К тому же как правильно заметил kashey с latency не поспоришь. Т.е. если там будут иерархические ветвления include-ов, ничего хорошего из этого не выйдет.
Соответственно есть реальная необходимость иметь возможность объединения модулей в 1 или несколько файлов. Или размещения нескольких модулей в рамках одного файла. Учитывая, что мы обсуждаем нативный функционал, то интересует как раз нативное решение. Объединение сопряжённое с правкой исходных кодов (автозамены include-ов и export-ов) на поддерживаемые конструкции мы можем и сейчас без поддержки ES6 модулей вообще.
Соответственно есть реальная необходимость иметь возможность объединения модулей в 1 или несколько файлов. Или размещения нескольких модулей в рамках одного файла. Учитывая, что мы обсуждаем нативный функционал, то интересует как раз нативное решение. Объединение сопряжённое с правкой исходных кодов (автозамены include-ов и export-ов) на поддерживаемые конструкции мы можем и сейчас без поддержки ES6 модулей вообще.
все зависит от проекта, где-то это нужно, где-то нет.В некоторых проектах вообще нет подключаемых JS-ов. Там, соответственно, это не нужно. Но зачем это обсуждать? :)
Ничего кроме bulk запросов не может решить проблему временых задержек на получения данных. Прямо каноническое бутылочное горлышко получается.
Требуется на сервере разрулить зависимости, и передать «предсказанную» кучу модулей. Иначе все будет работать как игра с DVD — вжик-вжик, вжик-вжик, ууууууу… С latency не спорят.
Требуется на сервере разрулить зависимости, и передать «предсказанную» кучу модулей. Иначе все будет работать как игра с DVD — вжик-вжик, вжик-вжик, ууууууу… С latency не спорят.
Можете посмотреть jspm.
Весьма удобная штука надстройка над SystemJS, которая даёт возможность импортить файлы разного «формата» + сборщик. Который на уровне импортов и конфига собирает это всё в один бандл или если хотите можете собирать это помодульно и т.д…
Весьма удобная штука надстройка над SystemJS, которая даёт возможность импортить файлы разного «формата» + сборщик. Который на уровне импортов и конфига собирает это всё в один бандл или если хотите можете собирать это помодульно и т.д…
browserify + babelify в данный момент спасают.
У меня есть ощущение, что эта система модулей сделана так, чтобы максимально легко транспилиться в любую другую — AMD, require, common. Поэтому можно легко писать в es6 стиле, а потом browserify или webpack.
Упс.
С ES6 мы будем не билдить, а бандлить)) Уже даже есть сборщики ES6 модулей, просто погуглите по гитхабу)
Многое уяснил. Спасибо за статью. Осталось не совсем ясным использование «from». В случае requireJS мы может влиять на то, какие конкретно файлы будут загружаться, и нужно ли что-либо вообще догружать. А как с этим делом обстоит в ES6 модулях? Судя по тексту, каждый файл — отдельная область видимости, которые с друг другом не пересекаются, но что если речь идёт о будущем frontend-а и мы хотим разместить несколько модулей в 1 файл (к примеру, для экономии запросов)?
Заюзайте вебпак)
Вообще, у меня пока ощущение, что эта система модулей сделана так, чтобы с минимальными потерями транспилиться в любую другую — по сути, такой метаязык, который можно потом хоть в AMD, хоть в CommonJS, хоть в require) И это круто. Но, конечно, это мои личные ощущения.
Вообще, у меня пока ощущение, что эта система модулей сделана так, чтобы с минимальными потерями транспилиться в любую другую — по сути, такой метаязык, который можно потом хоть в AMD, хоть в CommonJS, хоть в require) И это круто. Но, конечно, это мои личные ощущения.
Заюзайте вебпак)Да заюзать то я могу что угодно и когда угодно. Но ведь тут речь идёт о нативном представлении, о возможности самого языка или инфраструктуры связанной с ним. К примеру, в PHP есть autoloader-ы классов. И можно одновременно использовать несколько разных лоадеров, которые могут работать по совсем разной логике (очень давно не работал с PHP, могу в чём-нибудь ошибаться).
Вводя модульную систему в JS, подразумевая, что оная должна работать и в браузере, мы должны иметь возможность влиять на неё. Т.е. как то управлять механизмом работы этих ES6-Modules. Но пока что я ничего подобного ни в 1-ой статье не углядел.
Робко надеюсь на то, что этот вопрос будет удачным образом решён позднее. А транспилить код туда сюда я не люблю. Чем нативнее решение, тем надёжнее, и тем удобнее его debug-ить. К примеру, недавно я стал сталкиваться в Web Developer Tools с тем, что многие ошибки на страницах детектируются не там, где они произошли, а в каком-то абстрактном xml.js (которого даже не существует), в котором нужного кода нет и в помине. Оказалось что дело в sourceMap. Или вот в nodeJS обычный require, в непонятных мне случаях, все SyntaxError-ы в моих файлах детектирует в своих внутренних файлах (таких как vm.js), и я не могу понять ни в каком файле ошибка, ни в какой строке, ни на какой позиции. Потому что в стектрейсах просто чушь. И мне приходится некоторые require оборачивать в try catch, просто для того, чтобы узнать хотя бы файл, в котором ошибка произошла (я ведь знаю, что я require-ю).
Я предпочитаю использовать нативные решения (привет кофе-скрипт), за исключением тех случаев, где альтернатива предлагает просто бездну удобств (например scss, less и шаблонизаторы) и минимум геморроя.
Вот здесь сейчас идёт разработка спецификации загрузчика модулей, который как раз позволит подгружать всё динамически, асинхронно и условно.
Я сначала транспилил код, а теперь вообще пользуюсь babel-node, чтобы не прикручивать кучу галпа сверху. Не замечал проблем с дебагом. И ошибка с require у вас очень странная, не попробуете рабочий пример создать?
И да, я заметил логическое несоответствие: вы не любите транспилить, но юзаете кофескрипт?
Я сначала транспилил код, а теперь вообще пользуюсь babel-node, чтобы не прикручивать кучу галпа сверху. Не замечал проблем с дебагом. И ошибка с require у вас очень странная, не попробуете рабочий пример создать?
И да, я заметил логическое несоответствие: вы не любите транспилить, но юзаете кофескрипт?
Очень хороший вопрос. Предполагаю, что это будущее будет решаться в будущем.
Если вам надо программно управлять зависимостями вы можете использовать
System.import
который позволяет асинхронно загружать скрипты с интерфейсом промисовЕще одним отличием (на сколько я понял) import от require() является то, что import можно располагать только в начале кода, в то время как require() может быть где угодно и подгружать модули даже динамически.
Поправьте, если ошибаюсь.
Поправьте, если ошибаюсь.
Да, абсолютно верно. Импорт можно располагать только на самом «верхнем» уровне модуля, т. е. нельзя вот так
И даже, как я писал в статье, если написать импорт после чего-либо другого, то он всё равно «всплывет».
Вот здесь сейчас идёт разработка спеки для загрузчика модулей, с помощью которого как раз и можно будет реализовать динамическую, условную и прочую подгрузку модулей.
if (weNeedFS) {
import * as fs from 'fs';
}
И даже, как я писал в статье, если написать импорт после чего-либо другого, то он всё равно «всплывет».
Вот здесь сейчас идёт разработка спеки для загрузчика модулей, с помощью которого как раз и можно будет реализовать динамическую, условную и прочую подгрузку модулей.
Как-то очень смущает требование один файл — один модуль для скриптового языка, код которого активно передается клиенту по сети.
На самом деле, это не требование. Просто по факту сейчас в спецификации нет ничего, кроме описания структуры модуля и того, как устроен импорт/экспорт. А до тех пор, пока не появится описание того, как это всё должно лежать на фс, как резолвиться и так далее, реализаций у нас не будет. Поэтому пока ждём, пока они допишут стандарт (около года), и юзаем эту модульную систему, транспиля её в ноду, браузерифай и прочее.
Sign up to leave a comment.
Тонкости модульной системы ECMAScript 2015 (ES6)