Lazy-loading jQuery with webpack only when you need it

tomat
tomat
Published in
2 min readJan 4, 2017

--

Have you almost gotten rid of jQuery from your app, but still need it for a few critical things? Are those things used in only some parts of your app? Try this.

We are in the process of removing jQuery from a large React project, but we didn’t have the time to field replacements for all our dependencies. It’s one thing to replace $('.myclass').something() statements with document.querySelector('.myclass').somethingElse() . That might be boring, but it’s not difficult.

Replacing a whole jQuery plugin however might be a bit more work.

As an example we’ll use the text editor plugin Redactor, but you can apply this to basically anything that is loadable through an import statement; jQuery plugin or not.

Let’s set the stage for our small example. We’re assuming this is a React app with webpack configured properly, etc. jQuery is installed through npm, and Redactor is just a regular .js file that we stuck in our app directory.

app/
components/
MyTextEditor.js
lib/redactor/
redactor.js
node_modules/
jquery/
...

Now in this example the only place we use jQuery is in MyTextEditor.js, so we don’t want to load jQuery unless that component is mounted. If we use a regular import statement (or alias $ or jQuery in webpack), it will be bundled up with the rest of our JS and loaded anyway, adding precious milliseconds to our loading time.

However, we can use import() to load some things asynchronously, which will make webpack do a separate bundle that will load only when that code runs.

Let’s see what that looks like.

So unless jQuery is imported anywhere else in the app, webpack will put jQuery and Redactor in their own files, so they won’t bloat your main app bundle.

However, this will actually render a regular textarea until jQuery and Redactor has been loaded. Let’s at least fix that.

There, now we just render Loading... until the component state is updated, and then the textarea is rendered, and Redactor is initiated.

Note: import used in this way requires webpack 2.2 or later, and currently also requires a Babel plugin (dynamic-import) to work. If you are still on webpack 1.x you should instead use require.ensure which works pretty much the same way. See the webpack documentation for more information.

--

--