Understanding Webpack Loaders: Types, Configuration, Execution Order, and API
This article explains what Webpack loaders are, their four classification types (pre, normal, inline, post), how to configure them with enforce, the inline loader prefixes, execution priority, the loader call chain, synchronous vs asynchronous handling, parameters, output, caching, and useful loader development tools.
What is a loader
Webpack can only understand JavaScript and JSON files out of the box; loaders enable it to process other file types by converting them into modules that can be added to the dependency graph. A loader is essentially a JavaScript module that exports a function.
Loader classification
In Webpack, loaders are divided into four categories: post , normal , inline , and pre .
enforce
The category of a loader is determined by the Rule.enforce value in the configuration. It can be pre , post , or omitted (defaulting to normal ).
inline
Inline loaders are written directly in the import / require statement. Three prefix syntaxes control which loaders are ignored:
! – ignore normal loaders.
-! – ignore pre and normal loaders.
!! – ignore all loaders ( pre , normal , post ).
After the prefix, loaders are separated by ! , and optional query parameters can be passed with ? .
example
Assume a-loader is a pre loader, b-loader is a normal loader, and c-loader is a post loader. Various import statements illustrate how the prefixes affect the execution order.
// No prefix
import "/Users/jiangyuereee/Desktop/loader/d-loader.js!./txt.txt";
// ! prefix
import "!/Users/jiangyuereee/Desktop/loader/d-loader.js!./txt.txt";
// -! prefix
import "-!/Users/jiangyuereee/Desktop/loader/d-loader.js!./txt.txt";
// !! prefix
import "!!/Users/jiangyuereee/Desktop/loader/d-loader.js!./txt.txt";Loader priority
The call order from highest to lowest priority is pre > normal > inline > post . Within the same category, loaders are invoked from bottom to top and right to left (the normal functions run in reverse order, while pitch functions run left to right).
Loader call chain
Each loader has a normal function and an optional pitch function. The process starts by invoking all pitch functions from left to right; then the normal functions are called from right to left, forming an onion‑like model.
Loader – pitch
Loaders are always called from right to left. Some loaders only care about the metadata after the request and ignore the result of the previous loader. Before the right‑to‑left execution, their pitch methods are called from left to right.
If a pitch method returns a value, the remaining loaders are skipped and the returned value is passed up the chain as the content.
Synchronous / Asynchronous loader
In synchronous mode a loader can simply return the result. For asynchronous work, the loader must call this.async() to obtain a callback and then invoke that callback with err, content, sourceMap, meta .
Examples:
// Synchronous loader example
module.exports = function(content, map, meta) {
this.callback(null, handleData(content), handleSourceMap(map), meta);
return; // callback returns undefined
}; // Asynchronous loader example
module.exports = function(content, map, meta) {
var callback = this.async();
asyncHandleData(content, function(err, result) {
if (err) return callback(err);
callback(null, result, map, meta);
});
};Loader parameters
The initial loader receives the file content as a UTF‑8 string. Setting module.exports.raw = true makes it receive a Buffer . Loaders can also receive content , sourceMap , and meta via the callback.
pitch parameters
pitch receives three arguments:
remainingRequest – the request string for the loaders to the right of the current loader.
precedingRequest – the request string for the loaders to the left.
data – a shared object between pitch and normal phases.
Loader output
The compiler expects the final loader to emit a String or Buffer (representing the module's JavaScript source) and optionally a source map.
Additional files can be emitted with this.emitFile(name, content, sourceMap?) .
Loader caching
In development mode loaders are marked cacheable by default. To disable caching, set this.cacheable = false . Dependencies can be added with this.addDependency(filePath) to trigger re‑execution when those files change.
Loader API
Beyond the basic functions, loaders can use the full Loader Context API, which provides utilities such as this.emitFile , this.addDependency , and others.
Loader development toolkits
loader-runner – a package for developing and debugging loaders.
loader-utils – a collection of common helper functions for loader authors.
schema-utils – helps validate loader options.
References are listed at the end of the original article.
ByteFE
Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.