-
-
Notifications
You must be signed in to change notification settings - Fork 493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Function to transform asset file names for cache busting #2927
Comments
Eleventy doesn't even need to output a physical manifest.json file for this. |
I stumbled upon many conversations and blog posts regarding styles and javascript (i.e. global assets) cache-busting, but not very much is being said about the issue you raise here: content assets, like images in a blog posts or an article. Cache-busting for content assets is critical for things like documentation websites. I'm surprised nothing close to a best practice exists in that regard. Am I missing something, or is 11ty simply not meant to be used like that? Is there any solid resource I can refer to, in order to setup my configuration to provide cache-busting for content assets? |
I was able to do this with built in eleventy events using this. My contents are in const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
module.exports = function(eleventyConfig) {
// A cache to store the hashed file names
const hashCache = {};
// A cache buster if a file changes
const prefixLength ="./src/site".length
eleventyConfig.on('eleventy.beforeWatch', async (changedFiles) => {
for(const file of changedFiles) {
const relativePath = file.slice(prefixLength)
delete hashCache[relativePath]
}
});
// A filter to dynamically hash asset file contents
eleventyConfig.addFilter("digest", async (filePath) => {
// If we've already hashed this file, return the hash
if(hashCache[filePath]) {
return hashCache[filePath];
}
// Get the absolute path to the file inside of src/site
const absolutePath = path.join(__dirname, 'src/site', filePath);
// Digest the file
const fileBuffer = fs.readFileSync(absolutePath);
const hash = crypto.createHash('sha256').update(fileBuffer).digest('hex');
const relativePath = filePath.slice(0, path.basename(filePath).length * -1)
const digestFileName = `${relativePath}${hash}-${path.basename(filePath)}`;
// See if the digest file exists in the output folder _site
const digestFilePath = path.join(__dirname, '_site', digestFileName);
hashCache[filePath] = digestFileName;
if(!fs.existsSync(digestFilePath)) {
if(!fs.existsSync(path.dirname(digestFilePath))) {
fs.mkdirSync(path.dirname(digestFilePath), { recursive: true });
}
fs.copyFileSync(absolutePath, digestFilePath);
}
// Return the digest file name
return digestFileName;
})
// other stuff
return {
dir: {
input: "src/site", // source files
output: "_site", // destination folder
includes: "_includes", // folder for layouts and includes
data: "_data" // folder for data files
}
};
}; Then I digest assets like this: <link href="{{"/css/style.css" | digest}}" rel="stylesheet"> |
There's no way to do cache busting based on file content hash without hacks or using a separate process or external dependency. Some of those options are in #272.
It's actually quite simple to do like in https://github.com/keithamus/postcss-hash, but it's not possible to hook into eleventy's file outputting. Can we have a function like this?
That would output _data/manifest.json
It would make cache busting very simple to do with an
asset
filter which would get the transformed file name from the file inoutput
(_data/manifest.json). Then<img src={{ "dir1/dir/file.png" | asset }}>
will become<img src=dir1/dir/file-1234567890.png>
.The text was updated successfully, but these errors were encountered: