В этой статье сделан обзор системы модулей в ES6.
Старая система модулей JavaScript
В JavaScript нет встроенной поддержки модулей, но сообщество создало несколько прекрасных решений этой проблемы. Среди самых популярных можно выделить два таких:
Система модулей CommonJS: предпочтительно для использования в Node.js
Особенности:
— компактный синтаксис
— спроектировано для синхронной загрузки зависимостей
— главная среда использование — бек-енд
Asynchronous Module Definition, более известен как AMD
Самой популярной реализацией является библиотека RequireJS
Особенности:
— более сложный синтаксис, позволяющий работать AMD, без использования eval() (или этапа компиляции)
— спроектировано для асинхронной загрузки зависимостей
— в большинстве случаев используется в клиентском JS
ES6 модули
Основная цель ECMAScript 6 модулей создание единый формат для тех, кто использует CommonJS и AMD.
Стандарт ES6 модулей делится на две части:
— декларативный синтаксис для импорта и экспорта
— программный API — для настройки того как модули загружаются и опциональной загрузки.
Есть два типа экспортов: именованные и по умолчанию(default)
Модуль может экспортировать несколько сущностей просто указав слово export перед определением функции, класса, переменной. Эти экспорты можно различить по их именам, по тому они называются named exports.
// utils.js import * as moment from "moment"; export function getUtcTimeStamp(x) { return moment().utc().valueOf(); } export function tomorrowTimestamp() { return moment.utc().add(1, "days").hours(0).minutes(0).seconds(0).millisecond(0).valueOf(); } //controller.js import { getUtcTimeStamp, tomorrowTimestamp } from 'util'; console.log(getUtcTimeStamp()); // 1513003142000 console.log(tomorrowTimestamp()); // 1513036800000
В примере ниже показывается как загрузить весь модуль и присвоить ему какое-то имя
//controller.js import * as util from 'util'; console.log(util.getUtcTimeStamp()); // 1513003142000 console.log(util.tomorrowTimestamp()); // 1513036800000
Эквивалентный код с использованием синтаксиса CommonJS будет выглядеть так
// utils.js const moment =require("moment"); function getUtcTimeStamp(x) { return moment().utc().valueOf(); } function tomorrowTimestamp() { return moment.utc().add(1, "days").hours(0).minutes(0).seconds(0).millisecond(0).valueOf(); } //controller.js var getUtcTimeStamp=require("utils.js").getUtcTimeStamp; var tomorrowTimestamp=require("utils.js").tomorrowTimestamp; console.log(getUtcTimeStamp()); // 1513003142000 console.log(tomorrowTimestamp()); // 1513036800000
Default export
Модули, которые экспортируют только одно значение довольно популярны в Node.js сообществе. Также они популярны в фронт-енд разработке, где часто используется практика один класс на модуль.
Пример default export
// Controller.js export default class { ... }; //index.js import Controller from 'Controller'; let ctrl=new Controller();
Одновременное использование named и default экспортов
Этот паттерн очень популярен в JavaScript. Библиотека это одна функция, а все дополнительные сервисы предоставляются через через свойства этой функции. Библиотеки jQuery, Underscore.js используют этот шаблон.
Структура Underscore.js с использованием CommonJS
//underscore.js var _ = function (obj) { // library code }; var each = _.each = _.forEach = function (object, iter, ctx) { ... }; module.exports = _; }; //index.js var _ = require('underscore'); var forEach = _.forEach;
Если использовать ES6 модули, то функция _ это dafault экспорт, а each и forEach именованные экспорты. И как оказалось можно использовать два типа экспортов одновременно.
Underscore.js EcmaScript 6 version
//underscore.js export default function (obj) { // library code }; export function forEach (object, iter, ctx) { ... }; export { forEach as each }; }; //index.js import _, { forEach } from 'underscore';
С первого взгляда обе версии выглядят одинаково, но ES6 версия имеет плоскую структуру, а CommonJS вложенную. Что делает возможным статический анализ кода.
Заключение
ECMAScript 6 модули имеют компактный синтаксис, статическую структуру модулей, решают проблему несовместимости стандартов CommonJS и AMD