1. Introduction to Angular and its Development Stack
Hello, everyone. My name is Mikhail Gechev. I'm an engineer at the Angular team at Google. Today, I want to share the current state of Angular and what our team at Google has been working on. We provide an ergonomic API for developing components and a command line interface for scaffolding Angular applications. We also have the Angular Components team working on the Component Development Kit (CDK) and UI components based on the material specification. Our integrated development stack is battle-tested across thousands of web applications at Google, ensuring that changes and migrations are smooth and predictable.
Hello, everyone. My name is Mikhail Gechev. I'm an engineer at the Angular team at Google.
On the other side, we also have the Angular Components team. The components team, they're working on the CDK, which is the Component Development Kit. The CDK is providing a foundation for development of UI components. For example, by using this foundation, you can style the minimum amount of components that we're providing there for your own purposes, as well as use the tooling that we're building for accessible Angular applications. The components team is also working on Angular UI components based on the material specification. So if you have an Angular app that is following it, you can directly take these widgets and put them in your app and everything is going to work out of the box.
On top of that, we also have an internalization pipeline. We have a language service, router, animations, and so on and so forth. In general, we're providing this integrated development stack for web user interface. And I believe that the most unique thing about this is that it is really well battle tested across 2,000 and even more web applications across Google. These web applications vary from a small internal dashboard, let's say, to large enterprise applications such as the Google Cloud Console. It has millions of lines of TypeScript and Angular inside of it. We, as engineers at the Angular team, we're not only responsible for implementing bug fixes and new features, like doing fun things, we're also responsible for making sure that all these 2,000 applications are functioning properly with Angular. So if we introduce a change on GitHub that breaks something, we're supposed to go there and fix it. This helps us to make sure that we're aware of all the changes that are happening and making sure that they're not going to have any unpredictable effect on your applications. This way also by making large-scale changes, imagine we change a public API, we need to make sure that it works well in Google Cloud, which has several millions of lines of code. We need to implement an automated migration, which is just a code transformation that we have implemented in a couple of hundreds of lines of code that takes all this Google search code and migrates it to the latest API change.
2. Angular Updates and Motivations
We can make the source code available externally through the ng-update command to keep your project up to date. Angular version 10.0 RC is out, marking another milestone. We release new major versions every six months to maintain a predictable schedule. Upgrading may introduce minor backward incompatible changes and typing issues. We strive for a balance between predictability and flexibility, understanding the trade-off between constraints and adaptability.
We can take this source code and make it available externally, and that's what we do as part of the ng-update command that is going to keep your project up to date across different Angular versions. Not only is it going to update your configuration, but also your source code.
Now, since we are all on the same page, I want to talk more about what we have been up to lately. The good news is that Angular version 10.0 RC is out. Depending on when you're watching this video, maybe version 10.0 is not out yet. You might be considering that this is yet another rewrite of Angular. I hope that with the previous explanation I calmed you up and you're aware that we're not rewriting the framework often. That's mostly because it's not necessary and also we'd have to migrate all these 2000 projects inside. So, that's a lot of work.
Version 10.0 just means that we have achieved yet another milestone. We're in general releasing new major versions of Angular every six months. We do that with several different reasons. First, we want to make sure that we have a predictable release schedule and you're all aware of when exactly the next version is going to come. You know that this version may introduce some minor backward incompatible changes. Of course, we're primarily going to take care of them when you run ng-updates, but imagine we also update the version of the TypeScript compiler. This means that you may have some typing issues that you should take care of yourself. Of course, these typing issues are just going to make your application stricter, and from there, you'll be able to get some hints from the TypeScript compiler and catch errors ahead of time, but still this is maybe something that you'd want additional planning around.
Now, let me spend some time talking about some of our motivations for moving Angular forward. I strongly believe that if you understand the theoretical foundation of all of this, you'll be better aligned with our roadmap for Angular in general. I want to talk about predictability versus flexibility. Obviously, we want to have both, right? We want to have a predictable system which is also very flexible, but this often doesn't work great, because predictable systems, they have some constraints. In order for a system to be predictable, it needs to follow some pre-defined constraints that we know that we can rely on. But, at the same time, if we want a system to be flexible, we should ignore some of these constraints. That's why I'm calling this the predictable versus flexible trade-off. Since I'm quite excited about programming languages in general, usually in computer science folks are referring to this trade-off as static versus dynamic. Probably you have heard about static typing versus dynamic typing. Or strong typing versus weak typing. In this particular case, like strong versus static, these are orthogonal concepts. So let us think about static and dynamic for a second. If we try to place different programming languages that are popular right now onto this axis, we are going to see something like this.
3. Static and Dynamic Systems
Idris, Haskell, and Rust have restrictive typesystems with compile-time guarantees. TypeScript strikes a balance between static and dynamic languages. It's easy to go from static to dynamic but hard to go the other way. Static systems are well-optimizable and enable features like source code visualization. They allow for in-depth static analysis and can be used for reverse engineering applications.
Idris is a very powerful language that has a really restrictive typesystem. We have Haskell with a very restrictive typesystem as well, and Rust as well. Rust has a lot of compile-time guarantees about memory management.
At the same time, though, it could be really hard to rapidly ship a Rust program, because have a compiler that is setting some restrictions on top of you in order to push you to have a predictable system. It needs to set some constraints.
TypeScript is somewhere in the middle. TypeScript is great in general. TypeScript helps us to find the best from both worlds. And we can balance by using different type scripts' strictness flags. For example, if you have strict node checks, we're going to go slightly more on the static side compared to the dynamic.
Another important observation about static versus dynamic is that it's very easy to go from static to dynamic. This means that you should just relax some of the constraints, and your system is going go from predictable to more flexible. However, it's really tough to go from a very dynamic system to a very static system without breaking existing infrastructure.
If we put this into more practical terms, we can think of the static systems as systems which are really well-optimizable at compile time. The compiler can reason about your program much better if it has some metadata about your type annotations. It can just state your program and transform it to a more efficient version of itself. Also, text editors and IDs can take advantage of this feature as well. They can just look at your source code by using their language service and give you really great auto completion suggestions and also even show you inline different type checking errors that you have.
Source code visualization is a very exciting feature. In one of my first ng-conf, I presented a talk called The Mad Science with the Angular Compiler. There, I implemented a compiler which takes your Angular application and compiles it to a virtual reality. You are able to walk inside of this virtual reality with, let's say, Google Cardboard, and you are able to look around and explore your application in the 3D world, having your components being trees with crowns being their templates and so on and so forth. I know that this is a very silly example and not very practical in the real world scenario, but it shows that a static system can help you achieve this. It allows you to perform very in-depth static analysis of your application and do some crazy things.
This applied in the real world scenario for a really useful application could be a system for reverse engineering of an application. You can build a source code visualizer which just shows individual modules in your system, the individual components and their relationship between one another. This is a really important concept especially when you're onboarding new developers because visually we are much easier, it's more convenient for us as humans to reason about systems. On the other side, of course, if you have a static system, this means you need to have a compiler that enforces some guarantees and this compilation takes time.
4. Static vs Dynamic Systems and TypeScript
With dynamic systems, you don't have a build process, but you can easily lazy load components and dynamically assemble UI. Catching bugs early in the development process is ideal. A survey found that about 15% of bugs could have been caught at build time using the TypeScript type system. TypeScript has become more powerful over the years, with version 3.9 offering even more error-catching capabilities. AngularJS was more dynamic and didn't require a build process, but as applications grew more complex, guarantees became necessary.
You have a build process which can, depending on your type system, can take from a couple of minutes to even hours if you have a large project. On the other side, with dynamic systems, you don't have a build process because you don't have anything to be enforced at build time. However, you also have some benefits. You can very easily lazy load components, you can dynamically assemble UI, and so on and so forth.
Now this statement is not something novel that I came up with. In general, there are many people, like hundreds of thousands probably, who have came up with the same conclusion. Of course, it's great if we create programs that work out of the box from the beginning, right? It's perfect! And we all want that. We want to create bug-free programs and ship them to our users immediately. But in real world, things don't usually go this way. We're developers, we're humans, we deal with very complicated systems, so we make mistakes once in a while.
The second-best thing that can happen to you after shipping a system without any bugs and working from the first time, is to catch those bugs very early in the process, before you ship your source code to production. If your compiler tells you about some of the bugs that exist in your program, that's going to be ideal. There is a survey, from quite a few years ago, actually, called To Type or Not To Type. There are researchers from the academia and from Microsoft. They're looking at TypeScript and Flow, and open source projects. When looking at the issue trackers of these open source projects, these researchers are trying to figure out how many of these issues could have been caused by using the TypeScript type system. This way, you would be able to catch this error during your development process, without someone reporting it to you. They figure out that about 15% of these bugs were able to be caused at build time by using type system. See how these predictive systems are quite powerful. We're catching errors ahead of time. And that was many years ago, when TypeScript was still in version 2.0. Now, it is in version 3.9, and the TypeScript type system is much more powerful with so many more constraints that can help us catch errors ahead of time much easier.
5. Angular's Evolution and Version 10
We started with a very static version 2.0 of Angular, but realized it made the build process slower. In version 4.0, we relaxed the compiler restrictions, and with our recent changes in the Angular compiler under Ivy, builds are faster. In version 10, we're enabling an opt-in strict flag and increasing visibility into our decision-making process. Follow blog.angular.io for news. Version 10 also introduces a strict configuration with stricter TypeScript type checking and strict templates. ES5 support is optional, and CommonJS support is disabled by default.
We're building more complicated systems. And in Angular, with this in mind, we started with version 2.0 being very static, with a lot of constraints, with a very strict compiler. That was slapping your hands if you were doing something against its specification. However, we realized that this made your build process slower. And also, we wanted to enable some more dynamic behavior.
So, what we did in version 4.0 is to relax the restrictions of the compiler a little bit. We did the same with our most recent changes in the Angular compiler, under Ivy. Now, Ivy has more local properties that are performing type checking and computation in a slightly different way. We're doing less work, so the builds are faster.
Now, let us peek a little bit into the future. I hope that you have some better understanding of why type systems can help to catch errors and also to introduce some conventions that allow different tools to glue better together. Now, I want to talk a little bit about version 10. In general, the biggest things that we're doing for version 10 are enabling you to have an opt-in strict flag for Angular projects and also a community effort to increase the visibility on how we're making decisions.
Let's talk about the second thing more. Over the past many years, we have been forming and shaping our roadmap just by collecting feedback from different sources such as Stackoverflow, GitHub, different issues there, talking to developers on events like the one today we're going to chat in the forums, I hope soon. Also, talking to third-party customers like enterprises, large banks let's say, talking to internal customers, and so on and so forth. So although we have been doing this and our decisions are entirely driven by the requirements of our users, we don't communicate this well enough. We also don't communicate our roadmap well enough. This is something that we want to improve. So just follow blog.angular.io for news, I hope that we're going to surprise you in a positive way.
Now the next thing that I want to talk about, which is something that I'm quite excited about, is actually the opt-in strict flag. So with version 10, you will be able to create new projects with strict configuration. The strict configuration is going to enable a couple of things. Stricter TypeScript type checking, also strict templates. So we're going to check your templates better, whether they align with certain type system specifications. We're also going to enable ES5 support under an opt-in flag, so by default we will not be shipping ES5 bundles to the end user. If, however, you want to support browsers that are using ES, that do not support ES 2015 yet, you can opt-in into using ES5 by using differential loading. We are also going to disable CommonJS support by default. If you want to opt-in to that, if you have some CommonJS dependencies that you rely on too, you can do it. However, CommonJS modules are very dynamic.
6. Static Optimization and Angular Universal
They do not allow us to perform static optimizations by getting rid of unused libraries. Opting into strict mode catches more production errors. Strict configuration enables automated updates and more accurate migrations. The static nature of Angular optimizes the internalization pipeline. Angular Universal allows easy deployment with zero runtime overhead and efficient startup performance.
They do not allow us to perform static optimizations by getting rid of pieces of these libraries that you are no longer using. The final thing is reduced side effects. If we make some assumptions about your source code that it doesn't make any global side effects like adding global variables, for example, we will be able to tree shake it much more efficiently. We will be able to get rid of the pieces of different libraries, including your own, that you are no longer using.
So, talking about strictness. This means that if you opt-in into the strict mode that we hope that we eventually are going to enable by default for everyone, you are going to get more of these. And this may seem scary. But remember, if you have more view time errors, this means that you are catching more production errors before your source code reaches the final users. These examples of making your configuration stricter enables us to do a lot of things. For example, we can have automated updates, much more accurate ones. ngUpdate will be able to consume so much more type information if you have strict typescript flags and will be able to perform these migrations more accurately. We are also able right now, thanks to the static nature of the Angular ecosystem, to optimize the internalization pipeline.
And finally, we're able to perform much better development experience with tools like Angular Universal because of some static characteristics of Angular. First, let me talk a little bit about the zero overhead internalization pipeline that we have. Now, a lot of folks are asking for very dynamic behavior. Imagine you have a platform where you click a single button and we dynamically swap your language without page reload. This sounds great, but it has quite a few problems. First, for each one of your substrings for your localization, there should be another data binding. It doesn't matter whether you're using Angular's change detection or some reconciliation algorithm in another framework, this is going to add some runtime overhead. Second of all, we will not be able to properly reshape your localization files. If you use only 10% of these strings, we will not be able to efficiently get rid of the rest. That is why in Angular we're taking a slightly different approach. What we're doing is to compile your application once by using the Angular compiler and where you have internalization markers, we're adding some extra information that we can use in order to replace it with a specific substring for the specific localization that you're using. This way we are producing n different builds of your application for the n different languages that you support. And this is with zero runtime overhead and the most efficient way in terms of startup performance. See, this is only possible because of some static constraints, some static processing, some compilation step.
Now finally, I want to share a couple of things about Angular Universal, which are again related to the static behavior. With Angular Universal, very easily right now, you can deploy your application just by using two commands. You can do ng add, angular slash fire, this is going to automatically bootstrap the Angular Universal deployment process, which is only possible, again, because we have some specific convention on how we are treating different packages and how we are running their schematics in order to achieve certain behavior when you add them to your project. Right after that, when you run ng deploy, we're going to deploy your Angular Universal application as a Firebase function and pushing your static assets to a CDN.
7. Deploying Angular Universal Application
We can deploy your Angular Universal application with just two commands by setting constraints and conventions on top of Angular CLI. This allows us to discover routes statically and pre-render them for CDN availability.
So in the most possible and most optimal way, we'll be able to deploy your Angular Universal application with just two commands only because we're setting some constraints and conventions on top of how Angular CLI works. This is also applicable for the Jamstack. For example, in both Angular Universal and in Scali, we're able to discover all the different routes in your application statically without running your application. This way we can later pre-render them and make them available through CDN. Again, this is only possible because of some static assumptions that we have, which are only possible since we're driving currently the Angular CLI structure and making assumptions about your application structure as well.
Updating Angular and Incorporating Web Components
Updating your application to the latest version of Angular is not scary. Just run ng update Angular/CLI and Angular/core. We guarantee better migration steps and runtime/startup performance. Angular's well-integrated platform and static constraints enable a great development experience with two commands: deploying your Angular universal application to the cloud and automatically migrating it with a single command. Feel free to leave feedback at mgv.io and reach out to me at twitter.com. We have been supporting web components and you can use them in your Angular application. You can also build web components using Angular itself and wrap Angular components into web components with the Angular elements package. Both directions are possible.
So if you're left with two things in this presentation, the first one should be, it's not scary to update your application to the latest version of Angular. All you need to do is just run ng update Angular slash CLI and Angular slash core. Please do that. We're guaranteeing that we're going to get better with each next version in terms of both migration steps and also runtime and startup performance.
And second of all, I hope that you realize what forces this brings to us. So notice how just by having a well integrated platform with certain static constraints, we're able to deliver great development experience with two commands, deploy your Angular universal application to the cloud and also provides assumptions about your project in order to be able to automatically migrate it with a single command.
Well really thank you a lot for listening to my talk. If you have any feedback, please leave it at mgv.io. If you have any questions, I would really love to answer them. I really love talking about compilers and static optimizations, so feel free to reach out to me at twitter.com.
Thank you. Thank you for the talk Minko, that was really interesting. And I think in fact so interesting that we didn't get too many questions. We have a couple of them and let's walk through those. But this is just a reminder for everyone watching that if you still want to get your questions in, now is your time and I can still ask them to Minko. So let's start with this one from Albert. Any chance Angular will incorporate web components with or without lit HTML or lit element? Yes. Good question. So we have been supporting web components for a while now. You can take advantage of web components in your Angular application right now if you want to. Additionally we support building web components by using Angular itself. A lot of folks prefer to use the higher level APIs that Angular provides in order to declare your inputs, your outputs, to even use dependency injection if you want to. And this way you can wrap your Angular components into a web component by using the Angular elements package. I hope this answers your question. We have a lot of different initiatives where we're using... Our different projects are using web components under the hood and they're creating Angular wrappers on the other side. So both directions are possible. All right. Well, I hope Albert is very pleased with that answer. Next question is from Ishan.
Updating Projects and Dynamic Translations
When running ngUpdates, all libraries and projects in the Angular CLI workspace will be migrated to the specified version. The new internalization pipeline allows for static translations, optimizing performance and reducing bundle size. However, dynamic translations without refreshing the page are not supported. For those who require dynamic translations, ngxtranslate is recommended. The new internalization pipeline enables loading individual localizations at runtime. Variables in ng-template outlets are strictly typed in the strictest possible mode. As for the future of Angular, it looks promising and we are excited about its potential.
How to update multiple projects with a single command? Yeah. So when you run ngUpdates, this is going to migrate all your libraries and projects from this specific Angular CLI workspace to the version that you have specified. I guess this answers your second question as well. In general, if you have multiple Angular workspaces, you should run ngUpdates multiple times. We're going to migrate automatically your entire application and all the libraries in this workspace to the version that you have specified.
There was a bit of a follow up build there, but that's great. I think you answered that perfectly. From Janice, next question, will dynamically changing translations be supported in the new way thing? Yeah, so we have a... There are some trade-offs of both approaches. So far, the interprentalization, the way that we have implemented it, it's optimized for performance and the limitation that you have is dynamically changing translations without refreshing the page. We think that this trade-off is justified. That's why we're working towards this more static approach, because this drops your bundle size and also has zero runtime overhead. So we don't have any bindings, and your application's going to perform really well. On the other side, we cannot dynamically change translations without refreshing the page. For many customers, many Angular users, many developers, this is not a concern because of the performance benefits. Some prefer to have the dynamic change of translations. If this is critical for you, if you think that the users of your applications are going to be very frequently changing between different translations, and you want to make this as smooth as possible, I'd recommend you to take advantage of the third-party module, ngxtranslate, right now. Something that our new internalization pipeline would allow is to load individual localizations at runtime. This has been some very important feature for different customers who are using Angular, and also in mobile applications with Cordoba or similar hybrid environment. So this is what the new internalization pipeline would allow.
Right. Completely different question from Bram. Will variables in ng-template outlets be strictly typed? I believe so. Yeah, I believe so. The strictest possible mode that we currently support in templates, I believe it already does have strict typing for these as well unless I have missed something. All right. I see some people frantically typing in the Q&A room. So I'll ask you a question of my own. What do you think about the future of Angular? What do you see? What do you see in the future of Angular? Yeah. Thank you for asking this question.
Frameworks' Future and External Contributions
We're considering the future of frameworks in terms of performance, developer ergonomics, and correctness. Progressive hydration is a leading factor in performance. We focus on reducing the threshold from creating a project to shipping it, and on ensuring correctness through type checking and conformance checks. External contributors gain insights and a deeper understanding of the framework, benefiting both their companies and the Angular community.
In general, we're considering. So in general, I'm thinking of the future of frameworks in general in three different axes, three different directions. Performance is one of them. Developer ergonomics and correctness. Regarding performance, web browsers are very closely working with frameworks right now nowadays. For example, the Chrome team is collaborating with us constantly, and I know that they're working with React and checking up with Vue often. In terms of performance, there are many different areas, but progressive hydration is going to be one of the leading parts there. Another thing is that we should rethink what legacy capabilities of the web platform we are using that are dragging us back. For example, in Angular version 8, we dropped ES 5 module support by enabling differential loading.
Developer ergonomics is very important as well, developing an integrated platform that allows you to bootstrap your projects, develop it, and deploy it with a single command. This is something that at least on the Angular team, this has been a really big focus on us. We want to reduce the threshold from creating a new project to shipping it to production, and correctness. I talked a lot about correctness in my talk. I talked about type checking and why this is actually a good thing. Also, there are different conformance checks to make sure that you're staying on the right path, to make sure that you're not loading resources in the wrong order that are going to slow your application down. This is really important to have a bunch of different minting checks. This is something else that we have been working on, and we're also collaborating with Google Chrome on making sure that we don't regress in these terms. So these are three accesses that I think are important.
Interesting. It's something I asked someone before working for Big Corp, and then contributing to an open source project. What do you think makes it different for you to get the support of your company to work on open source and on this project? We have quite a few contributors who are working outside of Google. Usually there are different motivations. The framework is the external company. I'm calling it external but in fact Google is a customer of Angular, just like any other company. So usually the motivation is to have some more internal insights on what is going on next, although we're trying to make everything public and available for everyone. We have much more work to do in this direction to do things right, but although everything is public by still participating in team meetings and contributing actively to the framework, this provides you better insights. So this is a big benefit for some corporations. On the other side, you also have a much deeper understanding of how everything works in the framework. So if anyone from your company needs really in-depth Angular support, you have the experts on site who will be able to debug everything from starting from the runtime of the framework to the compiler, CLI and many other features. I guess these are two of the biggest benefits that folks may get.
Higher Visibility and Monorepo Setup
And another, of course, is with higher visibility. If you're working on a public highly visible project, your company might be able to attract more talent.
Yeah, absolutely. Maybe we can do one last question. What are your thoughts on using NX as a monorepo setup for Angular apps? Sorry, I didn't hear the beginning. What are your thoughts on using NX as a monorepo setup for Angular apps?
Absolutely. OK, thank you so much for that answer. And I think that concludes our Q&A session, but people can still join you in one of the discussion rooms that is opening up next, where you'll be co-hosting that discussion room together with Maxim Solnykov, who is actually one of my close colleagues, so that's nice, and I'll make sure to drop by a bit. There's also other discussion rooms, one on Alpine JS with Caleb, and then on TypeScript with Tejas. And also we have a couple of tickets left over for the workshops on TypeScript, so you can go to live.jsnation.com for those. So I'll let you go, Minko, and join the room, the discussion room, and people can go there and ask you more questions there. Awesome, thanks for the questions here as well. See you later.