Phasing out jQuery

Rupert Angermeier
Jul 5, 2018 · 3 min read

There was a time, when it was considered good practice among frontend developers to use jQuery for everything. Back in that time we started to build the Trayn web app. Since then, a lot of things changed, among them what are considered good practices. Well, best practices in JavaScript land change every second month or so, but good is good enough for me in that case.

In the ongoing struggle to modernize our code base, I recently started to phase out jQuery. What do I mean with phasing out? The app is too big to rewrite all code that relies on jQuery in one go. But since the base functionality of the app (session management, routing, localization, etc.) was already modernized in the last months, only the detail views (there are a lot of them) are using jQuery and various of its plugins. So the plan is to port/modernize one of these views after the other.

Image for post
Image for post
The gloomy road to a golden code base. Photo by Sven Wilhelm on Unsplash

But why?

Why removing jQuery at all? It’s still working…

Well, it’s not just jQuery we want to remove, it’s more about plugins and frameworks on top of it and — more specifically — the way we use them. Huge parts of these views use outdated versions of can.js, Bootstrap, and FullCalendar, and updating all that code at once seems harder to handle than migrating view-by-view to a more modern component based architecture.

Taming our jQuery Plugins

Using jQuery plugins together with Webpack can be tricky, since they usually register them on whatever jQuery instance they get thrown at. Because Webpack is putting everything into its own scope, each plugin would end up on a different jQuery instance. To handle this, Webpack provides the externals configuration option, which can be used to exclude some packages from the build, if they are loaded from somewhere else. This allows us to use one global jQuery instance and not breaking any plugin.

Additionally, we’re copying the minified jQuery file to our output directory for later use:

To jQuery or not to jQuery?

This leaves the challenge of actually loading jQuery when it’s needed. After trying some things, I decided to do this in our routing layer, which uses Vue Router. I added a boolean flag jquery to the meta field of routes that are still using legacy code. We check for it in the beforeEach hook: if the flag is present, navigation is blocked until jQuery is loaded. We can’t use import() or require() here, because we instructed Webpack to treat jQuery as an external dependency, so we’re using scriptjs:


Using this approach, we were able to defer loading jQuery until it is actually needed. We now need to maintain those jquery flags in our route config when we modernize views, but we didn’t need to adapt any of our legacy code and reduced the download size of the modernized parts of our web app.

And I used the word “jQuery” only 15 times in this article (not counting titles and code samples) without inventing any aliases for it.

Trayn Engineering

The Engines Behind Professional Sports Planning

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store