Методы модулей
В этом разделе описаны все методы, доступные в коде, скомпилированном с помощью webpack. При использовании webpack для сборки вашего приложения, вы можете выбрать различные стили синтаксиса модулей, включая ES6, CommonJS и AMD.
Хотя webpack поддерживает несколько синтаксических стилей модулей, мы рекомендуем придерживаться одного синтаксиса для обеспечения согласованности и избежания странного поведения/ошибок. Вот пример смешивания ES6 и CommonJS, но, безусловно, существуют и другие.
ES6 (Рекомендуется)
Версия 2 webpack поддерживает синтаксис модулей ES6 напрямую, что означает, что вы можете использовать import и export без инструмента, такого как babel, для обработки этого за вас. Имейте в виду, что вам все равно, вероятно, понадобится babel для других функций ES6+. Следующие методы поддерживаются webpack:
import
Статически import экспорты другого модуля.
import MyModule from './my-module.js';
import { NamedExport } from './other-module.js'; Ключевое слово здесь — статически. Обычное
importвыражение не может использоваться динамически в других логических операциях или содержать переменные. См. спецификацию для получения дополнительной информации иimport()ниже для динамического использования.
export
Экспортируйте всё как default или именованный экспорт.
// Named exports
export var Count = 5;
export function Multiply(a, b) {
return a * b;
}
// Default export
export default {
// Some data...
};
import()
function(string path):Promise
Динамическая загрузка модулей. Вызовы import() обрабатываются как точки разделения, что означает, что запрашиваемый модуль и его дочерние элементы разделены в отдельный фрагмент.
Спецификация загрузчика ES2015 ES2015 Loader spec определяет
import()как метод динамической загрузки модулей ES2015 во время выполнения.
if ( module.hot ) {
import('lodash').then(_ => {
// Do something with lodash (a.k.a '_')...
});
} Эта функция опирается на
Promiseвнутри. Если вы используетеimport()со старыми браузерами, помните о необходимости подменыPromiseс помощью полифилла, такого как es6-promise или promise-polyfill.
Динамические выражения в import()
Невозможно использовать полностью динамическое выражение import, например import(foo). Поскольку foo может потенциально представлять любой путь к любому файлу в вашей системе или проекте.
Выражение import() должно содержать хотя бы некоторую информацию о том, где находится модуль. Сборка может быть ограничена определённой директорией или набором файлов, чтобы при использовании динамического выражения — каждый модуль, который может быть запрошен в вызове import(), был включён. Например, import(`./locale/${language}.json`) приведет к тому, что каждый .json файл в директории ./locale будет включён в новый фрагмент. Во время выполнения, когда переменная language была вычислена, любые файлы, такие как english.json или german.json будут доступны для использования.
// imagine we had a method to get language from cookies or other storage
const language = detectVisitorLanguage();
import(`./locale/${language}.json`).then(module => {
// do something with the translations
}); Использование
webpackIncludeиwebpackExcludeопций позволяет добавлять шаблоны регулярных выражений, которые уменьшают количество файлов, которые webpack будет собирать для этого импорта.
Магические комментарии
Встроенные комментарии для работы функций. Добавляя комментарии к импорту, мы можем делать такие вещи, как назначать имя нашему фрагменту или выбирать разные режимы. Полный список этих магических комментариев см. в коде ниже, за которым следует объяснение того, что эти комментарии делают.
// Single target
import(
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
'module'
);
// Multiple possible targets
import(
/* webpackInclude: /\.json$/ */
/* webpackExclude: /\.noimport\.json$/ */
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackPrefetch: true */
/* webpackPreload: true */
`./locale/${language}`
); import(/* webpackIgnore: true */ 'ignored-module.js');
webpackIgnore: Отключает разбор динамического импорта, когда установлено значение true.
Обратите внимание, что установка
webpackIgnoreвtrueотключает разделение кода.
webpackChunkName: Имя для нового фрагмента. С webpack 2.6.0 поддерживаются замены [index] и [request] в строке для увеличения номера или фактического решённого имени файла соответственно. Добавление этого комментария вызовет присвоение отдельному фрагменту имени [my-chunk-name].js вместо [id].js.
webpackMode: С webpack 2.6.0 можно указать различные режимы для разрешения динамических импортов. Поддерживаются следующие опции:
-
"lazy"(по умолчанию): Создаёт загружаемый по запросу фрагмент для каждогоimport()модуля. -
"lazy-once": Создаёт единственный загружаемый по запросу фрагмент, который может удовлетворить все вызовыimport(). Фрагмент будет загружен при первом вызовеimport(), а последующие вызовыimport()будут использовать тот же ответ от сети. Обратите внимание, что это имеет смысл только в случае частично динамического выражения, напримерimport(`./locales/${language}.json`), где может быть запрошено несколько путей к модулям. -
"eager": Не создаёт дополнительных фрагментов. Все модули включаются в текущий фрагмент, и дополнительные запросы к сети не производятся. ВозвращаетсяPromise, но он уже разрешен. В отличие от статического импорта, модуль не выполняется до вызоваimport(). -
"weak": Пытается загрузить модуль, если функция модуля уже загружена каким-то другим способом (например, другой фрагмент импортировал его или скрипт, содержащий модуль, был загружен). ВозвращаетсяPromise, но успешно разрешается только если фрагменты уже на клиенте. Если модуль недоступен,Promiseотклоняется. Запрос к сети никогда не будет выполнен. Это полезно для универсальной отрисовки, когда необходимые фрагменты всегда вручную предоставляются в начальных запросах (встроены в страницу), но не в случаях, когда навигация по приложению вызовет импорт, который изначально не был предоставлен.
webpackPrefetch: Сообщает браузеру, что ресурс, вероятно, потребуется для какой-то навигации в будущем. Для получения дополнительной информации см. руководство по работе webpackPrefetch.
webpackPreload: Сообщает браузеру, что ресурс может потребоваться во время текущей навигации. Для получения дополнительной информации см. руководство по работе webpackPreload.
Обратите внимание, что все опции могут быть объединены, например
/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */. Это заключено в объект JavaScript и выполняется с использованием node VM. Вам не нужно добавлять фигурные скобки.
webpackInclude: Регулярное выражение, которое будет проверяться при разрешении импорта. Только модули, которые соответствуют шаблону, будут включены в сборку.
webpackExclude: Регулярное выражение, которое будет проверяться при разрешении импорта. Любые модули, которые соответствуют шаблону, не будут включены в сборку.
Обратите внимание, что опции
webpackIncludeиwebpackExcludeне влияют на префикс. Например:./locale.
Использование
System.importв webpack не соответствовало предлагаемой спецификации, поэтому оно было устаревшим в webpack 2.1.0-beta.28 в пользуimport().
CommonJS
Целью CommonJS является определение экосистемы для JavaScript вне браузера. Следующие методы CommonJS поддерживаются webpack:
require
require(dependency: String);
Синхронно извлекает экспорты из другого модуля. Компилятор обеспечит наличие зависимости в выходном пакете.
var $ = require('jquery');
var myModule = require('my-module'); Использование его асинхронно может не иметь ожидаемого эффекта.
require.resolve
require.resolve(dependency: String);
Синхронно извлекает идентификатор модуля. Компилятор обеспечит наличие зависимости в выходном пакете. См. module.id для получения дополнительной информации.
Идентификатор модуля — это число в webpack (в отличие от NodeJS, где это строка — имя файла).
require.cache
Несколько запросов к одному и тому же модулю приводят к выполнению только одного модуля и только одному экспорту. Поэтому в runtime существует кэш. Удаление значений из этого кэша вызывает новое выполнение модуля и новый экспорт.
Это необходимо только в редких случаях для совместимости!
var d1 = require('dependency');
require('dependency') === d1;
delete require.cache[require.resolve('dependency')];
require('dependency') !== d1; // in file.js
require.cache[module.id] === module;
require('./file.js') === module.exports;
delete require.cache[module.id];
require.cache[module.id] === undefined;
require('./file.js') !== module.exports; // in theory; in praxis this causes a stack overflow
require.cache[module.id] !== module;
require.ensure
require.ensure()специфично для webpack и заменено наimport().
require.ensure( dependencies: String[], callback: function(require), errorCallback: function(error), chunkName: String )
Выделяет указанный dependencies в отдельный пакет, который будет загружен асинхронно. При использовании синтаксиса модулей CommonJS это единственный способ динамической загрузки зависимостей. Это означает, что этот код может быть запущен в процессе выполнения, загружая dependencies только при определённых условиях.
Эта функция опирается на
Promiseвнутри. Если вы используетеrequire.ensureсо старыми браузерами, помните о необходимости подменыPromiseс помощью полифилла, такого как es6-promise или promise-polyfill.
var a = require('normal-dep');
if ( module.hot ) {
require.ensure(['b'], function(require) {
var c = require('c');
// Do something special...
});
} В следующих параметрах поддерживается указанный выше порядок:
-
dependencies: Массив строк, объявляющий все модули, необходимые для выполнения кода вcallback. -
callback: Функция, которую webpack выполнит после загрузки зависимостей. Реализация функцииrequireпередаётся как параметр этой функции. Функция может использовать это для дальнейшейrequire()необходимых ей модулей для выполнения. -
errorCallback: Функция, выполняемая, когда webpack не может загрузить зависимости. -
chunkName: Имя созданного этим вызовомrequire.ensure()фрагмента. Передавая одно и то жеchunkNameв различные вызовыrequire.ensure(), мы можем объединить их код в один фрагмент, что приводит к одной сборке, которую браузер должен загрузить.
Хотя реализация
requireпередаётся в качестве аргумента функцииcallback, использование произвольного имени, например,require.ensure([], function(request) { request('someModule'); }), не обрабатывается статическим анализатором webpack. Используйтеrequireвместо этого, напримерrequire.ensure([], function(require) { require('someModule'); }).
AMD
Asynchronous Module Definition (AMD) — это спецификация JavaScript, определяющая интерфейс для написания и загрузки модулей. Следующие методы AMD поддерживаются webpack:
define (с фабрикой)
define([name: String], [dependencies: String[]], factoryMethod: function(...))
Если dependencies предоставлены, factoryMethod будет вызван с экспортом каждой зависимости (в том же порядке). Если dependencies не предоставлены, factoryMethod вызывается с require, exports и module (для совместимости!). Если эта функция возвращает значение, это значение экспортируется модулем. Компилятор гарантирует, что каждая зависимость доступна.
Обратите внимание, что webpack игнорирует аргумент
name.
define(['jquery', 'my-module'], function($, myModule) {
// Do something with $ and myModule...
// Export a function
return function doSomething() {
// ...
};
}); Это НЕ может использоваться в асинхронной функции.
define (со значением)
define(value: !Function)
Это просто экспортирует предоставленное value. value здесь может быть чем угодно, кроме функции.
define({
answer: 42
}); Это НЕ может использоваться в асинхронной функции.
require (amd-version)
require(dependencies: String[], [callback: function(...)])
Подобно require.ensure, это разделит предоставленный dependencies в отдельный пакет, который будет загружен асинхронно. callback будет вызван с экспортом каждой зависимости в массиве dependencies.
Эта функция использует
Promiseв качестве внутренней реализации. Если вы используете AMD в старых браузерах (например, Internet Explorer 11), помните о необходимости подменыPromiseс помощью полифилла, такого как es6-promise или promise-polyfill.
require(['b'], function(b) {
var c = require('c');
}); Нет возможности указать имя пакета.
Именованные модули
Внутренняя LabeledModulesPlugin позволяет использовать следующие методы для экспорта и импорта внутри ваших модулей:
export метки
Экспортировать данную value. Метка может стоять перед объявлением функции или переменной. Имя функции или переменной — это идентификатор, под которым экспортируется значение.
export: var answer = 42;
export: function method(value) {
// Do something...
}; Использование в асинхронных функциях может привести к непредсказуемым результатам.
require метки
Сделать все экспорты из зависимости доступными в текущей области видимости. Метка require может стоять перед строкой. Зависимость должна экспортировать значения с меткой export. Модули CommonJS или AMD использовать нельзя.
some-dependency.js
export: var answer = 42;
export: function method(value) {
// Do something...
}; require: 'some-dependency'; console.log(answer); method(...);
Webpack
Помимо синтаксисов модулей, описанных выше, webpack также позволяет использовать несколько пользовательских методов, специфичных для webpack:
require.context
require.context( directory: String, includeSubdirs: Boolean /* optional, default true */, filter: RegExp /* optional, default /^\.\/.*$/, any file */, mode: String /* optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once', default 'sync' */ )
Указать целую группу зависимостей, используя путь к directory, опцию для includeSubdirs, filter для более тонкого управления включаемыми модулями и mode для определения способа работы загрузки. Подлежащие модули затем можно легко разрешить позже:
var context = require.context('components', true, /\.html$/);
var componentA = context.resolve('componentA'); Если mode указано как "lazy", подлежащие модули будут загружаться асинхронно:
var context = require.context('locales', true, /\.json$/, 'lazy');
context('localeA').then(locale => {
// do something with locale
}); Полный список доступных режимов и их поведение описан в документации import().
require.include
require.include(dependency: String)
Включить dependency без его выполнения. Это может использоваться для оптимизации расположения модуля в выходных пакетах.
require.include('a');
require.ensure(['a', 'b'], function(require) { /* ... */ });
require.ensure(['a', 'c'], function(require) { /* ... */ }); Это приведёт к следующему выводу:
- пакет входа:
file.jsиa - анонимный пакет:
b - анонимный пакет:
c
Без require.include('a') он был бы дублирован в обоих анонимных пакетах.
require.resolveWeak
Аналогично require.resolve, но это не включит module в пакет. Это считается "слабой" зависимостью.
if(__webpack_modules__[require.resolveWeak('module')]) {
// Do something when module is available...
}
if(require.cache[require.resolveWeak('module')]) {
// Do something when module was loaded before...
}
// You can perform dynamic resolves ("context")
// just as with other require/import methods.
const page = 'Foo';
__webpack_modules__[require.resolveWeak(`./page/${page}`)];
require.resolveWeak— основа универсального рендеринга (SSR + разделение кода), используемого в таких пакетах, как react-universal-component. Это позволяет коду рендерить синхронно как на сервере, так и при начальной загрузке на клиенте. Требует, чтобы пакеты вручную обслуживались или каким-то образом были доступны. Способен требовать модули, не указывая, что они должны быть объединены в пакет. Используется совместно сimport(), который подхватывает ситуацию, когда навигация пользователя запускает дополнительные импорты.
© JS Foundation and other contributors
Licensed under the Creative Commons Attribution License 4.0.
https://v4.webpack.js.org/api/module-methods