WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:00.846 --> 00:00:05.796 align:middle
Now that Webpack is handling
layout.js, let's simplify it!

00:00:06.466 --> 00:00:08.376 align:middle
Remove the self-executing function.

00:00:10.136 --> 00:00:15.366 align:middle
And, of course, add const $ = require('jquery').

00:00:16.476 --> 00:00:17.536 align:middle
Perfect, right?

00:00:18.246 --> 00:00:21.076 align:middle
Well... we're in for a surprise!

00:00:22.026 --> 00:00:24.036 align:middle
Go back to the main page and...

00:00:24.446 --> 00:00:26.096 align:middle
refresh! Bah!

00:00:27.026 --> 00:00:30.896 align:middle
tooltip() is not a function Uh oh!

00:00:31.546 --> 00:00:34.276 align:middle
The tooltip function comes from Bootstrap...

00:00:34.816 --> 00:00:37.856 align:middle
and if you look in our base layout, yea!

00:00:38.616 --> 00:00:42.476 align:middle
We are including jQuery and then Bootstrap...

00:00:43.286 --> 00:00:46.306 align:middle
which should add this function to jQuery!

00:00:46.946 --> 00:00:51.776 align:middle
But be careful: this is where
Webpack can get tricky!

00:00:52.486 --> 00:01:00.296 align:middle
Internally, the Bootstrap JavaScript
expects there to be a global jQuery variable

00:01:00.566 --> 00:01:03.096 align:middle
that it can add the tooltip() function to.

00:01:03.656 --> 00:01:06.546 align:middle
And there is a global jQuery variable!

00:01:06.976 --> 00:01:10.706 align:middle
It's this jQuery that's included in the layout.

00:01:11.456 --> 00:01:16.966 align:middle
So, Bootstrap adds .tooltip()
to that jQuery object.

00:01:17.536 --> 00:01:21.716 align:middle
But, in layout.js, when we require('jquery'),

00:01:22.116 --> 00:01:26.326 align:middle
this imports an entirely
different jQuery object...

00:01:26.736 --> 00:01:30.206 align:middle
and this one does not have the tooltip function!

00:01:31.326 --> 00:01:35.646 align:middle
To say this in a different way,
if you look at just this file,

00:01:36.046 --> 00:01:38.776 align:middle
we are not requiring bootstrap...

00:01:39.446 --> 00:01:45.266 align:middle
so it should be no surprise that bootstrap
hasn't been able to add its tooltip function!

00:01:46.516 --> 00:01:47.256 align:middle
What's the fix?

00:01:47.856 --> 00:01:49.536 align:middle
Require Bootstrap!

00:01:49.666 --> 00:01:59.886 align:middle
Find your open terminal and run: yarn add
bootstrap@3 -- dev Bootstrap 4 just came out,

00:02:00.026 --> 00:02:02.406 align:middle
but our app is built on Bootstrap 3.

00:02:03.836 --> 00:02:08.356 align:middle
Now that it's installed, go back
and add: require('bootstrap').

00:02:09.756 --> 00:02:11.006 align:middle
And... that's it!

00:02:11.546 --> 00:02:14.206 align:middle
Well, there is one strange thing...

00:02:14.626 --> 00:02:17.646 align:middle
and it's really common for jQuery plugins:

00:02:18.276 --> 00:02:22.406 align:middle
when you require bootstrap,
it doesn't return anything.

00:02:23.216 --> 00:02:27.156 align:middle
Nope, its whole job is to modify jQuery...

00:02:27.356 --> 00:02:28.956 align:middle
not return something.

00:02:29.906 --> 00:02:32.296 align:middle
Now that it's fixed, go back and...

00:02:32.296 --> 00:02:35.076 align:middle
refresh! What!

00:02:35.566 --> 00:02:37.316 align:middle
The same error!!!

00:02:38.086 --> 00:02:41.686 align:middle
This is where things get really interesting.

00:02:42.686 --> 00:02:46.986 align:middle
At this point, we're no longer
using the global jQuery variable

00:02:47.126 --> 00:02:54.726 align:middle
or Bootstrap JavaScript anywhere: all of
our code now uses proper require statements.

00:02:55.636 --> 00:02:58.796 align:middle
To celebrate, remove the two
script tags from the base layout.

00:02:59.536 --> 00:03:00.426 align:middle
And now...

00:03:00.526 --> 00:03:04.806 align:middle
refresh! Fascinating!

00:03:05.286 --> 00:03:09.926 align:middle
jQuery is not defined And it's
coming from inside of Bootstrap!

00:03:10.836 --> 00:03:16.876 align:middle
Ah, ha! When we require bootstrap,
internally in that file,

00:03:17.436 --> 00:03:23.356 align:middle
it looks for a global variable
called jQuery and then modifies it.

00:03:23.896 --> 00:03:32.646 align:middle
But when you require jquery, it does not create
a global variable: it just returns a value.

00:03:33.186 --> 00:03:38.576 align:middle
And now that there is no global
jQuery variable available, it fails!

00:03:39.676 --> 00:03:43.536 align:middle
This is a really common situation
for jQuery plugins...

00:03:43.826 --> 00:03:46.236 align:middle
and there's a great fix.

00:03:46.836 --> 00:03:49.286 align:middle
Actually, there are two ways to fix it...

00:03:49.376 --> 00:03:51.016 align:middle
but only one good one.

00:03:51.846 --> 00:03:58.036 align:middle
The ugly fix is to say window.jQuery
= $. Try it!

00:03:58.376 --> 00:03:59.956 align:middle
Go back and refresh!

00:04:01.006 --> 00:04:01.996 align:middle
All better.

00:04:02.616 --> 00:04:05.696 align:middle
Yep, we just made a global variable...

00:04:06.116 --> 00:04:09.906 align:middle
so that when we require bootstrap, it uses it.

00:04:10.306 --> 00:04:11.676 align:middle
But... come on!

00:04:12.146 --> 00:04:17.276 align:middle
We're trying to remove global variables
from our code - not re-add them!

00:04:17.276 --> 00:04:25.976 align:middle
So here's the better solution: go to
webpack.config.js and add autoProvidejQuery().

00:04:27.186 --> 00:04:27.696 align:middle
That's it.

00:04:27.696 --> 00:04:37.016 align:middle
Find your terminal and restart Webpack: And...

00:04:37.396 --> 00:04:40.886 align:middle
refresh! Yes!

00:04:41.326 --> 00:04:43.666 align:middle
It works! But...

00:04:43.916 --> 00:04:45.796 align:middle
what the heck just happened?

00:04:46.866 --> 00:04:51.976 align:middle
You've just experienced a
crazy super power of Webpack.

00:04:52.906 --> 00:04:58.106 align:middle
Thanks to autoProvidejQuery(),
whenever Webpack finds a module

00:04:58.446 --> 00:05:06.516 align:middle
that references an uninitialized global
jQuery variable - yep, Webpack is smart enough

00:05:06.516 --> 00:05:11.946 align:middle
to know this - it rewrites
that code to require('jquery').

00:05:12.906 --> 00:05:18.376 align:middle
Yea... it basically rewrites the
code so that it's written correctly!

00:05:19.296 --> 00:05:25.956 align:middle
And so suddenly, Bootstrap requires the
same jquery instance that we're using!

00:05:26.696 --> 00:05:30.256 align:middle
This makes jQuery plugins work beautifully.

00:05:30.976 --> 00:05:35.326 align:middle
Oh, but there's one other jQuery
legacy situation I want to mention.

00:05:36.026 --> 00:05:41.866 align:middle
If you're upgrading an existing app to
Webpack, then you might not be able to move all

00:05:41.866 --> 00:05:45.076 align:middle
of your JavaScript out of
your templates at once.

00:05:46.076 --> 00:05:49.716 align:middle
And that JavaScript probably needs jQuery.

00:05:50.736 --> 00:05:56.296 align:middle
Here's my recommendation: remove jQuery from
the base layout like we've already done.

00:05:56.976 --> 00:06:03.816 align:middle
But then, in your layout.js file,
require jquery and add: global.

00:06:04.066 --> 00:06:10.726 align:middle
$ = $. This global variable is
special to Webpack - well...

00:06:11.016 --> 00:06:14.836 align:middle
it's technically a Node thing,
but that's not important.

00:06:15.486 --> 00:06:20.596 align:middle
The point is, when you do this,
it creates a global $ variable,

00:06:20.906 --> 00:06:24.566 align:middle
which means that any JavaScript in
your templates will be able to use it -

00:06:25.006 --> 00:06:30.636 align:middle
as long as you make sure your code is
included after your layout.js script tag.

00:06:31.366 --> 00:06:34.906 align:middle
Later, you should totally remove
this when your code is refactored.

00:06:35.546 --> 00:06:37.756 align:middle
But, it's a nice helper for upgrading.

00:06:38.866 --> 00:06:43.046 align:middle
Next, let's talk about how
CSS fits into all of this!

