Like my last post, this is going to be another minor example, but it's yet another cool Eleventy 1.0 I'm happy to see added. (Even if I won't use it much - more on that towards the end.) Today's post is all about a new way to add global data to Eleventy, the new addGlobalData
function.
Before Eleventy 1.0, you could define global data for your templates by using the _data
folder (the exact name being configurable as well). In that folder you could drop in either a JSON or JavaScript file. JSON was good for setting hard coded values. Here's one I use here called site.json
:
{
"title":"Raymond Camden",
"description":"DevRel at Adobe, Star Wars nerd, Web/Serverless hacker, lover of good beer and good books. Oh, and cats.",
"url": "https://www.raymondcamden.com",
"navigation": [
{"text":"Home", "url":"/"},
{"text":"About","url":"/about/"},
{"text":"Speaking","url":"/speaking/"},
{"text":"Subscribe","url":"/subscribe/"},
{"text":"Contact","url":"/contact/"},
{"text":"Search","url":"/search/"}
],
"author_name":"Raymond Camden",
"author_image": "/images/avatar.jpg",
"author_location": "Lafayette, LA",
"author_bio": "Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos.",
"author_url": "https://www.raymondcamden.com",
"twitter_username": "raymondcamden",
"github_username": "cfjedimaster",
"codepen_username": "cfjedimaster",
"linkedin_username": "raymondcamden",
"youtube_username": "theraymondcamden"
}
JavaScript files lets you create data more dynamically. So for example, if I wanted to include Star Wars ship data in my templates, I could created ships.js
:
const fetch = require('node-fetch');
module.exports = async function() {
let resp = await fetch('https://swapi.dev/api/films/');
let films = await resp.json();
return films.results;
};
Now in Eleventy 1.0, there's an API you can use in yuour configuration file to specify the same kind of data. So for example:
eleventyConfig.addGlobalData('name', 'Eleventy Test Site');
eleventyConfig.addGlobalData('complex', {
facebook:'facebook foo',
twitter:'twittet goo',
insta:'insta zoo'
});
I used a simple string and object above, but any valid data works here. You can also use functions:
eleventyConfig.addGlobalData('generated', () => {
let now = new Date();
return new Intl.DateTimeFormat('en-US', { dateStyle: 'full', timeStyle: 'long' }).format(now);
});
As well as async functions:
eleventyConfig.addGlobalData('ships', async () => {
let shipRequest = await fetch('https://swapi.dev/api/starships');
let ships = await shipRequest.json();
return ships.results;
});
You can return promises as well if async/await isn't your thing.
This all works as expected so obviously I tried to break it a bit. One thing I was curious about was whether or not you could access all your global data. So I tried this:
eleventyConfig.addGlobalData('test', Object.keys(eleventyConfig.globalData));
And it works. The test
object was a list of the keys to all my data. But - and this is an important but - it only contains the key created before this particular line runs. If for some reason you add stuff afterwards, it won't reflect those changes. On a whim, I tried this:
eleventyConfig.on('beforeBuild', () => {
console.log('beforeBuild');
eleventyConfig.addGlobalData('test2', Object.keys(eleventyConfig.globalData));
console.log('done', JSON.stringify(eleventyConfig.globalData));
});
And while I can confirm the log message above showed test2
, my templates did not have access to it. I've got an open question about this on the Eleventy discussion board.
So... I like this! Will I use it? Probably not! Why? Right now I feel like my Eleventy config file is a bit complex, especially for this site. Having my global data in _data
makes me feel like things are a bit more organized. I also like having it there from a source control perspective. If I change one of the values in site.json
, I'd like that history to keep to itself if that makes sense. However, I cannot stress how much I appreciate that Eleventy provides multiple different ways of solving problems. One of the reasons I've ditched other static site generators is due to overly perscriptive functionality. I think it's great we've got multiple options now for this feature.
Don't forget that Eleventy has a "order of priority" when it comes to data. You can see this list at the "Sources of Data" documentation. Let me know what you think.