Эта статья является продолжением предыдущей статьи, которая находится здесь.

Введение в JavaScript модули. Часть 2

Эта статья является продолжением предыдущей статьи, которая находится здесь.

Существует несколько популярных конкурирующих форматов определения модулей в JavaScript. К ним относятся:

  • CommonJS - module.exports, применяется синтаксис, используемый в Node.js
  • Асинхронное определение модуля (AMD)
  • Универсальное определение модуля (UMD).

Но в ES6 (ES2015) был предложен единый стандарт модуля.

Все, что находится внутри модуля ES6, является закрытым по умолчанию и работает в строгом режиме (нет необходимости использовать директиву 'use strict'). Все, что должно быть доступно для внешнего использования помечается с использованием ключевого слова export:

  // lib.js
  export const PI = 3.1415926;

  export function sum(...args) {
   log('сумма', args);
   return args.reduce((num, tot) => tot + num);
  }

  export function mult(...args) {
    log('умножение', args);
    return args.reduce((num, tot) => tot * num);
  }

  // закрытая функция
  function log(...msg) {
    console.log(...msg);
  }

В качестве альтернативы первому варианту можно использовать один оператор экспорта. Например:

  // lib.js
  const PI = 3.1415926;

  function sum(...args) {
   log('сумма', args);
   return args.reduce((num, tot) => tot + num);
  }

  function mult(...args) {
   log('умножение', args);
   return args.reduce((num, tot) => tot * num);
  }

  // закрытая функция
  function log(...msg) {
   console.log(...msg);
  }

  export { PI, sum, mult }; // экспортируем для внешнего использования

Затем используется инструкция import для извлечения элементов из модуля в другой скрипт или модуль:

  // main.js
  import { sum } from './lib.js';

  console.log( sum(1,2,3,4) ); // 10

В этом случае lib.js находится в той же папке, что и main.js. Разрешается использовать как абсолютные ссылки на файлы (начинающиеся с /), так и относительные ссылки (начинающиеся с ./ или ../), а также полные URL-адреса.

Одновременно можно импортировать несколько элементов:

  import { sum, mult } from './lib.js';

  console.log( sum(1,2,3,4) ); // 10
  console.log( mult(1,2,3,4) ); // 24

При импорте название импортируемой функции может быть изменено для разрешения конфликтов имен:

 import { sum as addAll, mult as multiplyAll } from './lib.js';

  console.log( addAll(1,2,3,4) ); // 10
  console.log( multiplyAll(1,2,3,4) ); // 24

Наконец, все публичные элементы можно импортировать за раз используя знак*:

 import * as lib from './lib.js';

  console.log( lib.PI ); // 3.1415926
  console.log( lib.add(1,2,3,4) ); // 10
  console.log( lib.mult(1,2,3,4) ); // 24

Использование модулей ES6 в браузерах

Во время написания данной статьи модули ES6 поддерживались в браузерах на основе хромиума (v63 +), Safari 11+ и Edge 16+. Поддержка в Firefox начнется с версии 60.

Сценарии, которые используют модули, должны быть загружены путем установки атрибута type = "module" в теге <script>. Например:

  <script type="module" src="./main.js"></script>

или:

  <script type="module">
   import { something } from './somewhere.js';
   // ...
  </script>

Модули парсятся только один раз, независимо от того, сколько раз они используются на странице или в других модулях.

Файлы модулей должны иметь MIME-тип application/javascript.

Обычно тег <script> может извлекать скрипты c других доменов (сайтов), но модули извлекаются на основе принципа совместноого использования ресурсов между разными источниками (CORS). Поэтому модули на разных доменах должны устанавливать соответствующий HTTP-заголовок, например Access-Control-Allow-Origin: *.

Наконец, модули не будут отправлять файлы cookie или другие учетные данные d заголовках, если в тег <script> не будет добавлен атрибут crossorigin = "use-credentials", и ответ не будет содержать заголовок Access-Control-Allow-Credentials: true.

На этом все, а в последующих статьях мы продолжим говорить о применении модулей в JavaScript.