Thought I'd share my thoughts on small libraries like classnames
which are very used helpers, but could often be dropped in exchange for a homegrown alternative.
Here's a tiny classnames
implementation with only the most basic features:
export default (...classes) => {
const result = []
classes.forEach(a => {
if (typeof a === 'string') {
result.push(a);
} else if (Object.prototype.toString.call(a) === '[object Object]') {
Object.keys(a).forEach(b => a[b] && result.push(b))
}
})
return result.join(' ')
}
This works. I tested it. (Famous last words.)
Why was I prompted to write this? Just as an exercise. But also because I distinctly remember having a bad impression about how long the code of the library was, even though I check it now and in actuality it's very small.
But writing this put a bit into perspective into how much I'm giving up of the control of my code and its behaviour by giving the simple simple work to an external library, that perhaps could've been written in one minute like the one above.
If something doesn't work I have to check out the source, but first I've to double check which version I'm using and check its source code, not of newer or older versions, and then I've to read it. And it's in my node_modules
so to add a console.log
to it I've to edit the node_modules
file. Or at least that's how I do it.
In comparison I can just go to the utils/classnames.js
file and read it, simple enough, put debugger
statements or console.log
s or whatever. Easy.
BTW, instead of a fancy function like the above, you could actually just follow a pattern similar to the following:
const trimClassName = (class) => class.replace(/\s{2,}/g, ' ');
const Foo = () => (
<div
className={trimClassName(`
xyz
${someTruth() ? 'truth' : 'notruth'}
${someFalsety() ? 'false' : ''}
`)}
>
Hello world
</div>
);
So I just completely skipped a complex function and I just ran a search and replace for two-or-more whitespaces replacing them with one whitespace, on a string which uses built-in JS string templating.
Or another approach:
const cx = (...classes) => classes.filter(a => !!a).join(' ')
const Foo = () => (
<div
className={cx(
'xyz',
someTruth() ? 'truth' : 'notruth',
someFalsety() && 'false'
)}
>
Hello world
</div>
);
Now all that said. I realize homegrown options are not always the most performant options, but I prefer to leave the micro optimizations to the engine, and I like to work on macro optimizations.
Let me know your thoughts, often people I talk to prefer to use a library because "somebody already wrote it, no need to write it ourselves", but in some places I disagree with this.
Top comments (1)
This is the question of software development. What are the tradeoffs between doing it yourself and relying on a dependency.