05. Browser Modules
Спецификация ES6 модулей поддерживается в браузерах при помощи тега <script type="module">
. Выполняемый в таком скрипте код поддерживает ES6 и спецификацию модулей (импорты/экспорты).
Основные особенности:
Для подключения используется
<script type="module">
.Нативные модули в
"strict mode"
по умолчанию;Все определения в модулях не являются частью глобального объекта.
window
по прежнему доступен, ноthis
в модуле являетсяundefined
Модули по умолчанию асинхронны работают как
deferred
скрипты (такое же как у<script type="text/javascript" defer />
).
Со временем нативные JS-модули будут поддерживаться браузерами без дополнительных утилит. Сейчас браузерной поддержки почти нет. Поэтому ES-модули используются в сочетании с системами сборки, такими как webpack и другими, при подключённом Babel.
Скрипты и модули не смешиваемы друг с другом:
Переменные, определенные в скриптах недоступны в модулях
В скриптах нельзя использовать ES6 импорты/экспорты, но можно библиотеки модулей (UMD и др.).
Module execution
Главное отличие нативных модулей от обычных скриптов заключается в том, что обычные скрипты загружаются и выполняются сразу же, блокируя парсинг html. Нативные модули по умолчанию имеют поведение deffered
скриптов вне зависимости от того, импортируют ли они что-нибудь или нет. По умолчанию скрипты в модулях не блокируют, загружаются параллельно и выполняются, когда страница завершает парсинг html. Можно изменить это поведение, добавив атрибут async
, тогда скрипт будет выполнен, как только он загрузится.
The order should be
2.js
,1.js
,3.js
.
Пример с async
:
The fast-downloading scripts should execute before the slow ones.
Import paths
Импорт внутри модуля:
он может начинаться и заканчиваться пробелами;
он должен быть абсолютным URL-ом или:
он должен начинаться с
“/”
,“./”
, или“../”
..js
расширение не может быть опущено в директивеimport
;
Еще одно отличие модулей - это возможность загружать файлы с других доменов (например, загрузка модулей с CDN).
sctipt
attributes
sctipt
attributesКак в классических скриптах, есть много атрибутов, которые можно использовать в script type=”module”
.
Атрибут
type
используется для установки типа"module"
.src
мы используем, чтобы загрузить файл с определенным URI.defer
не нужен для скриптов типа“module”
, так как это поведение по умолчаниюЕсли вы используете
async
атрибут, модуль будет выполнен сразу же как только будет доступен, безdefer
поведения по умолчанию, когда скрипты выполняются по порядку после анализа документа, но перед событиемDOMContentLoaded
.integrity
по-прежнему может быть использован, чтобы убедиться, что выбранные файлы (например, изcdn
) не были подменены на что-то другое.атрибут
crossorigin
дает возможность контролировать обмен данными, которые отправляются с помощью CORS запросов.nonce
— это генерируемый случайным образом хеш, который добавляется в заголовок на сервер и добавляется в тегscript
.
Используйте события onload
и onerror
у script
элемента, чтобы обнаружить, может ли модуль быть успешно выполнен или не может загрузиться.
nomodule
attribute
nomodule
attributeАтрибут nomodule
означает, что скрипт должен быть выполнен только если браузер не поддерживает ES модули:
В данном примере кода если браузер поддерживает модули, то будет загружен и выполнен app.js
, в противном случае будет выполнен bundle.js
.
CORS and credentials
Unlike regular scripts, module scripts (and their imports) are fetched with CORS. This means cross-origin module scripts must return valid CORS headers such as Access-Control-Allow-Origin: *
.
Most CORS-based APIs will send credentials (cookies etc) if the request is to the same origin, but fetch()
and module scripts are exceptions – they don't send credentials unless you ask for them.
You can add credentials to a same-origin module by including the crossorigin
attribute (which seems a bit weird to me, and I've questioned this in the spec). If you want to send credentials to other origins too, use crossorigin="use-credentials"
. Note that the other origin will have to respond with the Access-Control-Allow-Credentials: true
header.
Also, there's a gotcha related to the "Modules only execute once" rule. Modules are keyed by their URL, so if you request a module without credentials, then request it with credentials, you'll get the same without-credentials module back. This is why I've used a ? in the URLs above, to make them unique.
References
Last updated
Was this helpful?