How to limit dependency on 3rd party tools and libraries

Software engineer with 10 years of experience working on frontend applications and tooling to make frontend development easier.
Search for a command to run...

Software engineer with 10 years of experience working on frontend applications and tooling to make frontend development easier.
No comments yet. Be the first to comment.
The id attribute is arguably one of the most popular attributes used in HTML, second only to the class attribute. It serves a lot of purposes, which means it can easily be misunderstood or misused. Let's take a look at what it's really for, what it's...

The URL can be a powerful tool for sharing and managing the state of an app, but it's often overlooked or misunderstood. When properly done, the typical CRUD app with read/write/edit/delete functionality doesn't need much more state management than t...

Why you should never rely on the default sort

There should be at least two ways for any user to submit a form. Pointer users should be able to press a submit button, and keyboard users should be able to press the enter key. Both of these UX behaviors are provided natively by the browser, given a...

The vast majority of design systems and component libraries organize their styles using class selectors. Generally, this is a good choice, but it's not perfect. Methodologies like BEM are used as a way to organize these classes into component and mod...

webdev.tips
6 posts
Awesome tips and tricks about JavaScript, TypeScript, CSS, Vue, React, and all things webdev.
NPM and other package managers have made integrating 3rd party libraries easier than ever.
Need to build a UI? There's a package for that.
Need to format time? There's a package for that.
Need to add authentication? There's a package for that.
Nowadays there's open-sourced code that does practically everything. Just npm install it and you're on your way. Simple enough, right?
But what happens when that package you installed stops being maintained or you find out has a security vulnerability? What do you do when a newer, faster, and smaller package is released?
It's easy to allow 3rd party code to weave and integrate itself into your app, and it's only until you need to replace or remove it that you realize it's become more of a weed than a benefit.
Refactoring and changing libraries is eventually inevitable in practically any long-term project. So what can you do to make the migration process easier?
To reduce dependency on a 3rd party library, you can create a single entry point where the 3rd party library is accessed. Then, throughout the app, you can access the local entry point instead of accessing the package directly. The day you decide to migrate, all you have to do is migrate the entry point instead of every instance the package was used.
Wrapping 3rd party libraries in this manner also makes it easier for you to add or modify functionality if something needs to be adjusted.
If the newer library has a different API, or if you just aren't a fan of the API, to begin with, this allows you to create your own custom API while reaping all the rewards of using an existing library.
Let's say there's a package we want to add called text-upper that capitalizes text.
Instead of accessing the package directly, first, we create an entry point in say utils/caseChanger. Usually, it's better to name it something generic or descriptive instead of just naming the entry point the same as the package.
Inside the entry point can be something as simple as:
import TextUpper from 'text-upper'
export default TextUpper
Then anytime we need to upper case text we just access the library through our entry point like so:
import caseChanger from './utils/caseChanger'
upperCase.makeUpperCase('hello world')
Later on, we find an even better package called textMcChanger that not only makes text uppercase but also makes text lowercase too. We definitely want that.
So now all we have to do is modify our entry point to use this new package. And even though the new package has a slightly different API for capitalizing text, we only have to modify our entry point to ensure everywhere we're already capitalizing text doesn't also need to be refactored.
Our migration in the utils/caseChanger might end up looking something like this:
import betterPackage from 'textMcChanger'
// Modify API for backwards compatibility
betterPackage.makeUpperCase = text => betterPackage.upper(text, true)
// Modify API for consistency with old API
betterPackage.makeLowerCase = text => betterPackage.lower(text, true)
export default betterPackage
Easy enough, right? All we had to do was change this one file and our app instantly reaps the benefits of the new package without all the extra refactoring.
It won't make sense to wrap every package like this. It would be silly to try to add a wrapper for React as your UI library and then later try to transform Vue to work like React. But I guess you could!
For most other things though, it's a good practice to follow, and you'll thank yourself later once you find the perfect replacement and you don't have to dread the migration.