[MUSIC PLAYING] STEPHEN FLUIN:
Hello, and welcome. My name is Stephen Fluin. I'm a developer advocate on the
Angular team here at Google. My job is really
fun, because I get to help developers be
successful with Angular. And I get to spend a
lot of time listening and engaging with the
community so we can reflect your needs on to the team. One of the things
that we've learned, having worked with a lot of
developers across the world, is that staying up to date
is really, really important. And so today's talk
is all about how to keep your application
as fast as possible and as fresh as possible using Angular. We're going to be diving into
some of the best practices that you should be following
as an application developer. And we'll take a
look at live code and see how you could
actually go in and debug and build your application out. So let's actually get started. So if we take a look
at what we've got here, this is a application that I've
built using the Angular CLI. So it's a very, very
basic application. This should look
very, very familiar. It's basically we ran
ng new, and then we installed something
called Angular Material. And so if you take a look
at the app component, I've put in an app dashboard. And so if we ran a command like
ng serve, what we would see is a normal dashboard
of an application that's coming from Angular Material. So we've got a few
dependencies installed. We've got a few other
things installed. And all of that should just be
coming to you automatically. So here we go. This is just the
default blank dashboard. And so even though we haven't
written a ton of code, we've got an application
up and running. And it's pulling in
a ton of code, right? We're pulling in the
features of Angular necessary for these
animations, for these menus, for these dialogs,
as well as for all of this content
around this dashboard that a user could interact
with and engage with. And so the first thing
I want to do in order to make my application
fast as possible is I really want to
understand my application, so we're going to make a
couple of changes within our build configuration in
the angular.json file. So what we're going
to do is we're going to find the angular.json file. You're going to
find this directly in the root of your application. And what we're
going to do is we're going to find in the production
build settings we're going to change two settings here. We're going to say source map-- I'm going to change
that from false to true. As well as in our
names chunks, we're going to turn that one to true. What source map does
is this will actually take my application and map
all of the generated JavaScript that comes out of the build
and map it back into the code that that JavaScript came from. And so if some of the generated
code came from your interior, we'll see that. If it came from Angular
itself, we'll see that. And we'll even see things like
the generated JavaScript being mapped back to my HTML and
into the application code that I'm writing for all the
components that I'm creating. And so source maps
are a really great way for you to understand
what's going on in your application and
the relationship between what happens in the code
you write in the IDE and the codes being
delivered to your users. And so there's a lot
of steps that we end up taking along that way, right? There's the Angular compiler
that takes that HTML and turns it into JavaScript. But there's also other steps
that we do, like optimizations where we'll change some
of the property names. You've got bundling, so that
we get all of this JavaScript coming down as a single
cohesive bundle that makes sense to browsers. And so source map allows
us to follow that path, follow that process, and
give us really good insights. And so what we can do is,
having made these two changes, we can actually now go and
run an ng build --prod. And what that will do is that
will create a production build of our application, which
is normally what you should have done to browsers. But because we've
turned on source maps and we've turned on
name chunks, we'll actually see the
JavaScript and be able to analyze those chunks. And so we're also going to
be using another tool today, called Source Map Explorer. There's a bunch of
other tools out there that developers use to analyze
bundle size and chunk size. But what we, on
the Angular team, actually really
strongly recommend is you only use Source Map
Explorer, because there are tools out there, like
webpack-bundle-analyzer, that categorically misrecognize
some of those steps within our process. And so we've done
that production build. And now whenever you
want to actually take a look at what a
source map looks like, we can just run
Source Map Explorer. If you don't have
this installed, you can just install
it globally-- yarn global add
source-map-explorer. Or you can install it
local to your project. Whichever makes sense to you,
just go ahead and do that. And what we'll do is we'll
run Source Map Explorer, and we will pass it
in the JavaScript file that we want to analyze. And so we can see that we've
got our dist folder here. And we're going to look
at the es2015 version of our JavaScript. So if we run that, it's going
to pop up in a web browser. And we're going to see this
visual interactive story about our application. So we can see our overall bundle
size in terms of minified, but not compressed JavaScript. So it's actually a
little bit smaller when it goes over the network. We have about 452
kilobytes of application. And what's really,
really helpful here is that you can see where that
bundle size is coming from. So you can see animations
is 64 kilobytes. Angular Material is
about 56 kilobytes. We've got things like HTTP
where we might actually need these things. And we might not even
know in our bundle. We might have forgotten it's
somewhere along the way. So you can see I'm
pulling in forms and HTTP. If we actually go
into our application, now that we know that
those things are there, we can say, hey, I
don't actually need that for this dashboard, right? If we look at the
content I'm showing here, there's no form data here. There's no data coming
from the internet. And I can go into my app module,
and I could pull those out. And so I'll just
comment these out, because we don't
need HTTP or forms. And what should happen is, when
I do my next production bundle, all of that code's
going to be left out. And so we're going to be able
to see that our bundle size will come down from around
450kb to a little bit less than that, which is
really, really nice. And it should actually
be exactly leaving out the size of the HTTP bundle
and the size of the forms bundle. And so source maps are one of
the best tools in your toolbox. And we really recommend
that every developer be using source maps for
using this on a regular basis to understand your application,
especially when you're doing any sort of
performance optimization. Now, let's say that you
are looking at your bundle, and you're saying
it's still too big, but I need all of
those features. I need all of
those capabilities. Fortunately, the
Angular CLI offers a lot of really smart capabilities. One of those
capabilities is being able to take an application and
build out lazy loaded modules. And so let's actually
go ahead and do this. And so I'm going to
use the CLI here, and I'm going to say, ng,
which is the Angular command. And I'm going to
say, generate module. And I'm going to give it
a root module that it's going to connect back to. So what we're going
to do is we're going to create a separate
part of our application where we can pull in
features that we need and just leave all of that code
outside of the main bundle. And so we're going to
generate a module here, and I'll just link it
back to the module known as app module, which is
the root of my application. And now, I'm going
to give it a route. And so what this does
is it automatically wires up this module to
be lazy loaded whenever a user hits that route. And so we'll just make,
for example, an about page. And so what this is
going to do, it's going to generate a module
called about module. It's going to be
able to route to it. And then it's going to
give me an about component. So we can see all of
that in our source code. So let's just close
all these files, and we're going
to see it created a new about folder with our
new module and our new code. And so if we do another
production build, what we'll actually see, because
we turned on named chunks, we'll actually get
out now not only a main chunk, a
main module, we're also going to get
out an about module. And we can see and independently
verify the size of that module and independently verify what
the dependencies of that module are doing to the overall
bundle size of our application. And so what you'll see is that,
by default, an Angular module is really, really small. It's very, very thin. It doesn't add a ton of bundle
size to your application. It's almost always
the dependencies that you are pulling in, as
a developer, the features that you are reaching out for. And what Angular will
do is intelligently, based on where you do the
imports, will lazy load and split that code. So if you remember, we
pulled HTTP and forms out of our main chunk. We can actually
now pull that in. And so you can see that
we've generated a-- let's just clear this out. And let's take a look
at our dist folder here. You can see we've
got a main chunk, and now we've got this
nice new about module. And as you can see in
the es2015 version, our about module's only
about 1.1K of code. So it's just that
about component, because it doesn't
have any dependencies. But if we add back in more
dependencies into that chunk-- if we wanted to pull
in, for example, Angular Material into
that about module-- then it's going to
pull in that code. But it's going to do it
very, very intelligently. It's going to lazy
load all of that code. And so if you haven't set
up lazy loading before, it's really, really easy. Just generate a new
module with that command that I showed where
we generate a module, and we hang it onto the routing
structure of our application. All right. Next up, I want to
talk a little bit about what happens after
we build an application. After we've been
building it out and we've added more and
more features, it's very, very easy to backslide. One of the things that
the Chrome team has seen consistently is
that even applications we've spent a ton
of time building great performance into their
apps tend to backslide. Because we, as developers,
we want to add more features. We want to push more
functional into our users. And that often comes
with more dependencies, which sometimes we don't
realize is negatively affecting our bundle size. And so one of the features
that's built into the Angular CLI is called Bundle Budgets. And so, again, if we go
back into our Angular JSON-- and so we'll just
search for that-- we can see this nice
little budgets section. And what this does
is it allows you to set several different
budgets for your application. And by default, we give
you two out of the box. We give you an initial budget. So this is the
JavaScript that it takes to load the initial
page of your application. So right now, we are
warning at two megabytes. So we'll see a
warning as part of our build if our application
is over two megabytes. And our build will
actually error out if it's more than
five megabytes. And so those are very,
very conservative defaults. We recommend you turn
those as small as you can, to really just give yourself
a knowledge of when you're increasing your bundle size so
that it's a conscious choice, rather than an accident. You'll see we also have a
few other types of budgets, including any component style. So what it says is that any
scoped styles to a component, we want to keep those
under 6 kilobytes. And we are going to error out if
they become above 10 kilobytes. And there's a few
more that you can see, if you just take a
look in your IDE. You've got allScript. So that's just, what
is the total sum of all the scripts
my application? Any scripts or any
individual scripts shouldn't be bigger than this,
the whole bundle overall, all those sorts of things. So we've got a whole bunch
of different features that allow you to really
take control and understand and prevent bundle
size increases. So that's a really,
really helpful tool. So those are some
of the top things that you should be doing
to keep your application as fast as possible. But one of the
best things you can do that doesn't
take a lot of work is actually staying up
to date with Angular. So if we jump back to the
terminal here, what we'll see is that I actually created
this Angular application on an old version of Angular. It is running Version 8. So Version 8 is not
the latest version. Version 9, as of this filming,
is the latest version. And Version 10 is coming out,
but it's always the same. So if you're on an out-of-date
version of Angular, your bundle size is going to
be bigger and slower than it needs to be. Because what happens
is, over time, every time we do a
release, the Angular team is looking at what
can we do better. With the release of Version 8,
we actually made a huge step forward by automatically doing
something called differential loading, where, because we
have this opinionated control of the entire tool chain,
we understand how to make your production bundles. And so what we did is we
said, hey, modern browsers are capable of loading
JavaScript differently than legacy browsers
that don't support something called es modules. And so using that knowledge,
you can actually conditionally force modern browsers to load
modern JavaScript and legacy browsers to load
legacy JavaScript. And this is a really
nice schism that allows you to have two
bundles that really gives you the best of both worlds where
you can ship the smallest, fastest JavaScript
to modern browsers that support the most recent
capabilities, like classes, like modules, all
those sorts of things. And you can leave an
older legacy bundle for browsers that don't
have that kind of support. And so we actually did this
out of the box, by default. So you noticed when we
were doing those builds, we were actually getting
the two JavaScript bundles for each of the files. So we had an about module 2015,
and we had an about module es5. And so again, this
is one of the changes that the Angular team
did behind the scenes, without having to
make you change any of the code in
your application. And this is something that
we do every single release. And so what we're
going to do now is we're going to make
our application as fresh as possible. So we're going to update to
the latest version of Angular, and we're going to automatically
get more improvements to our bundle size. This is something
that just happens every time you keep
your application up to date using Angular. And so we're going to, again,
use the ng cli command. And we're going
to use ng update. And we're going to
update our application in a couple of stages. First, we're going to update
the Angular core packages-- so core and the core package-- as well as the CLI package. And then what we're
going to do is we're going to go and
update our dependencies. So we're going to do it
as two steps, to make sure that we don't accidentally
enter a mistake or an error where
our application is no longer compatible with
one of those dependencies. So let's go ahead
and get this started. So I'm going to run ng update. And what we're
going to do is we're going to pass it angular/cli
and angular/core. Now, if you were on an even
older version, what we do is we recommend that you
go one version at a time, just that we can
apply things cleanly. And if you want to do
that-- for example, if you were on Version 6 and
you wanted to go to Version 7-- you can just say @7, and that
will just do that for you. But we're going to go all
the way from Version 8 up to Version 9,
which is the latest. So I'm going to
run this command. And theoretically,
things should work. There's a few places
where this might fail. If your repository isn't
clean, then what should happen is we're going to throw
this warning, which is what we're seeing right now. Repository is not clean. Please commit. Because what we
want is we want you to have a very clean history
so that you actually know what the Angular update process did. Because this isn't
like a normal ng update where we're just
modifying the node modules of your project. We're actually making
changes to your application so that you stay
compatible with Angular. And the reason we're
able to do this is because the Angular
team at Google, we have thousands of
projects across Google that are not run by our
team that are using Angular. And it's actually,
according to Google policy, our responsibility for keeping
those applications working as we make breaking
changes to Angular. And so the only way that we
could scale this at Google is to build really
great automation and really great tooling. And so what we did is
we baked that same sort of tooling into the public world
into this ng update command. And so whenever we need to
change a method name, whenever we need to deprecate
something, we're going to try and update your
application as best we can. And so that's why
we always make sure that you want to
have a clean history, so we'll just git
add everything. We'll commit that. And then we should be able
to run our update command. So again, what's
happening behind the scenes is it's going to
be downloading and installing the latest version
of Angular CLI. And then it's going
to be updating the packages on my application
and changing my code where needed. And so if there's any sort of
migrations, what should happen is, while you're doing
the update process, it's going to report what
migrations it's doing. So you can see Angular
workspace migration. So it made a few changes
to the workspace layout. So you can see it
updated my angular.json file, updated my tsconfig.app. It updated the packages. And so it's making all
of these migrations. Even ones that don't really
have any changes to my app, it's still double-checking
all those things so that we know that
my application's going to keep working. Now, there's a couple
of other places that you can look for
the latest information. You'll notice here at the very,
very bottom of the update, it actually says,
for more information, please see this link. And so we actually have
guides on what changes we're making behind the scenes
with every version of Angular, so that you can know about
things like deprecations, you can know about things like
removals and changes to the way that the APIs work. The other one that I
want to point you out to would be update.angular.io. So behind the scenes
when you ran ng update, we made a lot of
changes to your project. And so if you actually wanted
to see what you need to do, you can just go to
the update guide, and you can say, show
me how to update. And we'll say, oh, make sure
you're on the latest version here. Make sure you're using
this version of Node. It walks you through the changes
that are going to affect you, as a developer. And you can even
tune this, based on the number and
amount of features and the depth and complexity
of your usage of Angular. Because most applications don't
care about all the changes we're making under the hood. But let's say you have
a large application. Maybe you have several
hundred components. You have component libraries. You're using things
like Universal. You can check these
boxes, and what it will do is it
will show you all of the information about the
update, all of the changes we're making behind
the scenes so you can have a full,
complete understanding of what's going on. The other way you can
do it is if you just take a look at the git history. You can now go in and see what
all the changes we made were. So for example, when
we moved to Version 9, we turned on ahead of time
compilation by default. So that's going to make
your build a lot faster. You can see that we've
installed all the dependencies, and not just on Angular. We've also installed things
like rxjs to the latest version. We've updated your components
so that they actually continue working as we
make changes to Angular. And so this is really,
really powerful. And then we can actually do
a test to see if this works. So let's just run an ng serve. And we can say, yes, let's let
Google Analytics track some of our CLI usage anonymously. And what will happen
is, when we return back to the browser window,
we're going to get the latest version of Angular. And our app is generally
just going to keep working. And then the way
that this really affects you is not only keeping
you up to date as a developer, making sure you're
using best practices, but again, it's also going
to improve the performance of your application. One of the things that
you're going to see is that every time we
make an update to Angular, we're trying to look
for ways to make Angular more tree shakable, to
make your build system better. And so there's lots
of experimentation, lots of ideation going on there,
because the state of bundlers in JavaScript are not static. Webpac keeps getting better. Rollup keeps getting better. Terser keeps getting better. And these tools are changing,
and they're evolving, and the way that they relate
to each other is changing. And so what we do is,
as the Angular team, we're trying to stay
on top of that for you. And so let's go
ahead and refresh. And if we take a look
in the dev tools, we should see we are now on
the latest version of Angular-- so 9.1.9 at the writing. But whenever you
use ng update, it's just going to move you
to the latest version. It's going to do
that automatically for you, so that you
are staying up to date, staying fresh, staying fast. And so once you've
updated Angular and you've updated the
CLI by core [INAUDIBLE],, now what I'm going to do is
I'm going to go and update all the other packages. So if you take a look,
for example, we did not, in our package.json. We didn't update the CDK, or we
didn't update Angular Material. And so we're going to
do one more ng update command to update Angular
Material and Angular CDK. You can do this with any
of your dependencies. A lot of dependencies
are starting to support these
automatic migrations. This is what we've been pushing
very hard for in the ecosystem. All right, let's just run that
ng update @angular/material and @angular/cdk command again. And again, it's fetching
the latest version of those packages. It's updating their dependencies
in your package.json. And then it's going to execute
any migrations that you need to be on the latest version. And I think we're going to
try an ng serve one last time, and we see that our entire
application kept on working. And our bundle size should have
gotten a little bit better. And again, it's doing a little
bit of compiling ahead of time. Generally, this is
a temporary thing that you're going to see
with Ivy and with Version 9, is that we do this
extra compilation. That's really to offer the
latest version of Angular and the latest
features of Angular, while still staying compatible
with the rest of the ecosystem. And so this is just extra
compilation stuff the Angular team does to optimize things. All right. As soon as this
compilation is complete, what we're going to
see is we're going to be on the latest
version of Angular. And again, we updated
the package.json, so just all of the
dependencies, including removing things like HammerJS. And our application
should just keep working. Yep, there it is. We have a great dashboard,
just like we had before, right in the beginning. Everything works. Everything animates. We're now in the latest
version of Angular. We're now in the latest
version of Material in the CDK. And our application is
as fast as we can be, because we're budgeting. We're making sure that we're
understanding our application, making sure it doesn't
grow over time. We're analyzing the application
bundle size with source maps. And we're doing things
like lazy loading, so that we only make
users pay for the features that they're using
at the current time. That's going to be it for us. Thank you so much for watching,
and have a wonderful day. [MUSIC PLAYING]