Currently Hexo only emits generateAfter events after all files output.
So I am wondering is there a way to hook per-file generation?
By knowing what files have been changed in a generation, I am actually finding a way to purge specific caches on CloudFlare by URL. Therefore, the path to each generated file is also required.
Currently, I think the only way to get these information is through capturing and filtering the stdout of hexo generate.
https://github.com/hexojs/hexo/blob/master/lib/plugins/console/generate.js#L61
Great question, @momocow ❗️
I hope this will work for your purposes ⬇️
./scripts./scripts/filter-changed.js
/*
save what changed during `hexo generate` into ../changed-[time].json
*/
const fs = require("fs");
const path = require("path");
const flatten = require("lodash/flatten");
const projectPath = path.join(__dirname, "..");
let changed = [];
hexo.extend.filter.register("before_generate", function(docs) {
/*
1. collect a list of changed documents
2. map some basic information about it
*/
const items = flatten(docs).map(function(doc) {
const {
permalink,
path,
date,
updated,
_id,
source,
title
} = doc;
// convert from Moment object
const created = date && date.valueOf();
const modified = updated && updated.valueOf();
return {
_id,
created,
modified,
title,
source,
path,
permalink
};
});
changed = changed.concat(items);
});
hexo.extend.filter.register("after_generate", function() {
/*
1. after generating save the results from above
2. say it's done with path
*/
const now = Date.now();
const changedJsonPath = path.join(projectPath, `changed-${now}.json`);
const changedJsonSource = JSON.stringify(changed, null, " ");
fs.writeFile(changedJsonPath, changedJsonSource, function(err) {
if (err !== undefined && err !== null) {
return console.error("error saving changde json file", err);
}
console.log("saved", changedJsonPath);
});
});

(I'm using another hexo user's blog as an example)
hexo generate
The script ./scripts/filter-changed.js will save a file into the project root and give the absolute path.

I'm not sure why this Filter API vs. Events API but it works.
Can you inspect the output and tell me if this data is sufficient for you to work with the cache?
Alternatively you can use GNU diff:
rm -rf public-before
cp -r public public-before
hexo generate
diff --recursive --brief public-before public
Alternatively if the ./public directory is saved into git git diff
Thanks, @tcrowe, nice answer.
I can expect the two alternative ways, but wonder if there is anything more like a Hexo plugin ✨ .
Since both the two alternative ways only see files changed but have no knowledge about each file while Hexo knows what they are for and what the URL for each file should be!
(Although the URL can be guessed from the file path.)
Anyway, I'll have a try on the suggested script!
@momocow Thank you. Whatever you end up with it will be useful for us to give to the community or put into an article or plugin.
@tcrowe Sure!
I noticed that docs from hexo.extend.filter.register("before_generate", function(docs) { }) always contains a full list of every route in the blog.
Therefore I have to diff it myself for the actual changes, right?
I can provide a plugin to reveal the diffs of files under each route.
For diffing files, I will check out Google's diff-match-patch library.
Last question, how do you think the plugin can reveal file diffs to Hexo system?
This plugin does not make side effects to blog contents, but enhances the Hexo API instead.
I think it is a good idea to emit a new event on hexo instance, e.g. hexo.emit('file_diff', diffs) for other plugins or scripts to exploit.
Then provide some configurable pre-defined actions, like
If there is no problem in the approach described above, I can start working on the plugin. 😄
@momocow Soooo... if you leave the cache in place it will only regenerate the new files. It needs db.json in the project root or else it must regenerate all each time.
Hexo knows which files changed because it hashes them inside.
Changed or new files*
It needs db.json in the project root or else it must regenerate all each time.
@tcrowe Uhhhh, my fault, sorry.
I build from my gulp script using hexo.call('generate') which produces no db.json.
Running hexo g from CLI works just as you described.
Thanks!
Yay! 👌🎆🍉
This issue has been automatically marked as stale because lack of recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Most helpful comment
Great question, @momocow ❗️
I hope this will work for your purposes ⬇️
Create hexo script in
./scripts./scripts/filter-changed.jsChange some files
(I'm using another hexo user's blog as an example)
Generate
The script
./scripts/filter-changed.jswill save a file into the project root and give the absolute path.I'm not sure why this Filter API vs. Events API but it works.
Can you inspect the output and tell me if this data is sufficient for you to work with the cache?
Alternatively you can use GNU
diff:Alternatively if the
./publicdirectory is saved into gitgit diff