How to prevent “Uncaught ReferenceError: jQuery / $ is not defined”

When you want to build a microsite, jQuery can help you simplify client side interactivity. If you build your website with WordPress, then you will be able to use jQuery in the custom theme that you are building.

Since you will base your site interactivity on jQuery, you may write JavaScript codes that throw the following error:

Uncaught ReferenceError: jQuery / $ is not defined.

In some cases, the error may appear randomly, making it hard to detect.

So how can we prevent our JavaScript codes from throwing a "Uncaught ReferenceError: jQuery / $ is not defined"?

In order to prevent our JavaScript codes from throwing a "Uncaught ReferenceError: jQuery / $ is not defined", we need to ensure that the jQuery library:

  1. is available for the browser to download.
  2. is loaded before any of our JavaScript codes uses $ or jQuery

1. Making sure that the jQuery library is available for the browser to download

First of all, we need to ensure that the URL to a copy of jQuery library valid.

If you are using Chrome, then you can use the developer tool to check if the URL is valid.

When the URL to a copy of jQuery library is invalid, you should find a 404 error in the console.

So how do you get to the console?

In order to do so, right-click on your web page and choose Inspect.

After the chrome developer tool is loaded, click on the cross icon:
chrome developer tool with 2 errors

When you have done so, you should be able to see a 404 being reported in the console.
chrome developer console showing 404 (Not Found) to jQuery library

As shown above, the browser is not able to get ajquery-3.5.1.slim.min.js from the server. In this case, we had accidentally typed an extra a in front of the file name.

When that happens, any usage of the $ variable will report a "Uncaught ReferenceError: $ is not defined".

In case you are wondering, these are the HTML and JavaScript codes that caused the errors:

<html>
<head>
    <title>Saying hello</title>
</head>
<body>
    <script src="https://code.jquery.com/ajquery-3.5.1.slim.min.js"></script>
    <script>
        $(document).ready(function() {
            alert('Hello there');
        });
    </script>
</body>
</html>

Even though the URL can be a valid link to a jQuery library, the browser may fail to retrieve it because the server is down.

In order to ensure that the browser loading your codes can load a jQuery library, you can:

  1. Host the jQuery library on the HTTP server / reverse proxy server that serves your JavaScript codes. If your server is unavailable, then your JavaScript codes will not run anyway.
  2. Get a copy of jQuery from one of the Content Delivery Networks that host jQuery libraries. For example, you can link to a copy of jQuery from jQuery CDN, Google Hosted Libraries or cdnjs. One advantage of using a popular CDN is that your website visitor may have already downloaded the jQuery library that your codes references. When that happens, the jQuery library is fetched from the browser's cache directly. In addition to that, even if a download is needed, the CDN will direct the browser to the nearest server. Therefore the jQuery library can be loaded in the shortest possible time.

2. Making sure that the jQuery library is loaded before any of your JavaScript codes uses $ or jQuery

If you can control the inclusion of jQuery library on your web page, the most straightforward way is to tell the browser to download jQuery library before running our JavaScript codes:

<html>
<head>
    <title>Saying hello</title>
</head>
<body>
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script>
        $(document).ready(function() {
            alert('Hello there');
        });
    </script>
</body>
</html>

As shown above, the inline JavaScript will not run until the browser finish loading and running jquery-3.5.1.slim.min.js. Therefore, the reference to the $ variable will always be valid if the server at code.jquery.com is able to return jquery-3.5.1.slim.min.js in a HTTP response.

But what if you have no control to where your JavaScript codes is placed or how the script element to the jQuery library is written?

For example, the following code tell the browser to load the jQuery library asynchronously:

<html>
<head>
    <title>Saying hello</title>
</head>
<body>
    <script async src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script>
        $(document).ready(function() {
            alert('Hello there');
        });
    </script>
</body>
</html>

When the browser sees the above HTML file, it will download jquery-3.5.1.slim.min.js without blocking the parser. Therefore, the $ variable can be referenced before the jQuery library is being loaded by the browser. When that happens, you will not be able to see the alert popup.

If there are lots of codes in between the two script elements, then the error may not be apparent.

So how can we make sure that the jQuery library is loaded before any of our JavaScript codes uses $ or jQuery variable?

In order to do so, we can test whether window.jQuery is defined before referencing the $ or jQuery variable. If window.jQuery is not defined yet, then we wait for some time before checking again.

When window.jQuery is defined, we can then run our JavaScript codes that references the $ or jQuery variable.

Given that, we can rewrite our example as follows:

<html>
<head>
    <title>Saying hello</title>
</head>
<body>
    <script async src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script>
        function run() {
            if (window.jQuery) {
                $(document).ready(function() {
                    alert('Hello there');
                });
            }
            else {
                setTimeout(run, 50);
            }
        }
        run();
    </script>
</body>
</html>

After the code change, we can be sure that usage of the $ variable only happens after the browser loads the jQuery library.

About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns techcoil.com and hopes that whatever he had written and built so far had benefited people. All views expressed belongs to him and are not representative of the company that he works/worked for.