79

What is the purpose of the following code?

Note that before the second script code below, jquery.min.js is already included with googleapis.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/assets/js/vendor/jquery.min.js"><\/script>')</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Learner One
  • 623
  • 5
  • 13
  • Why not load local copy first before using CDN when you are sure the local copy is the one you need? There is probably a little speed advantage. – Learner One Apr 27 '16 at 02:24
  • 2
    Yes, it's mainly the speed advantage. [Read more here](http://stackoverflow.com/questions/2145277/what-are-the-advantages-and-disadvantages-of-using-a-content-delivery-network-c) – David Sherret Apr 27 '16 at 02:25
  • 6
    It's faster to load jquery if you already have it. Best chance to have it is when it is hosted at the same place for many websites. So basically, you want to try that first, and get it once and for all. If it fails, get the local version. – Frederik.L Apr 27 '16 at 02:37
  • 5
    It's a CDN fallback as explained here: [Best way to use Google's hosted jQuery, but fall back to my hosted library on Google fail](http://stackoverflow.com/questions/1014203/best-way-to-use-googles-hosted-jquery-but-fall-back-to-my-hosted-library-on-go) – Liam Apr 27 '16 at 10:20
  • 2
    Is there any guarantee jquery would be fully loaded off the server before that 2nd check is done anyway? – pay Apr 27 '16 at 13:28
  • 3
    @user1438893 Yes. The browser will not start executing another script while it's still loading the previous one (unless it's instructed to do otherwise, and here it's not). If that weren't the case it would be impossible to use *any* 3rd party libraries, or, in fact, any script that depends on another script. – JJJ Apr 27 '16 at 18:57

4 Answers4

123

It's to fallback to the jquery.min.js file stored on the same server when the CDN is down or cannot be reached.

It's essentially saying:

// 1. Try to download and run https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js

// 2. Was jQuery successfully loaded from the CDN? If so, it will be defined:
if (window.jQuery) {
    // Yes, it's defined. Good. Nothing more needed.
}
else {
    // No, it's not defined. Use my copy:
    document.write('<script src="/assets/js/vendor/jquery.min.js"><\/script>')
}

Read more here and you can find the original code here.

Regarding window.jQuery || document.write(...) that is essentially shorthand for the code above. When defined window.jQuery will be truthy and so the statement on the right hand side of || will not be executed; however, if it's not defined it will be falsy and the statement on the right hand side of || will be executed.

Community
  • 1
  • 1
David Sherret
  • 101,669
  • 28
  • 188
  • 178
  • 4
    Cool concept, I've never seen this before. Are we guaranteed that the first – loneboat Apr 27 '16 at 14:10
  • 3
    @loneboat yes, it will attempt to download and run the script before continuing to parse the page ([Source](https://developer.mozilla.org/en/docs/Web/HTML/Element/script)). It's why if you place script tags in a certain order it will run the scripts in that order instead of whatever finishes downloading first – David Sherret Apr 27 '16 at 14:18
  • 1
    Cool, didn't know that. I [mistakenly] thought when it encountered a – loneboat Apr 27 '16 at 14:22
  • 6
    @loneboat As an aside, HTML5 provides the `async` attribute which causes ` – MTCoster Apr 27 '16 at 14:27
18

It's trying to use the version hosted on Google's CDN first. There's a chance the person viewing the site already has that exact script cached from visiting some other site, so they might as well try that first.

If the CDN version loads, window.jQuery is set, the or is short-circuited, and the code moves on.

If the CDN version can't be loaded for some reason, it adds another script tag to the page pointing to a locally-hosted version of the script.

Edit: as MTCoster points out in a comment above, this trick relies on the way JavaScript is normally loaded. The browser pauses execution until the tag loads or times out. If jQuery were loaded asynchronously using the async attribute, this trick wouldn't work.

Community
  • 1
  • 1
Dave Ross
  • 3,313
  • 1
  • 24
  • 21
7

The first script will try to load jQuery from an external website (in this case, Google CDN).

The second one will try to find the jQuery object in window, and only if it doesn't find it, then it will load the library from an internal link. It's only a fallback in the case the CDN fails.

window.jQuery || document.write(...)
// the code above means the same as the code below
if (window.jQuery === undefined) document.write(...)

In Javascript, besides booleans (true/false), there are truthy and falsy values. Anything that's different to 0, false, undefined and null is a truthy value.

In that case, if the jQuery property exists on window, it will be an object, and it will be a truthy value, so, the second statement won't run (because the first one is already true - and in an OR operator, if any of the statements is true, it skips the others (from left to right).

Although, if the jQuery property doesn't exist, it's because the first script didn't load correctly, and the property will be undefined, a falsy value. So, the second statement will run, and the local jQuery will be loaded as a fallback.

Buzinas
  • 11,597
  • 2
  • 36
  • 58
  • `window.jQuery || ...` is *not* the same as `window.jQuery === undefined`, the `||` version will still return false if `window.jQuery` is `0`, `false`, or `null` as you stated. – Octavia Togami Apr 27 '16 at 18:35
3

It is a fallback mechanism if the jquery from CDN is not reached for some reason like blocked by firewall, CDN down etc

I will add one more practical scenario I faced last year. One of my client decided to host and use the web application created by me in LAN without internet availability. With the local IIS the application was deployed properly but failed due to CDN non availability, if I had used the code mentioned in question the web app would have worked the very first time without any change.

I hope that it will makes sense now :) For me it was a lesson learnt.

Vishwajit G
  • 510
  • 4
  • 9