There's a fundamental tradeoff here between efficiency and resiliency, and when 12.5% of the internet can have an outage because of one provider going down, I think we've swung way too far away from resiliency, as a society.
(If you want to avoid getting tracked this way, Decentraleyes is a useful browser extension)
One of the significant benefits touted by CDNs is speed, but this doesn't make as much sense as it once did.
First off, modern browsers don't cache requests to CDNs across multiple domains, since that can be used to track users — this means that even if someone has already downloaded the library you're including from the CDN on one website, they'll have to download it again when they visit your website. Note that this re-downloading doesn't actually protect against any of the privacy concerns mentioned above (and in fact makes them much worse), it's only to stop random websites from being able to tell what other websites you've visited via cache timing attacks.
Beyond just privacy, it's reasonable to be concerned that an attacker might be able to compromise end-users by hacking a CDN. Luckily, there is a way to protect against this — modern web browsers have a feature called Subresource Integrity, which allows you to specify a hash of the expected contents of a script tag (if you're using libraries via a CDN, you should be doing this! It's pretty simple, and has nothing but upside in terms of security).
Unfortunately, this doesn't yet work in all cases — if a library is split into multiple files (to reduce initial load time/size), browsers currently only allow the main file to have a SRI hash specified. I'm hopeful that this can be fixed in the future, but it's not there yet. (To be clear, using SRI on the initial bundle still provides a meaningful increase in security — the fact that it doesn't work in some, frankly somewhat niche cases isn't a reason not to use it in general!)
What to do instead
The takeaway here is that if you're using a CDN for any reason other than laziness, it's likely not a good reason.
What I do is just download the library that I want and include the files in my repo, just like any other source file. I usually do this in a directory called
3p, and be sure to include the version number of the package that I downloaded in the filename. This takes maybe 60 seconds more work than including the CDN version, which seems worth it to me for the privacy, robustness, and speed benefits.
If you are going to use a CDN, at the very least, include a SRI hash — they're super easy to generate with this tool. And if you're a library author who writes install instructions recommending the use of a CDN, definitely include a SRI hash — that way people don't need to know to do it themselves, they can just copy and paste it.