Writing a loader
An eleventy-load loader is just a JavaScript function, nothing complicated! The function is passed two arguments: the content
of the file being loaded and the user-provided options
for the loader.
An example loader #
Let’s write a loader to convert a text file to uppercase, but only if the user passes uppercase: true
as an option. Of course, this loader could be applied to any file, it just uppercases the content.
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(require("eleventy-load"), {
rules: [
{
test: /\.txt$/,
loaders: [
{
loader: function (content, options) {
return options.uppercase ? content.toUpperCase() : content;
},
options: {
uppercase: true,
},
},
],
},
],
});
};
Instead of writing the loader in your Eleventy configuration file, you might want to move it into a module which exports the loader function.
module.exports = function (content, options) {
return options.uppercase ? content.toUpperCase() : content;
};
const uppercaseLoader = require("./uppercase");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(require("eleventy-load"), {
rules: [
{
test: /\.txt$/,
loaders: [
{
loader: uppercaseLoader,
options: {
uppercase: true,
},
},
],
},
],
});
};
Loader interface #
As well as the function parameters content
and options
, loaders also have access to the loader context. The context of a function can be accessed using the this
keyword.
this.addDependency #
Add a dependency to be processed by eleventy-load. The dependency must be relative to the Eleventy project’s input directory. You should always await
adding a dependency, as the loaders processing the dependency might be asynchronous.
module.exports = async function (content, options) {
const license = await this.addDependency("LICENSE");
return license + content;
};
this.config #
A copy of the Eleventy configuration object passed to plugins, with two added properties: inputDir
and outputDir
.
{
"inputDir": "src",
"outputDir": "dist"
}
Click to see a full example of this.config
generated by eleventy-load.
{
"inputDir": "src",
"outputDir": "dist",
"events": {
"_events": {},
"_eventsCount": 1
},
"collections": {},
"liquidOptions": {
"dynamicPartials": true
},
"liquidTags": {},
"liquidFilters": {},
"liquidShortcodes": {},
"liquidPairedShortcodes": {},
"nunjucksFilters": {},
"nunjucksAsyncFilters": {},
"nunjucksTags": {},
"nunjucksShortcodes": {},
"nunjucksAsyncShortcodes": {},
"nunjucksPairedShortcodes": {},
"nunjucksAsyncPairedShortcodes": {},
"handlebarsHelpers": {},
"handlebarsShortcodes": {},
"handlebarsPairedShortcodes": {},
"javascriptFunctions": {},
"pugOptions": {},
"ejsOptions": {},
"markdownHighlighter": null,
"libraryOverrides": {},
"passthroughCopies": {},
"layoutAliases": {},
"linters": {},
"filters": {},
"activeNamespace": "",
"dynamicPermalinks": true,
"useGitIgnore": true,
"dataDeepMerge": true,
"extensionMap": {},
"watchJavaScriptDependencies": true,
"additionalWatchTargets": [
"./src/"
],
"browserSyncConfig": {},
"chokidarConfig": {},
"watchThrottleWaitTime": 0,
"dataExtensions": {},
"quietMode": false
}
this.emitFile #
Save content to a file in the project’s output directory. The function takes three parameters:
- The content to save, either a
String
orBuffer
. - The filepath in which to save the content, relative to the project’s output directory.
- A flag which dictates whether the file should be saved. Defaults to
true
, passfalse
to dry run.
module.exports = async function (content, options) {
return this.emitFile(content, "assets/[name].[hash:12].css", false);
};
The filepath can contain placeholders, useful for creating hashed files. The following placeholders are replaced:
[ext]
the extension of the resource[name]
the basename of the resource[dir]
the directory of the resource[hash]
or[hash:N]
the hash of the content of the resource, lengthN
defaults to 8 characters
this.resource #
The current resource being processed, relative to the project’s input directory. Use this.resourcePath
and this.resourceQuery
to access the path and the query respectively.
module.exports = function (content, options) {
console.log(this.resource); // assets/cat.jpeg?width=1920&height=1080&format=webp
};
this.resourcePath #
The path of the current resource being processed, relative to the project’s input directory. Here’s an example which gets the last-modified time of the current resource.
const fs = require("fs");
const path = require("path");
module.exports = function (content, options) {
console.log(this.resourcePath); // assets/cat.jpeg
const resource = path.resolve(this.config.inputDir, this.resourcePath);
const lastModifiedTime = fs.statSync(resource).mtime;
};
this.resourceQuery #
The query of the current resource being processed. You can use URLSearchParams to easily parse the query.
module.exports = function (content, options) {
console.log(this.resourceQuery); // ?width=1920&height=1080&format=webp
const params = new URLSearchParams(this.resourceQuery);
console.log(params.get("format")); // webp
};
Raw loaders #
By default, the content of a resource is loaded as a UTF-8 string and passed to the first loader. By setting the raw
flag to true
, the loader will receive a raw Buffer
instead of a String
. This is useful for loaders which deal with binary filetypes, such as images.
module.exports = function (content, options) {
console.log(content instanceof Buffer); // true
};
module.exports.raw = true;