Статьи

Использование модулей ES в браузере сегодня

Эта статья покажет вам, как вы можете использовать ES-модули в браузере сегодня.

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

Одним из распространенных решений является загрузка произвольных сценариев на веб-странице с использованием тегов <script> . Однако это приносит свои проблемы. Например, каждый сценарий инициирует HTTP-запрос, блокирующий рендеринг, что может привести к тому, что JS-страницы будут работать медленно и медленно. Управление зависимостями также усложняется, поскольку порядок загрузки имеет значение.

ES6 (ES2015) каким-то образом решил эту ситуацию, внедрив единый стандарт модулей. (Вы можете прочитать больше о модулях ES6 здесь .) Однако, поскольку поддержка браузером модулей ES6 изначально была плохой, люди начали использовать загрузчики модулей для объединения зависимостей в один кросс-браузерный файл, совместимый с ES5. Этот процесс представляет свои проблемы и степень сложности.

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

Современный ландшафт ES-модулей

Safari, Chrome, Firefox и Edge поддерживают синтаксис импорта модулей ES6. Вот как они выглядят.

 <script type="module"> import { tag } from './html.js' const h1 = tag('h1', ' Hello Modules!') document.body.appendChild(h1) </script> 
 // html.js export function tag (tag, text) { const el = document.createElement(tag) el.textContent = text return el } 

Или как внешний скрипт:

 <script type="module" src="app.js"></script> 
 // app.js import { tag } from './html.js' const h1 = tag('h1', ' Hello Modules!') document.body.appendChild(h1) 

Просто добавьте type="module" в теги скрипта, и браузер загрузит их как ES Modules. Браузер будет следовать всем путям импорта, загружая и выполняя каждый модуль только один раз.

Модули ES: график сети, показывающий загрузку

Старые браузеры не будут выполнять сценарии с неизвестным «типом», но вы можете определить резервные сценарии с атрибутом nomodule :

 <script type="module" src="module.js"></script> <script nomodule src="fallback.js"></script> 

Требования

Вам понадобится сервер, чтобы иметь возможность извлекать данные с помощью импорта, так как он не работает с протоколом file:// . Вы можете использовать npx serve для запуска сервера в текущем каталоге для локального тестирования.

Если вы хотите загрузить модули ES в другой домен, вам нужно включить CORS
,

Если вы достаточно смелы, чтобы попробовать это сегодня, вы все равно должны будете создать отдельные пакеты для старых браузеров. В браузере es-module-loader имеется полифилл, который соответствует спецификации. Тем не менее, это не рекомендуется для производства вообще.

 <script nomodule src="https://unpkg.com/browser-es-module-loader/dist/babel-browser-build.js"></script> <script nomodule src="https://unpkg.com/browser-es-module-loader"></script> <script type="module" src="./app.js"></script> 

Производительность

Пока не выбрасывайте свои инструменты сборки, такие как Babel и Webpack, поскольку браузеры все еще реализуют способы оптимизации выборки. Тем не менее, в будущем с модулями ES будут иметь место ошибки и улучшения производительности.

Почему мы связываем

Сегодня мы связываем наш JavaScript, чтобы уменьшить количество HTTP-запросов, так как сеть часто является самой медленной частью загрузки веб-страницы. Это все еще очень актуальная проблема сегодня, но будущее блестящее: модули ES с поддержкой HTTP2 для потоковой передачи нескольких ресурсов с помощью push-серверов и браузеров, реализующих предварительную загрузку .

Предварительная загрузка

ссылка rel = ”modulepreload” скоро появится в ближайшем к вам браузере. Вместо того, чтобы браузер разрешал импорт всех модулей один за другим, создавая сетевой водопад, подобный этому…

 <script type="module" src="./app.js"></script> 
 ---> GET index.html <--- ---> GET app.js <--- ---> GET html.js <--- ---> GET lib.js <--- 

… Вы сможете html.js сообщить браузеру, что на страницах требуются html.js и lib.js , что позволяет контролировать этот водопад:

 <link rel="modulepreload" href="html.js"> <link rel="modulepreload" href="lib.js"> <script type="module" src="./app.js"></script> 
 ---> GET /index.html <--- ---> GET app.js ---> GET html.js ---> GET lib.js <--- <--- <--- 

HTTP2 с сервером Push

HTTP2 способен выдвинуть несколько ресурсов в одном ответе по сравнению с HTTP1.1, который может доставить только один. Это поможет свести к минимуму количество поездок по сети.

В нашем примере было бы возможно доставить index.html , app.js и html.js в одном запросе:

 ---> GET /index.html <--- index.html <--- app.js <--- html.js <--- lib.js 

Кэширование

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

асинхронный / отложенный

По умолчанию модули ES не блокируют рендеринг, как <script defer> . Если ваши модули не нужно выполнять в том же порядке, в котором они определены в HTML, вы также можете добавить async выполнение для их выполнения, как только они будут загружены.

Библиотеки

Популярные библиотеки начинают публиковаться как модули ES, однако они все еще нацелены на сборщики, а не на прямой импорт.

Этот скромный небольшой импорт вызывает водопад из 640 запросов :

 <script type="module"> import _ from 'https://unpkg.com/lodash-es' </script> 

Как насчет того, чтобы сделать правильные вещи и импортировать только одну нужную нам функцию? Нам осталось всего 119 запросов :

 <script type="module"> import cloneDeep from 'https://unpkg.com/lodash-es/cloneDeep' </script> 

Это всего лишь пример, демонстрирующий, что lodash-es еще не создан для загрузки непосредственно в браузер. Для этого вам все равно нужно будет создать собственный пакет с ES-модулями в качестве цели.

Поддержка браузера

Как показано в следующей таблице, поддержка браузером модулей ES хорошая (и постоянно улучшается).

Время начать экспериментировать с ES-модулями в браузере сейчас. Достаточно скоро вы сможете использовать их во всех современных браузерах без транспилятора или упаковщика, если хотите.