eleventy
eleventy copied to clipboard
functions in eleventyComputed (directory data file) execute twice
Operating system
Node.js 19.4.0
Eleventy
2.0.0-beta.1
Describe the bug
the following code logs to the console twice for every element in the collection:
collection/collection.11tydata.js
module.exports = {
eleventyComputed: {
test: () => {
console.log('TEST')
}
}
}
and when logging the data object, it returns one empty object and then the expected object for every element:
module.exports = {
eleventyComputed: {
test: (data) => {
console.log(data)
}
}
}
might be related to #2754
Reproduction steps
No response
Expected behavior
No response
Reproduction URL
No response
Screenshots
No response
Still seems to happen in Eleventy 2.0.1. Also when using the data()
function in Javascript templates.
Since this is still happening in Eleventy 3.0.0-alpha.4, I took a closer look. In order to detect dependencies between eleventyComputed
keys, Eleventy seems to call all functions twice. As far as I understand it, the first call is to determine the call order and the second call is the "actual" one, in the correct order, with the proper data
argument.
So, I guess this is a "works as intended" case. The question is, if we could prevent unnecessary computing time and make Eleventy even faster. Off the top of my head, I have the following idea. (Please forgive me, if I haven't completely understood the inner workings of Eleventy.)
The idea is to pass a second argument to the eleventyComputed
functions, which is only present and true
, if the call is to determine the dependencies. I'll call it isDryRun
here.
module.exports = {
eleventyComputed: {
test: (data, isDryRun) => {
// Help Eleventy determine dependencies as per docs.
if (isDryRun) {
data.foo;
data.bar;
// We're done for the dry run.
return;
}
// Do some computing with foo and bar here that now only runs once.
return somethingComputed;
},
foo: (data, isDryRun) => { /* ... */ },
bar: (data, isDryRun) => { /* ... */ }
}
}
This should be backwards compatible and easy to understand and to implement by Eleventy users. One danger is, that users could forget to declare dependencies but I think a note in the documentation and/or error messages should quickly clear things up.