Загрузчики
Введение
Загрузчики позволяют предварительно обработать файлы при их require() или «загрузке». Загрузчики похожи на «задачи» в других инструментах сборки и предоставляют мощный способ обработки шагов сборки фронтенда. Загрузчики могут преобразовывать файлы из других языков, например, CoffeeScript в JavaScript, или встраивать изображения в виде данных URL. Загрузчики даже позволяют выполнять действия, такие как require() CSS-файлы прямо в вашем JavaScript!
Чтобы указать Webpack на преобразование модуля с помощью загрузчика, вы можете указать загрузчик в файле конфигурации Webpack (предпочтительно) или в запросе модуля, например, в вызове require.
var moduleWithOneLoader = require("my-loader!./my-awesome-module");
Обратите внимание на синтаксис !, разделяющий загрузчик и путь к модулю? Загрузчики, как и модули, также могут быть указаны с относительным путем (как если бы вы его подключали), вместо имени загрузчика:
require("./loaders/my-loader!./my-awesome-module");
Загрузчики также могут быть объединены, разделяя их с помощью !. Это полезно для применения нескольких преобразований к файлу в конвейере.
require("style-loader!css-loader!less-loader!./my-styles.less");
При объединении загрузчиков они применяются справа налево (от файла назад). В приведённом выше примере my-styles.less сначала будет преобразован загрузчиком less-loader, преобразуя его в CSS, а затем передан загрузчику css-loader, где обрабатываются URL, шрифты и другие ресурсы, и, наконец, передан загрузчику style-loader, чтобы преобразовать его в тег <style>.
Параметры
Загрузчики могут принимать параметры запроса:
require("loader?with=parameter!./file");
Формат строки запроса зависит от загрузчика, поэтому ознакомьтесь с документацией загрузчика, чтобы узнать о принимаемых им параметрах, но в большинстве случаев загрузчики поддерживают традиционный формат строки запроса.
Загрузчики по конфигурации
Указание загрузчиков в каждом запросе модуля может быть хрупким и повторяющимся. Webpack предоставляет способ указать, какие загрузчики применяются к различным типам файлов в вашем файле конфигурации Webpack. Указание загрузчиков в конфигурации — это рекомендуемый подход в большинстве случаев, так как он не добавляет никакого специфичного для сборки синтаксиса в код, что делает его более переиспользуемым.
{
module: {
loaders: [
{ test: /\.coffee$/, loader: "coffee-loader" }
],
preLoaders: [
{ test: /\.coffee$/, loader: "coffee-hint-loader" }
]
}
};
Дополнительную информацию о настройке загрузчиков см. на странице конфигурации.
Обратите внимание, что загрузчики, такие как coffee-loader или json-loader, — это модули, которые можно установить из NPM. Например:
npm install json-loader --save-dev
Порядок загрузчиков
После того, как файл прочитан из файловой системы, загрузчики выполняются в следующем порядке.
-
preLoadersуказанные в конфигурации -
loadersуказанные в конфигурации - загрузчики, указанные в запросе (например,
require('raw!./file.js')) -
postLoadersуказанные в конфигурации
Вы также можете переопределить порядок загрузчиков конфигурации в запросе модуля для специальных случаев.
- добавление
!к запросу отключит настроенныеpreLoaders.require("!raw!./script.coffee")
- добавление
!!к запросу отключит все загрузчики, указанные в конфигурацииrequire("!!raw!./script.coffee")
- добавление
-!к запросу отключит настроенныеpreLoadersиloaders, но неpostLoaders.require("-!raw!./script.coffee")
Рекомендации
Рекомендуется, чтобы результатом был JavaScript после шага 2.
Рекомендуется применять преобразования из не-JavaScript в JavaScript на шаге 1 (или на шаге 2, если они не применяются глобально).
Рекомендуется оставаться в одном и том же языке в пре- и пост-загрузчиках.
Исходный код, который хочет переопределить преобразование не-js в js, должен использовать префикс !. (т. е. преобразовать его другим способом)
Использование префиксов !! и -! для отключения загрузчиков не рекомендуется, за исключением другого загрузчика.
- Пример пре-загрузчика: сжатие изображений
- Пример загрузчика (в конфигурации): преобразование кофи-скрипта
- Пример загрузчика (в запросе): загрузчик пакета
- Пример пост-загрузчика: инструментарий для покрытия кода
Написание загрузчика
Написание загрузчика довольно просто. Загрузчик — это просто файл, который экспортирует функцию. Компилятор вызывает эту функцию и передает результат предыдущего загрузчика или файла ресурса в неё. Контекст this функции заполняется компилятором полезными методами, которые позволяют загрузчику, среди прочего, изменить стиль вызова на асинхронный или получить параметры запроса. Первый загрузчик получает один аргумент: содержимое файла ресурса. Компилятор ожидает результат от последнего загрузчика. Результат должен быть строкой или буфером (который преобразуется в строку), представляющей JavaScript-исходный код модуля. Также может быть передан необязательный результат SourceMap (как JSON-объект).
В синхронном режиме можно вернуть один результат. Для нескольких результатов необходимо вызвать this.callback. В асинхронном режиме this.async() необходимо вызвать. Он возвращает this.callback, если разрешён асинхронный режим. Затем загрузчик должен вернуть undefined и вызвать обратный вызов.
Ошибки могут быть выброшены в синхронном режиме, или можно вызвать this.callback с ошибкой.
webpack позволяет асинхронный режим в любом случае.
enhanced-require позволяет асинхронный режим только с require.ensure или AMD require.
Более подробные инструкции и рекомендации см. в разделе Как написать загрузчик.
Примеры
Синхронный загрузчик
module.exports = function(content) {
return someSyncOperation(content);
};
Асинхронный загрузчик
module.exports = function(content) {
var callback = this.async();
if(!callback) return someSyncOperation(content);
someAsyncOperation(content, function(err, result) {
if(err) return callback(err);
callback(null, result);
});
};
Примечание: рекомендуется предоставить асинхронному загрузчику резервную синхронную обработку. Это не требуется для webpack, но позволяет запустить загрузчик синхронно с помощью enhanced-require.
Загрузчик raw
По умолчанию файл ресурса обрабатывается как utf-8 строка и передаётся как строка загрузчику. Установив raw в true, загрузчику передаётся исходный буфер.
Каждый загрузчик может возвращать результат в виде строки или буфера. Компилятор преобразует их между загрузчиками.
module.exports = function(content) {
assert(content instanceof Buffer);
return someSyncOperation(content);
// return value can be a Buffer too
// This is also allowed if loader is not "raw"
};
module.exports.raw = true;
Загрузчик pitch
Загрузчики вызываются справа налево. Но в некоторых случаях загрузчики не заботятся о результатах предыдущего загрузчика или ресурса. Они заботятся только о метаданных. Метод pitch загрузчиков вызывается слева направо перед вызовом загрузчиков. Если загрузчик возвращает результат в методе pitch, процесс меняет направление и пропускает оставшиеся загрузчики, продолжая вызовы более левым загрузчикам. data может передаваться между фазами pitch и обычного вызова.
module.exports = function(content) {
return someSyncOperation(content, this.data.value);
};
module.exports.pitch = function(remainingRequest, precedingRequest, data) {
if(someCondition()) {
// fast exit
return "module.exports = require(" + JSON.stringify("-!" + remainingRequest) + ");";
}
data.value = 42;
};
Контекст загрузчика
Эта информация доступна в this загрузчика.
Для примера используется этот вызов require:
В /abc/file.js:
require("./loader1?xyz!loader2!./resource?rrr");
version
Версия API загрузчика. В настоящее время 1.
context
Строка. Директория модуля. Может использоваться как контекст для разрешения других вещей.
В примере: /abc, потому что resource.js находится в этой директории
request
Разрешённая строка запроса.
В примере: "/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr"
query
Строка. Запрос запроса для текущего загрузчика.
В примере: в загрузчике 1: "?xyz", в загрузчике 2: ""
data
Объект данных, используемый между фазами pitch и нормального вызова.
cacheable
cacheable(flag = true: boolean)
Сделать результат загрузчика кэшируемым. По умолчанию он не кэшируется.
Кэшируемый загрузчик должен иметь детерминированный результат, когда входные данные и зависимости не изменились. Это означает, что у загрузчика не должно быть других зависимостей, кроме указанных с this.addDependency. Большинство загрузчиков являются детерминированными и кэшируемыми.
loaders
loaders = [{request: string, path: string, query: string, module: function}]
Массив всех загрузчиков. Он изменяемый в фазе pitch.
В примере:
[
{ request: "/abc/loader1.js?xyz",
path: "/abc/loader1.js",
query: "?xyz",
module: [Function]
},
{ request: "/abc/node_modules/loader2/index.js",
path: "/abc/node_modules/loader2/index.js",
query: "",
module: [Function]
}
]
loaderIndex
Индекс в массиве загрузчиков текущего загрузчика.
В примере: в загрузчике 1: 0, в загрузчике 2: 1
resource
Часть ресурса запроса, включая запрос.
В примере: "/abc/resource.js?rrr"
resourcePath
Файл ресурса.
В примере: "/abc/resource.js"
resourceQuery
Запрос ресурса.
В примере: "?rrr"
emitWarning
emitWarning(message: string)
Выдать предупреждение.
emitError
emitError(message: string)
Выдать ошибку.
exec
exec(code: string, filename: string)
Выполнить фрагмент кода, как модуль.
Подсказка: Не используйте
require(this.resourcePath), используйте эту функцию для создания цепочки загрузчиков!
resolve
resolve(context: string, request: string, callback: function(err, result: string))
Разрешить запрос, как выражение require.
resolveSync
resolveSync(context: string, request: string) -> string
Разрешить запрос, как выражение require.
addDependency
addDependency(file: string) dependency(file: string) // shortcut
Добавить файл как зависимость результата загрузчика для отслеживания изменений.
addContextDependency
addContextDependency(directory: string)
Добавить директорию как зависимость результата загрузчика.
clearDependencies
clearDependencies()
Удалить все зависимости результата загрузчика. Даже начальные зависимости и те, что от других загрузчиков. Рассмотрите использование pitch.
value
Передать значения следующему загрузчику. Если вы знаете, что экспортирует ваш результат, если его выполнить как модуль, установите это значение здесь (как массив из одного элемента).
inputValue
Передаётся от предыдущего загрузчика. Если бы вы выполняли входной аргумент как модуль, рассмотрите чтение этой переменной для сокращения (для производительности).
options
Параметры, переданные компилятору.
debug
Логический флаг. Устанавливается при отладке.
minimize
Требуется ли сжатие результата.
sourceMap
Требуется ли генерация карты исходного кода.
target
Цель компиляции. Передаётся из параметров конфигурации.
Примеры значений: "web", "node"
webpack
Установите в значение true, когда это компилируется webpack.
emitFile
emitFile(name: string, content: Buffer|String, sourceMap: {...})
Вывести файл. Это специфично для webpack.
_compilation
Неофициальный доступ к объекту Compilation webpack.
_compiler
Неофициальный доступ к объекту Compiler webpack.
© 2012–2015 Tobias Koppers
Licensed under the MIT License.
https://webpack.github.io/docs/loaders.html