require javascript что это

Что такое require и module.exports

November 09, 2015

Данная статья является прочтением и переосмыслением перевода Node.js, Require и Exports статьи-оригинала Node.js, Require and Exports.

С помощью этих команд Node.js осуществляет взаимодействие своих модулей между друг другом.

Команда require подключает один модуль к другому. Команда module.exports делает модуль доступным для других модулей.

В Node.js все штуки видны друг другу только в рамках одного и того же файла. Под штуками я подразумеваю переменные, функции, классы и их члены.

Например, у нас есть файл misc.js следующего содержания:

Дело в том, что Node.js состоит из блоков, называемых модулями; и каждый отдельный файл по своей сути — отдельный блок (модуль), чья область видимости изолирована от других таких же блоков (модулей).

Теперь перед тем как мы узнаем, как сделать эти штуки видимыми вне модуля, рассмотрим более подробно, как загружаются модули в Node.js.

Другими словами можно сказать, что в Node.js служебное слово require служит для подключения одного независимого модуля (файла) к другому независимому модулю (файлу). Принцип подключения через require заключается в создании в целевом модуле объекта и помещении в этот объект подключаемого модуля.

Конечно же, до тех пор, пока наш модуль ( some_module ) ничего не отдает, все приведенные примеры бесполезны.

А чтобы наш модуль ( some_module ) что-нибудь отдал, мы будем использовать служебное слово module.exports :

Вот теперь наш модуль ( some_module ) стал гораздо более полезным:

В результате в целевом модуле будет создан объект someModule со свойством x = 5 ( someModule.x ) и методом summ ( someModule.summ ).

Есть ещё такой способ отдать штуки из нашего модуля:

Разница между этими подходами не велика, но важна. Как видно, в данном случае мы экспортируем функцию напрямую:

Всё это к тому, что потом ее будет легче использовать:

Выгода от использования такого способа заключается в том, что в данном случае нам не важно, будет ли ваш модуль представлять контейнер c экспортируемыми значениями или нет.

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

Что, по сути, является упрощенной записью следующего кода:

Источник

Модульный подход к разработке web-приложений с использованием JavaScript: AMD и RequireJS

Подключение загрузчика

Имеем следующую структуру каталогов:
Для начала, подключим в index.html загрузчик. Будем использовать RequireJS:

Описание модуля

Опишем наш модуль в /js/module.js с помощью define:
Первый аргумент — строка, название модуля, не обязателен. Вторым аргументом передаются зависимости в виде массива строк, также опционально. Третий аргумент — функция-фабрика, которая выполняется только после удовлетворения всех зависимостей (загрузки перечисленных файлов). В неё в качестве аргументов передаются экспортируемые зависимостями переменные. А возвращать она должна сам модуль. В данном случае это объект с одним полем.

Использование

В /js/app.js подключим нужные модули с помощью JS и выполним свой код:
Module при этом не будет доступна в глобальной области видимости, как и другие переменные, экспортируемые библиотеками из зависимостей. Не смотря на то, что библиотека jQuery с версии 1.7 поддерживает AMD-архитектуру, она является исключением: экспортирует свой доллар в глобальную область видимости. Скорее всего, это сделано для сохранения совместимости с армией плагинов, написанных за многие годы.

Конфигурация

Заключение

Надеюсь, концепция AMD зацепила вас, так же, как и меня. Она помогает избежать хаоса при использовании большого количества JS-файлов в разработке, подталкивает к написанию реюзабельного кода, снимает ответственность за подключение файлов с бэкенда. А если у вас реально большое MVC-приложение из пары десятков файлов, то подобная система просто незаменима.

Исходный код из статьи доступен в репозитории на GitHub.
Happy hacking!

Источник

Правильное использование require в node.js

Предисловие

Не так давно проект, на котором я работаю в данный момент, начал использовать модульную систему ES2015. Я не буду заострять внимание на этой технологии JavaScript, т.к статья совсем не об этом, а о том как технология сподвигла меня к одной мысли.

Как многие знают, ES2015 Modules представляют собой импортирование/экспортирование скриптов крайне схожее по синтаксису с python и многими другими языками программирования. Пример:

Все, кто интересовался модулями JavaScript знают, что импортирование и экспортирование возможно только на верхнем уровне модуля (файла с кодом).

Следующий грубый пример кода вызовет ошибки:

В отличие от ES2015 Modules — в модульной системе node.js импортирование и экспортирование возможны на любом уровне вложенности.

Аналогичный код на node.js не вызовет ошибку:

Преимущество такого способа в том, что модули необходимые в обработчике явно импортированы внутри и не засоряют пространство имен модуля (особенно актуально, если импортируемый модуль нужен только в одном обработчике). Так же появляется возможность отложенного экспортирования данных модуля.

Разбор полетов

В большинстве задач для которых используется node.js — front-end или основной веб-сервер, и высокая нагрузка на node.js частое явление. Пропуская способность вашего сервера должны быть максимально возможная.

Измерение пропускной способности

Для измерения пропускной способности веб-сервера используется великолепная утилита от Apache — ab. Если вы еще с ней не знакомы, то настоятельно рекомендую это сделать.

Код веб-сервера одинаков за исключением обработчиков.
Тест запускался на node.js 6.0 с использованием модуля ifnode , сделанного на базе express

Импортирование модулей непосредственно в обработчик

Результат:

Импортирование модулей в начале файла

Результат:

Анализ результатов

Импортирование модулей в начале файла уменьшило время одного запроса на

23%(!) (в сравнение с импортированием непосредственно в обработчик), что весьма существенно.

Note: пробовал «прогревать» кеш для случая с непосредственным импортированием модулей в обработчик (перед запуском утилиты ab, модули были уже закешированы) — производительность улучшалась на 1-2%.

Источник

Модули JavaScript

require javascript что это. Смотреть фото require javascript что это. Смотреть картинку require javascript что это. Картинка про require javascript что это. Фото require javascript что это

При разработке front-end части приложения на языке JavaScript, мы можем столкнуться с рядом традиционных проблем. Все они решаются при помощи модульных подходов. Ниже мы рассмотрим самые популярные подходы для описания модулей в JavaScript, которые существуют на сегодняшний день.

Итак, какие проблемы имеются в виду:

Большие файлы. Довольно часто возникает такая ситуация, когда в проекте есть файлы, названные в стиле app.js или common.js, в которых все просто свалено в одну кучу: функции, хелперы, виджеты и т.д. Работать и поддерживать код в таких файлах довольно тяжело. Приходится постоянно прокручивать туда-сюда, выискивая нужный кусочек кода, ставить много закладок при помощи IDE, чтобы не потерять нужные места в файле. Также есть тенденция, что чем больше размер файла, который содержит в себе кучу общей логики, тем быстрее он продолжает расти. Плюс ко всему, в большой команде это может стать причиной постоянных конфликтов в системе контроля версий.

Более трудной в обнаружении причиной ошибок может стать дублирование подключения одних и тех же файлов. Например, есть файл с куском кода, который вешает обработчик события на какой-либо dom-элемент. Ваш коллега может не заметить, что этот файл уже был подключен, и подключает его еще раз. В результате обработчик будет выполняться два раза, что может привести к неприятной ошибке, которую довольно трудно заметить сразу.

Неструктурированный и не очевидный код. Еще одна довольно неприятная ситуация — когда нет четких границ, разделяющих логические куски кода. Когда, не вникая в код, сразу и не скажешь, какие другие части приложения он использует.

Первые модули

Изначально в JS не было возможности создавать настоящие модули. Хотя раньше это и не требовалось: на сайтах было относительно маленькое количество JS-кода. В основном нужно было где-то «прикрутить карусель», где-то красивое анимированное меню, и на этом все. Но затем web-приложения по сложности интерфейса и насыщенной функциональности начали догонять традиционные настольные. И тогда стал популярным так называемый паттерн «модуль».

Этот подход работает достаточно просто: создается немедленно-вызываемая анонимная функция-обертка, которая возвращает публичный интерфейс модуля, а вся остальная реализация инкапсулирована в замыкании. Это помогает решить две проблемы из вышеперечисленных: количество глобальных переменных сильно уменьшается, а сам код становится немного нагляднее благодаря тому, что мы разграничиваем его на логические куски. Но проблема управления зависимостями и порядком подключения файлов остается открытой.

CommonJS

Первый стандарт, который описывает API для создания и подключения модулей, был разработан рабочей группой CommonJS. Этот стандарт был придуман для использования в серверном JS, и его реализацию можно увидеть, например, в node.js.

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

НО! В браузере, просто так, такой синтаксис не заработает. Для этого нужно использовать специальный сборщик. Например, популярны browserify или Brunch, которые работают на node.js. Эти инструменты довольно удобны, их функциональность не ограничивается только лишь возможностью создавать CommonJS-модули, и многие разработчики предпочитают использовать их в своих проектах. Суть у них одинакова: сборщик проходится по дереву зависимостей модулей и собирает все в один файл, который в свою очередь будет загружаться браузером. Даже при разработке в debug-режиме нужно постоянно запускать сборщик из командной строки, или, что удобнее, запускать watcher, который будет следить за изменениями в файлах и автоматически производить сборку. Стоит заметить, что отлаживать приходится не исходные файлы, а то, что сгенерирует сборщик. Если вы не планирует отлаживать ваш код в старых браузерах, то это не будет проблемой, потому что сборщики умеют генерировать Source Maps, благодаря которым результирующий сжатый файл будет связан с исходниками. Это позволит вести отладку так, как будто вы работаете с самим исходным кодом. Также, сборка в один файл — это не всегда хорошо. Например, если мы хотим подгружать модуль удаленно, с CDN, или загружать часть кода только по требованию.

Будущее уже наступило

В новом стандарте ECMAScript 6, помимо всяких крутых штук, описан новый синтаксис для создания и подключения модулей.

Один модуль, как и в CommonJS, — это один файл. Область видимости также ограничена этим файлом. Ключевое слово export экспортирует нужные значения в остальные части программы. Его можно использовать где угодно: посреди кода модуля или в конце, экспортируя все скопом.

…или сразу несколько.

Либо можно импортировать весь модуль в качестве объекта со всеми экспортированными значениями.

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

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

Чтобы импортировать значение по умолчанию, достаточно лишь не использовать фигурные скобки.

В качестве единственного параметра необходимо передавать путь к модулю. В результате выполнения System.import() возвращается объект Promise. Таким образом, поток выполнения не блокируется и код, который не имеет отношения к импорту модуля, будет выполняться дальше.

Браузеры еще толком не поддерживают новый синтаксис, но возможность использовать уже есть. В этом вам поможет один из специальных трансляторов, например, Babel. Как и в случае с CommonJS, нужно запускать транслятор из командной строки или ставить watcher, благодаря которому исходники, написанные на ES6, при изменении будут преобразовываться в кроссбраузерную форму.

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

Вот уже несколько лет подход под названием Asynchronous Module Definition позволяет разбивать код приложений на модули во всех популярных браузерах (IE6+), используя при этом только возможности браузера.

AMD — это подход к разработке, который позволяет создавать модули таким образом, чтобы они и их зависимости могли быть загружены асинхронно и параллельно. Это позволяет ускорить загрузку страницы, так как загрузка JS-модулей не будет блокировать загрузку остального контента сайта. Плюс, AMD дает возможность загружать модули по мере их востребованности. Например, есть страница со сложным модальным окном, в котором сосредоточено много логики: разные «визарды», несколько форм и т.д. При этом предполагается, что окно будет использоваться крайне редко. В таком случае, AMD позволяет загружать JS-код для этого окна не со страницей, а перед тем, как оно будет открыто пользователем.

Самая популярная реализация подхода AMD — библиотека RequireJS.

RequireJS

Скачать библиотеку можно с официального сайта, или же можно воспользоваться любым популярным пакетным менеджером. Например, с NuGet можно установить ее, выполнив команду Install-Package RequireJS.

В RequireJS методы require и define имеют несколько вариаций.

Метод define может принимать три параметра:

Первый параметр — это id модуля. id можно использовать вместо пути к файлу, чтобы подключить модуль как зависимость другого модуля, но только когда файл с кодом модуля уже был загружен в браузере. На самом деле, это необязательный параметр. И не просто необязательный, его даже нежелательно использовать в разработке. Он, скорее, нужен для корректного управления зависимостями в том случае, если в одном файле определено сразу несколько модулей. Оптимизационный инструмент, использующийся для сборки модулей в один файл для production, автоматически добавляет эти id.

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

В данном случае первый параметр — это массив зависимостей модуля. Чтобы определить зависимость, нужно просто добавить в массив строку, содержащую путь к модулю или его id. Последний параметр — функция-фабрика, которая занимается созданием модуля. Эта функция выполнится только тогда, когда все зависимости модуля будут загружены, и принимает в качестве аргументов экспортированные значения со всех зависимостей. Внутри функции находится реализация модуля, которая не доступна извне. В конце с помощью вызова return экспортируется сам модуль. Экспортировать можно все, что угодно: обычную функцию, конструктор, объект, строку; в общем, любой тип данных. Важно понимать, что функция-фабрика выполняется только один раз, когда мы впервые подключаем модуль как зависимость. Остальные модули, которые тоже подключат эту зависимость, получат уже закешированное значение модуля.

Есть одна проблема — вызов define может выглядеть вот так:

Также можно определить модуль как простой объект.

Такие модули удобно использовать как набор констант.

Есть возможность делать вложенные вызовы require внутри callback-функции или внутри определения модуля.

Еще одно существенное отличие такого варианта вызова require заключается в том, что подключаемые файлы начнут загружаться только тогда, когда поток выполнения дойдет до вызова функции. Благодаря этому есть возможность загружать модули только по требованию или по условию.

Подключение

При помощи первого параметра baseUrl можно указать путь, относительно которого будут загружаться все JS-файлы. Если файлы вдруг переедут в другое место, то достаточно в одном месте поменять корневой путь. Если его не указать, то базовой будет директория, в которой находится файл самой библиотеки require.js. Параметр path позволяет «мапить» пути к модулям, чтобы использовать потом более короткие варианты.

RequireJS позволяет загружать не только JS-файлы, но и, например, HTML, используя плагин text.

В данном примере require загрузит файл module.html и вернет строку, содержащую HTML-код файла. Это удобно для работы с клиентскими шаблонами, не нужно мучатся с HTML-кодом внутри JS-файлов.

Сборка

Загружать много мелких файлов удобно при разработке и отладке, но не очень производительно, поэтому не подходит для production. И тут на помощь приходит утилита оптимизации r.js, которая идет в поставке с require.js.

Работает эта утилита на JS, поэтому на компьютере должен быть установлен node.js. Перед тем как запускать оптимизацию, нужно ее сконфигурировать. Для этого в приложении нужно создать файл app.build.js, который будет содержать обычный JS-объект с набором параметров.

Будет удобно добавить эту команду, например, в pre-build event в Visual Studio, чтобы JS-код собирался в тот же момент, когда запускается компиляция проекта.

Profit

Итак, выгоды, которые дает использование RequireJS:

Источник

Понимание (всех) «модульных» форматов и инструментов JavaScript

require javascript что это. Смотреть фото require javascript что это. Смотреть картинку require javascript что это. Картинка про require javascript что это. Фото require javascript что это

Доброго времени суток, друзья!

Представляю вашему вниманию перевод статьи «Understanding (all) JavaScript module formats and tools» автора Dixin.

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

IIFE модуль: шаблон JS модуля

Определяя переменную в JS, мы определяем ее как глобальную переменную. Это означает, что такая переменная будет доступна во всех файлах JS, загружаемых на текущей странице:

Для того, чтобы избежать загрязнения глобального пространства имен, можно использовать анонимную функцию:

Вуаля, глобальных переменных больше нет. Однако код внутри функции не выполняется.

IIFE: немедленно вызываемое функциональное выражение

Это называется IIFE (немедленно вызываемым функциональным выражением). Модуль может быть определен следующим образом:

Мы оборачиваем код модуля в IIFE. Анонимная функция возвращает объект. Это заменяет интерфейс экспорта. Присутствует только одна глобальная переменная — название модуля (или его пространство имен). Впоследствии название модуля может использоваться для его вызова (экспорта). Это называется шаблоном JS модуля.

Примеси импорта

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

Ранние версии популярных библиотек, таких как jQuery, использовали этот шаблон (в последней версии jQuery используется UMD модуль).

Открытый модуль: шаблон открытого JS модуля

Шаблон открытого модуля был придуман Christian Heilmann. Этот шаблон также является IIFE, но акцент в нем делается на определении всех интерфейсов как локальных переменных внутри анонимной функции:

Такой синтаксис облегчает понимание того, за что отвечает (или что делает) каждый интерфейс.

CJS модуль: CommonJS модуль или Node.js модуль

CommonJS, первоначально названный ServerJS, это шаблон для определения и использования модулей. Он встроен в Node.js. По умолчанию каждый JS файл — это CJS. Переменные module и exports обеспечивают экспорт модуля (файла). Функция require обеспечивает загрузку и использование модуля. Следующий код демонстрирует определение модуля счетчика на синтаксисе CommonJS:

Вот как этот модуль используется:

В среде выполнения (движке) Node.js этот шаблон используется путем оборачивания кода внутри файла в функцию, которой в качестве параметров передаются переменные exports, module и функция require :

AMD модуль или RequireJS модуль

AMD (асинхронное определение модуля) — это шаблон для определения и использования модулей. Он используется в библиотеке RequireJS. AMD содержит функцию define для определения модуля, которая принимает название модуля, названия зависимостей и фабричную функцию:

Он также содержит функцию require для использования модуля:

require AMD отличается от require CommonJS тем, что в качестве аргументов функции принимает названия модулей и сами модули.

Динамическая загрузка

Функция define также имеет другое назначение. Она принимает функцию обратного вызова и передает похожую на CommonJS require этой функции. Внутри функции обратного вызова require вызывается для динамической загрузки модуля:

AMD модуль из CommonJS модуля

UMD модуль: универсальное определение модуля или UmdJS модуль

UMD (универсальное определение модуля) — набор шаблонов для обеспечения работы модуля в разных средах выполнения.

UMD для AMD (RequireJS) и браузера

Следующий код обеспечивает работу модуля как в AMD (RequireJS), так и в браузере:

Выглядит сложно, но это всего лишь IIFE. Анонимная функция определяет наличие функции define из AMD/RequireJS.

UMD для AMD (RequireJS) и CommonJS (Node.js)

Следующий код обеспечивает работу модуля как в AMD (RequireJS), так и в CommonJS (Node.js):

Не пугайтесь, это снова всего лишь IIFE. При вызове анонимной функции, происходит «оценка» ее аргумента. Оценивание аргумента позволяет определить среду выполнения (определяется наличие переменных module и exports из CommonJS/Node.js, а также функции define из AMD/RequireJS).

ES модуль: ECMAScript2015 или ES6 модуль

Для обратной совместимости в браузере можно добавить тег

ES динамический модуль: ECMAScript2020 или ES11 динамический модуль

В последней 11 версии спецификации JS 2020 года представлена встроенная функция import для динамического использования ES модулей. Данная функция возвращает промис, поэтому использовать модуль можно с помощью then :

Благодаря тому, что функция import возвращает промис, в ней может использоваться ключевое слово await :

Системный модуль: SystemJS модуль

SystemJS — это библиотека для обеспечения работы ES модулей в старых браузерах. Например, следующий модуль написан с использованием синтаксиса ES6:

Этот код не будет работать в браузерах, не поддерживающих синтаксис ES6. Одним из решений данной проблемы является транспиляция кода с помощью интерфейса System.register библиотеки SystemJS:

Нового модульного синтаксиса ES6 больше нет. Зато код будет прекрасно работать в старых браузерах. Эта транспиляция может быть выполнена автоматически с помощью Webpack, TypeScript и т.д.

Динамическая загрузка модуля

SystemJS также содержит функцию import для динамического импорта:

Webpack модуль: транспиляция и сборка CJS, AMD и ES модулей

Webpack — это сборщик модулей. Его транспилятор объединяет CommonJS, AMD и ES модули в единый сбалансированный модульный шаблон и собирает весь код в один файл. Например, в следующих 3 файлах определяются 3 модуля с помощью различного синтаксиса:

Следующий код демонстрирует использование этого модуля:

Webpack способен объединить эти файлы, несмотря на то, что они представляют собой разные модульные системы, в один файл main.js :

Поскольку Webpack основан на Node.js, он использует модульный синтаксис CommonJS. В webpack.config.js :

Для транспиляции и сборки необходимо выполнить следующие команды:

И снова это всего лишь IIFE. Код из 4 файлов преобразован в массив из 4 функций. И этот массив передается анонимной функции в качестве параметра.

Babel модуль: транспиляция ES модуля

Babel — это еще один транспилятор для обеспечения работы ES6+ кода в старых браузерах. Приведенный выше ES6+ модуль может быть преобразован в Babel модуль следуюшим образом:

Это транспиляция по умолчанию. Babel также умеет работать с другими инструментами.

Babel и SystemJS

SystemJS может использоваться как плагин для Babel:

Данный плагин должен быть добавлен в babel.config.json :

Теперь Babel может работать с SystemJS для транспиляции CommonJS/Node.js, AMD/RequireJS и ES модулей:

Весь синтаксис AMD, CommonJS и ES модулей транспилирован в синтаксис SystemJS:

TypeScript модуль: транспиляция CJS, AMD, ES и SystemJS модулей

TypeScript поддерживает все разновидности синтаксиса JS, включая ES6. При транспиляции синтаксис ES6 модуля может быть сохранен или преобразован в другой формат, в том числе CommonJS/Node.js, AMD/RequireJS, UMD/UmdJS или SystemJS согласно настройкам транспиляции в tsconfig.json :

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

Внутренние модули и пространство имен

Оба транспилируются в JS объекты:

Sub module и sub namespace транспилируются в свойства объекта:

TypeScript module и namespace также могут использоваться в операторе export :

Приведенный код также транспилируется в sub module и sub namespace:

Заключение

Добро пожаловать в JS, который имеет 10+ систем/форматов модуляции/пространства имен:

Спасибо за потраченное время. Надеюсь, оно было потрачено не зря.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *