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.
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.
I havent even realized there is a library for this. I definitely do this myself as well, but I can understand why youd use someone elses well tested implementation.
This is the question of software development. What are the tradeoffs between doing it yourself and relying on a dependency.
And when using a dependency there are some more questions on how exactly to handle that. Do you fork the repository (or even copy/paste directly into your application) and use your own "safe" copy or do you trust NPM? Do you pull in updates when they become available on NPM? What's your process for validating changes to this dependency? Dependency management can be a lot of work if you are cautious.