Video Summary and Transcription
Minko Gedev presents tradeoffs of deferred loading in Angular and React, addressing misconceptions about the frameworks. Exploring Deferred Loading Nuances and Angular vs. React Implementation with Large Language Models. Beginning with AngularJS, Transition to React, and Contribution to Angular Community. Joining Angular Team at Google, Building React App, Comparing Functionality with Angular. AI Assistance in Angular App, Using Chat Functionality with AI for Actions, Implementing Function Calling for Cart Items. Adding T-shirts to Cart Using AI, Simple Implementation and Tool Addition for AI.generate Call, Visualizing Messages and Adding Products to Cart. Speeding up Application with Lazy Loading in React and Angular, Configuring Chat Functionality. Configuring Chat Data in React, Dependency Observation in Component Tree. Async Function Issue in React, Component Data Dependency, Data Loading in Angular. Inspiration from Amazon for Lazy Loading, React and Angular Implementation, Visibility with IntersectionObservers. Adding Prefetching in Angular and Server-Side Rendering Considerations with Incremental Hydration. React and Angular Trade-offs in Templating and Framework Features. Evaluating JavaScript Frameworks and SEO Impact. Utilizing GenKit API for Function Mapping and React Component Logic Abstraction. Exploring requestIdleCallback in Safari and Signals vs. RxJS in Angular. Considering Framework Selection Criteria Beyond Popularity and Trendiness. Exploring React Features and Angular Templating in TypeScript. Disadvantages of Angular Partial Hydration and Waterfall Effects.
1. Exploring Deferred Loading Tradeoffs
Minko Gedev presents tradeoffs of deferred loading in Angular and React, addressing misconceptions about the frameworks.
My name is Minko Gedev. I'm working on web frameworks at Google, where one of the technologies that I'm responsible for is Angular. And today, in this presentation, I would like to explore the tradeoffs of deferred loading across Angular and React.
First, I know that React Summit is happening tomorrow. I'm just curious, how many of you are using React? Raise your hands. Yeah, I'd say about 80% of people. How many of you are using Angular or other technology? Oh, actually, great. So about maybe 40 to 50% of people.
So I've been in a lot of React circles, either in person or on social media. And often I hear this narrative, Angular is bad. Usually, sometimes even worse words, but, you know, code of conduct. And React is good. Sometimes I hear the opposite as well. Or Angular is hard and React is easy. I'll say usually when you hear that, there is some truth to it. But at the same time, when there is a very strong statement, it's usually a little bit one-sided. It hasn't been, like, holistic over the whole feature set of a framework or different context of execution.
2. Analyzing Frontend Framework Features
Exploring Deferred Loading Nuances and Angular vs. React Implementation with Large Language Models.
So that's why I wanted us to have a little bit more nuanced perspective by looking at only one feature of front end frameworks, which is deferred loading. There are I'll say hundreds of other aspects of a framework that we may want to review in order to make a more informed decision. But deferred loading is something that we can probably cover in the next 20 minutes.
So in the presentation today, we're going to look at an e-commerce application that I have in Angular and I implemented myself in React. We're going to enhance it with large language models. Because why not? I've been loving what large language models can provide to web UI. We're going to use suspense for deferred loading of a particular feature and resource and deferred views, which is the Angular alternative of that. And at the end, we're going to touch on a pattern called incremental hydration.
Just out of curiosity, have you heard about incremental hydration? Would you raise your hand? Okay. Great. For context, I have been involved in Angular in one way or another for about 12 years now. I've been a community contributor. Before that, I was using AngularJS. After that, I joined the team as a contractor. And I've been leading the product roadmap for the past three, four years or so.
3. Reflecting on Technology Choices
Beginning with AngularJS, Transition to React, and Contribution to Angular Community.
It all started for me with this email right here. I just finished my internship and I was wondering what to do. Went to get coffee. And I saw that in my inbox there was this email, a venture capital back start up wanted me to help them build their web UI. And I had to pick a technology for the purpose. I was never really aligned with my core values back then to write testable and maintainable code. So, I picked AngularJS. And I started coding this project. That was literally where I was in my college dorm room in Bulgaria. I was shipping a lot of code for about two months before my finals finished the project. So, overall, it was a success. The startup didn't have market fit, so it failed. But my Angular app worked out.
After that, I talked to the same investors and founders of the startup and I showed them an idea that I had about using virtual machines in the browser. And we turned that into an idea, into a company called Rime.com. And I had to build a front end for this startup, for this product. It was pretty ambitious, I would say, several hundreds of thousands of lines of code. And that was happening a few years later, in 2014, 2015, when my technological choices were AngularJS, React, and Angular. I was AngularJS experienced developer back then. But I also knew that AngularJS was soon going away. Angular at the same time was far from stable, so I knew that if I used Angular, probably I'll have to rewrite my application multiple times until they graduated to stable in version 2. So I ended up picking React.
And I actually loved React. It was just like, I love its solid, theoretical backup model with functional programming. I like the orthogonal design where you have non-overlapping concepts. So I ended up using React. My whole team adopted it. And we built a product that I ended up presenting at ng-conf, an Angular conference. So I felt a little bit like a Trojan horse there. I was contributing to Angular in my spare time.
4. Exploring Web Frameworks
Joining Angular Team at Google, Building React App, Comparing Functionality with Angular.
So I was at this conference, but my product launched with React. Time passed. Coursera ended up acquiring us. And instead of joining Coursera, I ended up joining the Angular team at Google because of my contributions in my spare time. So I have some experience with React, but I'm definitely not a React expert. And I've been using Angular and developing it for the past few years as well.
So for this presentation, we have two apps, one Angular application, e-commerce app. And I built a clone of this application with React in a couple of days with Curser. It was a huge productivity boost for me. This is my first non-trivial React application in about seven years. So I kind of learned a lot of things while doing it as well.
Of course, I'm working on web frameworks. So I use other frameworks just to see what feature set they have. But usually, I'll build a small app, and I'll drill very deep into one particular feature set. This time, I built an application that is closer to a real-world app, still very small, still very basic, but using proper state management, having some acing actions and stuff. Here is what it looks like. You can just explore, like, navigate in different products, add them to your cart. And we have the exact functionality, the exact same functionality for Angular as well.
5. Implementing AI Chat Functionality
AI Assistance in Angular App, Using Chat Functionality with AI for Actions, Implementing Function Calling for Cart Items.
There is also some AI assistance that I wanted to demo right here in the Angular app because it just looks better because someone else who has better sense of design built it instead of me building the React app. So we have the functionality here. And we have this chat where we can talk to Jim and I and ask him about products. And Jim and I would respond with what we have in the store. And I can ask it. Let me just go to the cart first. Angular. We can ask it to perform actions in my application, such as, like, adding items to my cart and checking out.
You're going to see why I have this functionality in a little bit. I wanted to build a slightly more sophisticated chat experience. And it functions pretty similar there. It's pretty simple, actually. What you have is just an async function send message on the client. When we send this message on the server, we process it here. I'm instantiating GenKit model that is backed by Jim and I 2.0 Flash. I'm sending requests to Jim and I and getting a response. And that's it. I'm not even using streaming here, because I wanted to keep it as simple as possible.
The functionality for adding items to the cart is a little bit more interesting. It's something called function calling. Because we can pass a string to Jim and I, and it can return function parameters that we can later on invoke in our system. So what I did with the chat is the client sends a request to the server. In this case, with a prompt, add to Angular t-shirts to my cart. The server forwards this information to Jim and I together with a schema of all the available methods that we have in our application. From there, Jim and I, looking at the schema, it returns the particular action, let's say add to cart, and provides the parameters.
6. Implementing AI with Cart Functionality
Adding T-shirts to Cart Using AI, Simple Implementation and Tool Addition for AI.generate Call, Visualizing Messages and Adding Products to Cart.
In this case, two t-shirts. And the t-shirt is an item with ID, in this case, 123. We call add to cart on the server, and we update the UI as well. That's pretty much how it works. And the functionality has pretty simple implementation as well.
Very much the same features, very much the same code that I showed you, with the difference that we're also adding a tool, which is this adding to cart functionality, which provides a schema. And we provide the tool as part of the AI.generate call. And on the client, we send the message using our async function.
We add this message to the list of messages that we have in the chat so that we can visualize all the different messages in our app. After that, we check whether there is a product that we need to add to the cart, if the user has invoked any particular action. And if there is one, we just add it to the cart. That's pretty much it, pretty simple. Cool, so now we are AI-ready.
7. Optimizing Chat Functionality Loading
Speeding up Application with Lazy Loading in React and Angular, Configuring Chat Functionality.
Now, we can speed this application up. We have our fancy AI functionality, but still, most people are used to using e-commerce stores just by navigating and clicking through the application. So I'll say the vast majority of users would not really use this chatbot, even though we have it. So why do we have to load it as part of the initial application load time? We don't really have to. We can delay it. And we have the same exact functionality in React here.
In order to lazily load this in React, I assume you'll be using suspense, right? First, we use react-lazy so that we can create this lazy component that we can later on load with suspense. We declare this local state in our application with use states, whether the chat box is expanded or not. If it's expanded, we render the suspense boundary. And we show a fallback loading. That's pretty much it. I'll say it is pretty straightforward.
Here is the alternative implementation in Angular. It is entirely in the template. Angular has templates that are adding some extra semantics. We have something called deferrable views, which provides this deferred block, where we're specifying a condition when we want to load something part of the UI. And we provide a placeholder, or a loading indicator. Cool. That was it. I'll say the functionalities here were pretty equivalent, a little bit more imperative, potentially, in React, because we did it with JavaScript. There is also data loading. Now, let's see. We may want to configure our chat in a certain way.
8. Configuring Chat Data and Dependency Observation
Configuring Chat Data in React, Dependency Observation in Component Tree.
We may want to configure our chat in a certain way. Let's say provide the user's name so that we can pass it as part of the prompt, or as part of the URL parameters that we're sending to Gemini later on. So in this chat box right here, we'd like to provide some data.
In React, we can use suspense again. We have our cached promise and the getConfig function that checks if the promise exists, if we have set it to a value. If it is not, no. We return it. Alternatively, we send a request to get the user name, and we assign the promise, returned by fetch, to the data promise. Later on in the chat, we use the hook use so that we can call our getConfig and implement this data suspension.
Another interesting observation here is that this component particularly depends on its data. It is a chat component that we have wrapped in suspense. But it could be also any other transitive child of this component. So if we have a more complicated component tree, the chat consists of many other components, if any of these components, even like a leaf component in the component tree, has some unresolved data, our application will keep loading. It has its own trade-offs.
9. Managing Async Functions and Data Dependencies
Async Function Issue in React, Component Data Dependency, Data Loading in Angular.
I wish you were there with me, then. I spent some time. Luckily, I also was able to ask Jim and I for help. And I found that the problem came from my async. I didn't realize that I'm having an async function that is returning a promise. So my promise is being robbed by another promise. And every time I'm getting a new promise, so because of React's execution model, suspense just doesn't work, since every time I'm getting a different promise and this function gets invoked every time so it can produce the virtual DOM so that React can perform reconciliation. Not too obvious, but you can learn it, right? After some headache.
Another interesting observation here is that this component particularly depends on its own data. And in this case, it is a chat component that we have wrapped in suspense. But it could be also any other transitive child of this component. So if we have a more complicated component tree, the chat consists of many other components, if any of these components, even like a leaf component in the component tree, has some unresolved data, our application will keep loading. So it has its own trade-offs. It's not necessarily good or bad. It's good in some sense that every component has its own data, like directly depends on it. At the same time, it might be sometimes not too trivial to debug. So we would need a little bit more sophisticated debugging tools that show us the components and their dependencies.
Here is how we achieve the same thing in Angular. We create an HTTP resource where we're sending a request over the network, API user. And whenever the resource is loading, we show a loading indicator. Whenever we have loaded the data, we just pass it to the chat. So there are a couple of different differences here. I'll say the main difference is that we have extracted the data loading in the parent component. So the child would always receive the data that it's waiting for. It is a very explicit data flow. Again, not good or bad, just different. It will be easier to debug. I'll say probably easier to reason about. Now let's look at another example. Loading component before below default.
10. Implementing Deferred Loading Functionality
Inspiration from Amazon for Lazy Loading, React and Angular Implementation, Visibility with IntersectionObservers.
So I got the inspiration for this functionality from amazon.com, where there is a section with sponsored products at the very bottom of the page. And I just want to lazily load it because that is below default. Probably I don't have to wait for it. I just don't have to wait for this functionality to get loaded so that I can show the initial set of items at the beginning. I would like to load this functionality and render it whenever the user scrolls to it.
In React, we use a similar approach with suspense. So we have our showRecommended flag, which whenever it is true, we're going to render the suspense boundary. And we're going to render our lazily recommended product. Still pretty straightforward and mostly declarative. The tricky part comes in when do we set the showRecommended to true? There is something related to visibility of the recommended products item. So we probably have to use the browser API, IntersectionObservers. We use effects. We pass an empty array of second arguments because that's what you do, I guess. And we call IntersectionObserver.
Here is how we can manage it to track when this item gets visible. And whenever it gets visible, somewhere right there after the if statement, we set our showRecommended to true. We also need to remember to disconnect the IntersectionObserver so we don't have any memory leaks. And that was the functionality in React. And here is the equivalent in Angular. Pretty much the same thing as the previous example. We have a deferrable view where we're specifying that whenever this component enters the viewport, we'd like to render it. Alternatively, we're showing a spacer. It gets even more complicated when we want to add prefetching.
11. Exploring Prefetching and Server-Side Rendering
Adding Prefetching in Angular and Server-Side Rendering Considerations with Incremental Hydration.
It gets even more complicated when we want to add prefetching. So we have the functionality from before. And if you would like to prefetch this functionality, the recommended products, whenever the browser is idle, let's say, we need to do another use effect with requestIdleCallback and use preloadModule, specifying the path. If we want to do that in Angular, all we need to do is add the prefetch on idle directive. Cool.
So the last part of the presentation, I wanted to touch on server-side rendering. Because if we're building an e-commerce platform, we would likely want to server-side render the app so that we can quickly show the products to the user and increase their engagement rate. Something with server-side rendering is that we send a request to the server. The server renders our application. We receive HTML. The browser parses this HTML. And we start downloading all the associated JavaScript with the page. From there, we execute the JavaScript. And finally, we can handle user interactions, which means that the more JavaScript we have, the larger this gap is.
For longer, we cannot respond to user actions. So what we can do is render part of the page, for example, the sponsor recommendations, but not load the JavaScript associated with it. Because we would like to load it and hydrate this part of the application only when it is in the viewport or when the user engages with it. This technique is called incremental or partial hydration, depending on where you're using it. On the definition, there are no very specific definitions. Everyone is using the term a little bit differently. In order to do that with Angular, we have this called snippets. All we need to do is change the default block, instead of being only on viewport, to be hydrate on viewport. And that's it.
12. Evaluating Templating and Framework Trade-offs
React and Angular Trade-offs in Templating and Framework Features.
I'm sure we can achieve that in React, too. We can also use server components by modifying our entire application. But it's pretty straightforward to do that in Angular.
Now, does that mean that React is bad, and Angular is good? Or React is hard, and Angular is easy? Well, I'll say it's just all about trade-offs. In this presentation, in the last 20 minutes or so, we were able to explore some of the trade-offs of the templating systems, or the kind of composition systems of all frameworks, Angular and React.
We can see that JSX is very minimal. It is easy to learn. And you compose it with JavaScript. You can very quickly become productive with it. Angular templates are very expressive at the same time, because this is a language that the Angular team is maintaining. So we can express very complicated features in a very compact way. Additionally, templates are statically optimizable.
So we have different execution model. We don't really necessarily have to invoke every single component on every render, or use different hacks with memorization. We can just call the component once for initial rendering, from there updates the dynamic parts. Just different trade-offs. And there are many other aspects of a frontend framework that we can look at, such as template authoring, component model and lifecycle, runtime abstraction, language choice, whether it's just pure JavaScript or TypeScript, reactivity. And we only looked at deferred loading today.
Exploring SEO Impact with JavaScript Frameworks
Evaluating JavaScript Frameworks and SEO Impact.
So I guess evaluating a JavaScript framework is way more interesting than the binary, good or bad. It's a multi-dimensional problem, and it's pretty fun, actually. To make a really good solution, like a really good decision for what framework we should be using, we can look at the framework space more holistically and map the individual features to the problems that we're solving.
So I guess my call for action here will be to go and try as many frameworks as you can, and see what works for you best. Thank you. That's all I have for you.
How does suspense work with SEO using server-side rendering? So for example, what you showed with the sponsored items section. Yeah. Yeah. Well, I can comment on deferrable views, because I showed only the equivalent in Angular. That makes sense, yeah. Everything gets rendered, so I guess the bot, the crawler, will be able to see the content and index it. It's not going to have JavaScript, so eventually if there is an action that dynamically pops up, probably the crawler will have to engage with it in order to see what is going on there.
Yeah, I guess there's a sort of like, is there a way to block it being picked up from SEO? Because normally, I think you don't want your sponsored items, for example, to appear in your search results necessarily. Yeah, you can if you want to, yeah. All right, lovely. What else we got? OK. Of course, there's a lot of excitement about the AI side of things. So there was a quick question on Gemini, and how does that Gemini API know what the functions on the server are called? For example, your addItemToCart functionality.
Utilizing GenKit API and React Component Logic
Utilizing GenKit API for Function Mapping and React Component Logic Abstraction.
Yeah. So as part of the tool registration, this is actually I'm using a specific wrapper of the Gemini API by GenKit. There you're specifying all the available functions, which is a very declarative way to specify what are the functions and what are their parameters. So Gemini can map the text to a function and parameters. Yeah, I'm actually quite a fan of GenKit. I don't think many people, and I think enough people know about GenKit yet. It's very cool. Go check out GenKit for doing this kind of stuff. You have to go in and describe those things. Everything in prompting and Gemini and all sorts of Gen AI stuff is about the prompt. So you just tell it you've got these functions, and it works.
I'll ask, this question maybe came in a specific time. No, it just happened just now. Wouldn't it be easy to create a JSX component that abstracts the same logic that you've been talking about? So I guess if you're working in React. Yeah, you can extract the intersection observers logic into whether it's going to be a component or something else. Yeah, you can do that. You still need to write it once. Yeah, that's true. Yeah, it's still not as easy as it just being there.
But what about these four lines? Yeah. But yeah, it doesn't stop you doing it. Yeah, if React is your thing, it's still going to be there. Oops, I said that. Sorry, I'm getting repeats there for some reason. OK, is there any plan to add more route preloading strategies to Angular, like the ngx-quicklink library that apparently you worked on? Yeah, probably not built-in functions that are going to be part of the framework. But you can declare, like, custom ones, the quicklink. I'm still maintaining it, so if you want to use it. There you go. No need to.
Exploring Browser Callbacks and Reactive Paradigms
Exploring requestIdleCallback in Safari and Signals vs. RxJS in Angular.
No need to. Yeah, yeah, nice. And OK, can you explain more about how and when requestIdleCallback is called, and how you would handle it in Safari, specifically? Yeah, so the browser would see when there is available bandwidth for execution. And if it has a couple of spare milliseconds, it's going to invoke the functions that we have scheduled in requestIdleCallback. I don't know if this API is available in Safari specifically. If it's not, probably you can polyfill it in a suboptimal way with, like, some test scheduling. It's a difficult polyfill, isn't it? Yeah. Cool.
OK, this might be a controversial one. I don't know. Are signals going to replace RxJS in Angular? Well, for particular things, we've been wanting to use signals, specifically when you're managing your local component states. RxJS, it's still really convenient when you have a stream of data. And you prefer to use the high-level operators there that they provide. Yeah. I guess maybe what the question is trying to get at is, treating everything as a stream was maybe too much abstraction for things that you don't think about as a stream. Yeah, you're great in reading between the lines. I mean, that's what I've always kind of thought about with any kind of reactive stuff, anyway, is that it's like, everything's a stream. And what if it's not a stream? It's still a stream. Yeah. I see people like that with regular expressions, too. I can solve this problem with regular expressions. Why not? So everything would have. So true. Yes.
Considering Framework Selection Criteria
Considering Framework Selection Criteria Beyond Popularity and Trendiness.
The best advice with regular expressions is try something else first. Yeah. Absolutely.
OK, we still have some questions here in the pending section, which, oh, they're up there. OK, cool. I know, sorry.
Do you think people choose frameworks based on popularity and familiarity rather than their pros and cons? Yeah, I would say that's a very valid point, too. If you are going to pick a framework, you want to pick something that you're going to find people to build your application with, like people with experience. Right, yeah. The concerns are more than just about the code. Yeah. Yes. Yeah, you need people to be able to build it with. Yeah. There is also the maintenance model, whether this product would just disappear if the maintainer burns out or wants to take a break. Yeah. A lot of different things. I think you also called out right at the end of the talk that the important thing is to try a bunch of frameworks. And that way, you're dealing with your own experiences and not just what's got the most stars on GitHub or most downloads on NPM. Yeah, I would say whatever is the most trendy on Twitter or in hacker news, making a decision based on that, I would say, might backfire in the long run. Yeah. Or might be just not the most optimal choice for you. Right. Right, yeah. And not the most optimal is not the worst thing in the world. But you just have to be aware of it. Yeah, yeah. Nice. Oh, OK.
Comparing React and Angular Features
Exploring React Features and Angular Templating in TypeScript.
Oh, OK. Did you enjoy using React after such a long time? And are there any cool features that you discovered in React whilst playing with it that you would want to see back in Angular? Well, they have very different execution models. I'll say I enjoyed the simplicity of the altering experience in React. And there are some other features in React, which there are features in other frameworks, too, like Svelte, for example, where you're directly able to import a component and use it in your template. Why do you need to have multiple different dynamics co-ops to declare? These are some things that we've been considering for a long time. Yeah. Yeah, nice. I suppose, yeah. The Angular team, I guess in general, is looking at other frameworks, what they're doing, in order to learn from them. Yeah. And bring in what's best? Yeah, and some things just make sense. Some decisions we made a very long time ago. And we can revisit them. Yeah, nice. Nice.
OK. How different is this Angular DSL when you're writing in TypeScript? This is specifically a templating format, which compiles to TypeScript. We have a compiler that turns our templates to TypeScript instructions. So no different. If you want to, people can theoretically write this code themselves. But I would not recommend it. Our compiler knows how to optimize the templates. It's a feature that you have. It's one of the reasons you use Angular, is for it to do a lot of work for you. Yeah. Nice.
All right. We've got about a minute left. I'm going to make this the last question for now. Because I also have to set myself up to talk next.
Evaluating Partial Hydration Risks
Disadvantages of Angular Partial Hydration and Waterfall Effects.
Are there any disadvantages to partial hydration in Angular? Is there a visible delay between user action and response, particularly on slow or 3G mobile internet? Yeah. I'm going to add something for five seconds about the previous question. And I'm going to respond to this one. The previous question, also, we're trying to keep our templates be as close to TypeScript as possible so they're easy to use. Yeah, nice. On partial hydration, yeah, you can shoot yourself into food if you have lots of levels of nesting and you have a waterfall. So avoid the waterfalls. Yeah. OK, nice. Right. Well, that is all the time we've got for it. I'd like everybody else to thank Minko again for a wonderful talk. Thank you so much. Yeah. Thank you all.
Comments