New Year Codebase Health Check: A January Checklist for Development Teams
A practical January checklist for development teams: audit dependencies, target test coverage, prune...
Plenty of sites still running jQuery are perfectly healthy. The pages load, the forms submit, and nobody has complained in years. The real problem is the cost of change: the plugin you rely on was last updated in 2016, the build is a pile of concatenated files, and every new feature means negotiating with code nobody wants to touch. Migrating isn't about fashion. It's about making the front end editable again.
It also doesn't have to be a rewrite. A controlled migration — audit, replace, test, roll out — gets you to modern JavaScript without freezing the roadmap for six months.
Start with a search, not a plan. Run a project-wide search for "$(" and "jQuery." across your templates and scripts, and note where each hit lives. Then categorise them by the job they do: DOM selection and class juggling, AJAX requests, animation, form validation, or a third-party plugin.
Plugins decide your timeline, so list every one with its version and whether it is still maintained. Date pickers, carousels, modals and table sorters are the usual suspects, and most now have a native or well-supported replacement. While you're in there, flag the places where JavaScript is load-bearing: content that only appears after a click, navigation that depends on a script, forms that will not submit without one. Those are your risk points, and they set the order of work.
There are two honest strategies. The first keeps jQuery loaded while you replace features one at a time, then removes the library in a final pass. The second rebuilds the front end wholesale. Choose the first unless the templates are being rewritten anyway, because it keeps the site shippable every week instead of every quarter.
Serving both libraries has a cost. jQuery is roughly 30KB minified and gzipped, and it can't be tree-shaken, so you pay for all of it even if you use a handful of methods. If what remains is two AJAX calls and some class toggling, the final removal is straightforward. If you have eight plugins, it isn't, and that's worth knowing before you promise a deadline.
A migration is the right moment to stop depending on JavaScript for things the browser already does well. Server-rendered links and forms should work with scripting switched off; the script layer then adds speed, filtering and inline validation on top. If a menu only opens with JavaScript, it still needs a real button element to trigger it — not an anchor with a href of "#", which keyboard users and screen readers will thank you for avoiding.
For newer APIs, detect the feature rather than the browser:
Where a polyfill is genuinely needed, load it conditionally: a short inline check that injects the script only when the feature is missing, or the nomodule attribute for older browsers. Never sniff the user agent string. It lies, and it keeps lying after every browser update.
Most jQuery code is a small set of idioms repeated many times. Learn the modern equivalent of each and the migration becomes mechanical:
If you must write innerHTML with content from a form, a query string or a third-party API, sanitise it first. That risk existed in the jQuery version too, but a rewrite is a good time to fix it.
Write end-to-end tests against the current site first. Playwright or Cypress will do; pick whichever your team already argues about least. Cover the paths that cost money or trust: search, sign-up, checkout, password reset, the contact form. Run them against the jQuery version until they pass. That passing suite is your baseline, and it's what lets you move quickly without holding your breath.
Then work in small changes. Replace one behaviour, run the suite, commit. When something breaks you'll know exactly which change caused it, which is the entire point of the exercise.
Ship each replacement behind a flag or to a small share of traffic, and watch your error reporting and Core Web Vitals for a few days. Removing jQuery can change timing in ways you didn't plan for: code that quietly relied on jQuery's ready ordering, or on a global "$", will throw the moment the library disappears. Keep the previous release easy to restore for at least one cycle.
Start with the component that has the most traffic and the least risk — a header menu, a filter, a newsletter form. Replace it, test it, ship it, then repeat. Keep a running list of remaining jQuery usage somewhere visible and watch the number shrink. When it reaches zero, delete the script tag and enjoy the smaller bundle.
The goal isn't to be modern for its own sake. It's to reach a front end where a new feature takes an afternoon rather than a week of negotiating with code from 2014.
A practical January checklist for development teams: audit dependencies, target test coverage, prune...
CSS Grid usually breaks on mobile because of sizing floors, not the grid itself. Here's why implicit...
A practical checklist for keeping personal data out of application logs, setting sensible retention...