WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.026 --> 00:00:02.956 align:middle
Head back to /admin/article.

00:00:04.526 --> 00:00:05.296 align:middle
We have a...

00:00:05.446 --> 00:00:05.866 align:middle
sort of...

00:00:06.176 --> 00:00:07.786 align:middle
"performance" issue here.

00:00:08.606 --> 00:00:12.466 align:middle
When you create a new article, we
have an author field that uses a bunch

00:00:12.466 --> 00:00:14.716 align:middle
of autocomplete JavaScript and CSS.

00:00:17.536 --> 00:00:24.006 align:middle
The thing is, if you go back and edit an
article, this is purposely not used here.

00:00:24.586 --> 00:00:26.206 align:middle
So, what's the problem?

00:00:26.956 --> 00:00:28.886 align:middle
Open admin_article_form.js.

00:00:30.336 --> 00:00:32.696 align:middle
We import algolia-autocomplete...

00:00:34.566 --> 00:00:38.986 align:middle
and it imports a third-party
library and some CSS.

00:00:39.426 --> 00:00:42.606 align:middle
So, it's not a tiny amount
of code to get this working.

00:00:43.536 --> 00:00:49.986 align:middle
The admin_article_form.js entry file is
included on both the new and edit pages.

00:00:50.386 --> 00:00:55.656 align:middle
But really, a big chunk of that file
is totally unused on the edit page.

00:00:56.076 --> 00:00:56.826 align:middle
What a waste!

00:00:57.596 --> 00:01:02.796 align:middle
The problem is that you can't conditionally
import things: you can't put an if statement

00:01:02.796 --> 00:01:07.076 align:middle
around the import, because Webpack
needs to know, at build time,

00:01:07.186 --> 00:01:10.476 align:middle
whether or not it should include
the content of that import

00:01:10.476 --> 00:01:14.166 align:middle
into the final built admin_article_form.js file.

00:01:15.106 --> 00:01:17.976 align:middle
But, this is a real-world problem!

00:01:18.046 --> 00:01:25.296 align:middle
For example, suppose that when a user clicks a
specific link on your site, a dialog screen pops

00:01:25.296 --> 00:01:28.266 align:middle
up that requires a lot of JavaScript and CSS.

00:01:28.686 --> 00:01:33.126 align:middle
Cool. But what if most users
don't ever click that link?

00:01:33.426 --> 00:01:39.166 align:middle
Making all your users download the dialog
box JavaScript and CSS when only a few

00:01:39.166 --> 00:01:41.836 align:middle
of them will ever need it is a waste!

00:01:42.466 --> 00:01:44.796 align:middle
You're slowing down everyone's experience.

00:01:45.256 --> 00:01:48.526 align:middle
We need to be able to lazily load dependencies.

00:01:48.876 --> 00:01:50.036 align:middle
And here's how.

00:01:51.116 --> 00:01:53.506 align:middle
Copy the file path then delete the import.

00:01:54.816 --> 00:01:57.906 align:middle
All imports are normally at the top of the file.

00:01:58.386 --> 00:01:59.426 align:middle
But now...

00:01:59.726 --> 00:02:06.306 align:middle
down inside the if statement, this is when
we know that we need to use that library.

00:02:07.106 --> 00:02:12.126 align:middle
Use import() like a function and pass
it the path that we want to import.

00:02:13.116 --> 00:02:16.046 align:middle
This works almost exactly like an AJAX call.

00:02:16.786 --> 00:02:19.906 align:middle
It's not instant, so it returns a Promise.

00:02:20.816 --> 00:02:25.836 align:middle
Add .then() and, for the callback,
Webpack will pass us the module

00:02:25.836 --> 00:02:27.966 align:middle
that we're importing: autocomplete.

00:02:29.826 --> 00:02:33.456 align:middle
Finish the arrow function,
then move the old code inside.

00:02:36.436 --> 00:02:41.356 align:middle
So, it will hit our import code, download
the JavaScript - just like an AJAX call -

00:02:41.536 --> 00:02:44.136 align:middle
and when it finishes, call our function.

00:02:44.656 --> 00:02:49.436 align:middle
And, because the "traditional" import
call is gone from the top of the file,

00:02:49.956 --> 00:02:54.896 align:middle
the autocomplete stuff won't be
included in admin_article_form.js.

00:02:55.896 --> 00:02:58.826 align:middle
That entry file just got smaller.

00:02:59.336 --> 00:03:00.846 align:middle
That's freakin' awesome!

00:03:02.186 --> 00:03:06.496 align:middle
By the way, if we were running the code,
like, after a user clicked something,

00:03:06.736 --> 00:03:10.056 align:middle
there would be a small delay while
the JavaScript was being downloaded.

00:03:11.066 --> 00:03:16.216 align:middle
To make the experience fluid, you could add
a loading animation before the import() call

00:03:16.746 --> 00:03:18.606 align:middle
and stop it inside the callback.

00:03:22.026 --> 00:03:23.496 align:middle
Ok, let's try this!

00:03:25.396 --> 00:03:27.896 align:middle
Go back to /admin/article/new.

00:03:29.236 --> 00:03:31.076 align:middle
And... oh!

00:03:31.676 --> 00:03:35.476 align:middle
autocomplete is not a function
in article_form.js.

00:03:36.336 --> 00:03:39.206 align:middle
So... this is a little bit of a gotcha.

00:03:40.236 --> 00:03:46.746 align:middle
If your module uses the newer, trendier,
export default syntax, when you use "async"

00:03:46.966 --> 00:03:52.686 align:middle
or "dynamic" imports, you need to say
autocomplete.default in the callback.

00:03:54.626 --> 00:03:56.696 align:middle
Move back over and refresh again.

00:03:58.336 --> 00:03:59.286 align:middle
No errors!

00:04:00.526 --> 00:04:02.456 align:middle
And it works!

00:04:03.036 --> 00:04:07.156 align:middle
But also, look at the Network
tab - filter for "scripts".

00:04:09.596 --> 00:04:11.656 align:middle
It downloaded 1.js and 0.js.

00:04:11.796 --> 00:04:24.556 align:middle
The 1.js file contains the autocomplete vendor
library and 0.js contains our JavaScript.

00:04:25.166 --> 00:04:31.426 align:middle
It loaded this lazily and it's even "code
splitting" our lazy JavaScript into two files...

00:04:31.506 --> 00:04:33.206 align:middle
which is kinda crazy.

00:04:33.856 --> 00:04:36.816 align:middle
The 0.js also contains the CSS...

00:04:37.366 --> 00:04:39.366 align:middle
well, it says it does...

00:04:39.366 --> 00:04:41.136 align:middle
but it's not really there.

00:04:41.856 --> 00:04:48.026 align:middle
Because, in the CSS tab, it's
loaded via its own 0.css file.

00:04:48.026 --> 00:04:54.256 align:middle
If you look at the DOM, you can even see
how Webpack hacked the script and link tags

00:04:54.256 --> 00:04:58.676 align:middle
into the head of our page: these
were not there on page-load.

00:04:58.676 --> 00:05:01.216 align:middle
So... dynamic imports...

00:05:01.246 --> 00:05:02.166 align:middle
just work!

00:05:02.596 --> 00:05:06.756 align:middle
And you can imagine how powerful this
could be in a single page application

00:05:06.846 --> 00:05:12.936 align:middle
where you can asynchronously load the components
for a page when the user goes to that page...

00:05:13.126 --> 00:05:17.126 align:middle
instead of having one gigantic
JavaScript file for your whole site.

00:05:17.886 --> 00:05:21.396 align:middle
By the way, the dynamic import
syntax can be even simpler

00:05:21.606 --> 00:05:25.846 align:middle
if you use the await keyword
and some fancy destructuring.

00:05:26.666 --> 00:05:30.716 align:middle
You'll also need to install a
library called regenerator-runtime.

00:05:31.576 --> 00:05:33.336 align:middle
Check out the code on this page for an example.

00:05:34.316 --> 00:05:38.586 align:middle
Next: there's just one more thing to
talk about: how to build our assets

00:05:38.586 --> 00:05:41.126 align:middle
for production, and some tips on deployment.

