WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:02.026 --> 00:00:06.386 align:middle
We already added the app entry files
to our base layout: the &lt;script&gt; tag

00:00:06.386 --> 00:00:08.346 align:middle
and the &lt;link&gt; tag both live here.

00:00:09.026 --> 00:00:14.066 align:middle
This means that any time we have some
CSS or JavaScript that should be included

00:00:14.066 --> 00:00:18.156 align:middle
on every page, we can put it in app.js.

00:00:19.146 --> 00:00:21.526 align:middle
Look down at the bottom.

00:00:21.636 --> 00:00:27.146 align:middle
Ah... we have a few script tags for
external files and some inline JavaScript.

00:00:27.376 --> 00:00:28.826 align:middle
Shame on me!

00:00:29.546 --> 00:00:33.816 align:middle
Let's refactor all of this into
our new Encore-powered system.

00:00:33.816 --> 00:00:36.846 align:middle
The first thing we include is jQuery...

00:00:37.106 --> 00:00:39.506 align:middle
which makes sense because we're using it below.

00:00:40.046 --> 00:00:42.276 align:middle
Great! Get rid of it.

00:00:43.066 --> 00:00:44.306 align:middle
Not surprisingly...

00:00:44.396 --> 00:00:49.986 align:middle
this gives us a nice, big error:
$ is not defined No worries!

00:00:50.406 --> 00:00:54.366 align:middle
One of the most wondrous things
about modern JavaScript is

00:00:54.366 --> 00:00:58.016 align:middle
that we can install third-party
libraries properly.

00:00:58.566 --> 00:01:01.006 align:middle
I mean, with a package manager.

00:01:01.096 --> 00:01:08.346 align:middle
Find your terminal and run: yarn add jquery
-- dev The -- dev part isn't important.

00:01:08.956 --> 00:01:13.966 align:middle
Technically we only need these
files during the "build" process...

00:01:14.236 --> 00:01:16.676 align:middle
they don't need to be included on production...

00:01:17.166 --> 00:01:19.726 align:middle
which is why the -- dev makes sense.

00:01:20.116 --> 00:01:23.666 align:middle
But in 99% of the cases, it doesn't matter.

00:01:24.546 --> 00:01:28.216 align:middle
We'll talk about production builds and
deploying at the end of the tutorial.

00:01:29.026 --> 00:01:30.986 align:middle
And... that was painless!

00:01:31.176 --> 00:01:33.626 align:middle
We now have jQuery in our app.

00:01:33.626 --> 00:01:39.006 align:middle
We already know how to import a file
that lives in a directory next to us.

00:01:39.466 --> 00:01:44.426 align:middle
To import a third party library,
we can say import $ from,

00:01:44.796 --> 00:01:47.766 align:middle
and then the name of the package: jquery.

00:01:48.816 --> 00:01:51.106 align:middle
The critical thing is that there is no .

00:01:51.276 --> 00:01:53.926 align:middle
or ./ at the start.

00:01:54.716 --> 00:02:00.636 align:middle
If the path starts with a ., Webpack knows
to look for that file relative to this one.

00:02:01.316 --> 00:02:07.126 align:middle
If there is no ., it knows to look for
it inside the node_modules/ directory.

00:02:07.976 --> 00:02:10.976 align:middle
Check it out: open node_modules/ and ...

00:02:13.876 --> 00:02:15.266 align:middle
there's it is!

00:02:15.266 --> 00:02:16.646 align:middle
A jquery directory!

00:02:17.146 --> 00:02:21.706 align:middle
But how does it know exactly
which file in here to import?

00:02:22.516 --> 00:02:24.156 align:middle
I'm so glad you asked!

00:02:24.736 --> 00:02:26.946 align:middle
Open jQuery's package.json file.

00:02:28.066 --> 00:02:30.336 align:middle
Every JavaScript package you install...

00:02:30.716 --> 00:02:35.396 align:middle
unless it's seriously ancient,
will have a main key

00:02:35.516 --> 00:02:38.896 align:middle
that tells Webpack exactly
which file it should import.

00:02:40.266 --> 00:02:45.816 align:middle
We just say import 'jquery', but it
really imports this specific file.

00:02:46.566 --> 00:02:52.716 align:middle
Cool! We've imported jQuery in
app.js and set it to a $ variable.

00:02:53.566 --> 00:03:00.216 align:middle
And because that &lt;script&gt; tag is included
above our inline code in base.html.twig,

00:03:00.586 --> 00:03:04.816 align:middle
the $ variable should be
available down here, right?

00:03:05.486 --> 00:03:09.256 align:middle
Nope! $ is still not defined!

00:03:10.346 --> 00:03:12.456 align:middle
Wait, the second error is more clear.

00:03:14.776 --> 00:03:20.376 align:middle
Yep, $ is not defined, coming
from our code in base.html.twig.

00:03:21.566 --> 00:03:24.626 align:middle
This uncovers a super important detail.

00:03:25.126 --> 00:03:30.346 align:middle
When you import a file from a 3rd party
library, that file behaves differently

00:03:30.546 --> 00:03:37.206 align:middle
than if you add a &lt;script&gt; tag on your
page that points to the exact same file!

00:03:37.526 --> 00:03:42.296 align:middle
Yea! That's because a well-written
library will contain code

00:03:42.296 --> 00:03:47.606 align:middle
that detects how it's being used
and then changes its behavior.

00:03:48.506 --> 00:03:50.476 align:middle
Check it out: open jquery.js.

00:03:50.476 --> 00:04:02.056 align:middle
It's not super easy to read, but look at
this: if typeof module.exports === "object".

00:04:02.456 --> 00:04:03.856 align:middle
That's key.

00:04:04.466 --> 00:04:10.696 align:middle
This is jQuery detecting if it's being used
from within an environment like Webpack.

00:04:11.116 --> 00:04:19.196 align:middle
If it is, it exports the jQuery object in
the same way that we're exporting a function

00:04:19.366 --> 00:04:22.106 align:middle
from the get_nice_message.js file.

00:04:23.516 --> 00:04:27.426 align:middle
But if we are not in a module-friendly
environment like Webpack...

00:04:27.796 --> 00:04:34.886 align:middle
specifically, if jQuery is being loaded via a
script tag in our browser, it's not too obvious,

00:04:35.556 --> 00:04:38.856 align:middle
but this code is creating a global variable.

00:04:39.606 --> 00:04:44.846 align:middle
So, if jQuery is in a script
tag, we get a global $ variable.

00:04:45.486 --> 00:04:52.276 align:middle
But if you import it like we're doing
here, it does not create a global variable.

00:04:53.026 --> 00:04:59.126 align:middle
It returns the jQuery object, which
is then set on this local variable.

00:04:59.716 --> 00:05:01.656 align:middle
Also, all modules...

00:05:01.736 --> 00:05:07.676 align:middle
or "files", in Webpack live in "isolation":
if you set a variable in one file,

00:05:07.946 --> 00:05:14.036 align:middle
it won't be available in any other file,
regardless of what order they're loaded.

00:05:14.976 --> 00:05:18.576 align:middle
That is probably the biggest
thing to re-learn in Webpack.

00:05:19.176 --> 00:05:21.406 align:middle
Global variables are dead.

00:05:22.096 --> 00:05:23.316 align:middle
That's awesome.

00:05:23.836 --> 00:05:26.566 align:middle
But it also changes everything.

00:05:27.776 --> 00:05:32.446 align:middle
The ultimate solution is to refactor
all of your code from your templates

00:05:32.446 --> 00:05:36.296 align:middle
and un-Webpack-ified JavaScript
files into Encore.

00:05:37.156 --> 00:05:41.346 align:middle
But... if you're upgrading
an existing site, phew!

00:05:42.286 --> 00:05:46.016 align:middle
You probably have a ton of
JavaScript that expects there

00:05:46.016 --> 00:05:48.996 align:middle
to be global $ or jQuery variables.

00:05:49.626 --> 00:05:52.996 align:middle
Moving all of that into Encore all at once...

00:05:53.096 --> 00:05:53.806 align:middle
it's, uh...

00:05:54.266 --> 00:05:56.026 align:middle
not very realistic.

00:05:56.026 --> 00:06:01.606 align:middle
So, if you really want a global
variable, you can add one with global.

00:06:01.606 --> 00:06:06.336 align:middle
$ = $. That global keyword
is special to Webpack.

00:06:07.386 --> 00:06:09.016 align:middle
Try it now: refresh!

00:06:10.646 --> 00:06:13.116 align:middle
It works! But...

00:06:13.616 --> 00:06:15.886 align:middle
don't do this unless you have to.

00:06:16.506 --> 00:06:21.336 align:middle
I'll remove it and add some comments to
explain that this is useful for legacy code.

00:06:22.486 --> 00:06:27.846 align:middle
Let's properly finish this next by
refactoring all our code into app.js,

00:06:28.186 --> 00:06:33.306 align:middle
which will include installing two more
libraries and our first jQuery plugin...

00:06:33.306 --> 00:06:37.736 align:middle
It turns out that jQuery
plugins are a special beast.

