Reading time, without the dependency
I added reading time to this site yesterday; the little “3 min read” line under each post title. There’s a whole npm ecosystem for this, but instead I wrote a thirty-line remark plugin.
Why not just npm i reading-time
The package works fine, it’s a great library. But every dependency bets on the same core things:
- that the author keeps maintaining it
- that its transitive deps don’t drift
- that its type definitions stay in sync with your toolchain
- that you remember why it’s in the lockfile six months from now
For a feature whose entire spec is “divide by 220 and round,” that bet costs more than it pays.
The whole thing
const WORDS_PER_MINUTE = 220;
function nodeToText(node) {
if (!node || typeof node !== 'object') return '';
if (typeof node.value === 'string') return node.value;
if (Array.isArray(node.children)) {
return node.children.map(nodeToText).join(' ');
}
return '';
}
export function remarkReadingTime() {
return (tree, file) => {
const text = nodeToText(tree);
const words = text.trim().split(/\s+/).filter(Boolean).length;
const minutes = Math.max(1, Math.round(words / WORDS_PER_MINUTE));
file.data.astro.frontmatter.minutesRead = minutes;
};
}
Wire it into astro.config.mjs under markdown.remarkPlugins, then read remarkPluginFrontmatter.minutesRead from await render(post) in your layout. Done.
The rule
If the library is shorter than its README, write it yourself. The balance between writing it yourself and another dependency to manage is worth weighing.