Defer and other reasons to try Angular again
with Jessica Janiuk
There’s a whole lot happening in Angular lately. Jessica Janiuk and the rest of the core team have been working hard to add new capabilities & improved APIs. Learn what’s new & why it’s worth a look.
Topics
Resources & Links
- https://jessicajaniuk.com/
- https://angular.dev/
- https://github.com/thePunderWoman
- https://angular.dev/guide/defer#nested-defer-blocks-and-avoiding-cascading-loads
- https://developer.chrome.com/docs/aurora/overview
- https://angular.dev/tutorials/learn-angular/deferrable-views
- https://angular.dev/guide/defer
- https://angular.dev/tools/cli
- https://github.com/MarkTechson/angular-fundamentals-lessons/blob/main/projects/13-deferrable-views/README.md
- https://www.learnwithjason.dev/angular-is-so-back/
- https://www.learnwithjason.dev/reactive-state-management-using-ngrx-and-angular/
Transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone, and welcome to another episode of Learn with Jason! Today on the show we are bringing on Jessica Janiuk. Jessica, how are you doing?
JESSICA: Doing pretty well, how are you?
JASON: I'm doing great. I'm so excited to have you on the show. It's always a pleasure and just utter torture when you come on because we know we're in for just boundless puns.
JESSICA: Yes, yes. I will do my best to make it as bad as possible for you. And painful.
JASON: Good. And I'm especially looking forward to the absolutely terrible influence you're going to have on the audience.
JESSICA: Good, excellent.
JASON: Good.
JESSICA: Pun proliferation, it's part of my job title, I'm pretty sure.
JASON: yeah, we're gonna push toward pun-bounded growth.
JESSICA: Ooo... starting strong. It wasn't even me. Well done. I'm having an influence even on you!
JASON: Oh, no. This is how it starts. This is the beginning of the end. Okay. We got people tuning in from all over the place, hello, everyone, how are you? This is gonna be a lot of fun. And we're starting off with a great question: Why Angular again? And that is a wonderful question. So, we had Mark on the show about two weeks ago. And I think that was the first time that I had talked about Angular since I'd had Brandon Roberts on the show maybe 18 months ago, maybe 2 years ago... so, feels like a lot of Angular. But for the history of this show, I've actually only had Angular on a handful of times. And the reason I'm so excited about Angular, I feel like something special is happening in Angular right now where there is -- there's new energy. There's new ideas. There's collaboration. There's stuff that I wasn't seeing coming out of the Angular team until fairly recently. So, I think Mark plays a big part in that. That's why I wanted Mark on the show. And Jessica, I feel, you have been bringing a lot of new energy and new ideas into the Angular space. And I know that you're doing that with your team. But I feel like when I talk to you about this stuff, you are bringing like a fresh mind to it in a way that feels very, very special. And so, I felt like I couldn't -- I couldn't just have Mark or just have Jessica, I had to talk to both of them. So, Jessica, before I go too much further, let's talk a little bit about you. So, for folks who aren't familiar, can you give us a background on yourself?
JESSICA: No. I'm kidding. Yes, of course. So, my name is Jessica. I have been an engineer for 15 years, I think? I'm madly old at this point. But love this field. I have mostly worked in frontend that whole time. I joined Google a little over 4 years ago and joined the Angular team 3 years ago. And this is actually a place I never thought I would be. I had worked with AngularJS back in the day. Back in like, what? 2014, 2015, 2016, and then started picking up Angular2 at the time. And I remember I went to Google I/O and I saw a couple of speakers who were on the Angular team. And I was just like, man, how cool would it be to work with those two folks? Like they're just power houses. They know everything. What a dream? And never, ever in my life thought I would be here on the Angular team calling those people colleagues. So, yeah. I mostly am self-taught. I actually started my career in video production. And shifted careers shortly after I, you know, started my -- turns out I don't like video producing. Like writing very drab, boring scripts every day. That was not fun. I'm guessing it's more fun when you're doing stuff like in Hollywood. But paid advertising is not great.
JASON: Yeah.
JESSICA: So, yeah, and that's how I ended up here. Now I, you know, work on the Angular team. I'm on the Core Framework Team. And I get to do a lot of really cool stuff with the team. I've got to go round and give talks everywhere. And meet awesome people like you. And get to have fun still doing videos here and there. Case in point.
JASON: Yeah, I was gonna say, I've had the chance to see some of your video production and it's really good. Like very funny, very quality. So, I'm -- I'm not surprised to hear that that's in your background after seeing some of your work.
JESSICA: Thank you, yeah. I enjoy it. And I am -- I feel like I'm in exactly the right place with the Angular team because I get to flex the engineering skills, get to do these like really, you know, difficult challenges. Working on a framework used all over the world and having to make sure it works well for everyone. While also getting to do a lot of public speak which is actually something they enjoy quite a bit. And get to do the video production stuff. So, it's like all of my interests with the exception of the robot building. Which for those of you that don't know, I'm a member of the R2-D2 Builders Club and I build Star Wars robots for fun.
JASON: Yes. And I have had a chance to see this R2-D2 in person and it is astonishing. Like it's life-sized. It works. It's got all the servos and stuff in it so it moves. It's incredible. Yeah. I feel like I saw a picture of it I assumed it would be like this little R2-D2 on the desktop.
JESSICA: Like this one over here?
JASON: Yeah, like that little one. Exactly, exactly. But I -- it is -- I always love talking to people who have very broad bases of experience. Because it -- to me, that varied experience leads to, I guess, more lateral thought about problems. And so, you know, I talked about this at length on a previous stream. If you want to watch that, it's on my Tuesday stream. But I was talking about this idea of like how as an industry we've really focused on specialists. And we really like people to specialize in, you know, find one thing, go as deep as you can on that thing. But the challenge that I've noticed with that, if somebody is a deep specialist and they don't have any outside experience. It can turn them into a bit of a battering ram. They look at a problem, this is what my expertise says. I'm going to solve this using my expertise no matter what the problem is. And the balance of having generalists in a group is that they might not be able to go as deep, but they've seen a broader set of problems and so they can say, I see what you're trying to do, but if we turn the problem like this, we can actually solve it in a much less painful way. It's like, wow. Okay. And so, I wonder, did that experience -- did your previous experience as you were joining the Angular team -- has that come into play like as you're planning the future of Angular? As you're talking about some of these new features and APIs? Do you feel like the generalism in your past is feeding that?
JESSICA: I certainly do. And actually, I think not just on the Angular team. I think that generalism and ability -- like especially the visual -- since I worked in video and have that ability to see things in a more visually creative way, I have found that that has impacted my ability across my whole engineering career. Especially in areas like UX. Because I'm sure you've worked with people who've been very focused on a solution. But they get so caught up in how they have internalized to this solution that they have built the experience around that.
JASON: Yes.
JESSICA: And they aren't thinking about it from how somebody else whose coming into it is going it use it.
JASON: Yeah.
JESSICA: And I found that my background can reparation help me kind of get out of that mentality of thinking about it in that way. So, I'm able to maybe think through a better user experience from the get-go. And I actually think on the Angular team, that also plays into like usable API design. It's maybe not as visual, but it comes from the same place of like, as a developer, is this something that I'm going to want to use myself? And when someone comes in here, is this gonna be too much? Or too little? Or not named well enough? Because we know the most difficult problem in engineering is naming things. So...
JASON: Yeah.
JESSICA: So, yeah. I think -- I think that's where my background has really helped a lot.
JASON: Yeah. And I feel like it shows. You know? I think that the -- there's a freshness that I'm feeling in -- in discussions about Angular. And I think that it's -- it's due to pushing that envelope and rethinking it and saying, you know, just because we have done it this way, does it need to continue to be that way? And, you know, Brandon is in the chat right now, and I think Brandon has been a really good voice for this as well. I see something -- Brandon, I got to get you back on the show. I saw what looked like single file JSX-style Angular components in analog which is super interesting. What happens if we reframe to the single API that other standards are working on. That's super-interesting. I'll talk to Brandon about that later. But with you, I want to talk about Defer. I feel Defer is a big change in --
JESSICA: Angular.
JASON: I had analog locked in my brain. What's happening? So, Defer feels like kind of a big shift. Or a big boon to Angular developers, I guess I should say? How did that come about? Like what's the back story?
JESSICA: So, like Defer is something we've known we've needed something like it for a while. There have been kind of user space-created tools to solve the defer loading problem or lazy loading problem in Angular. And if you were to dig into them, they're actually not intuitive to use at all. They're very confusing. And it's been frustrating to the users because it's the best they have. The only options they have. Like it's been in our backlog of like, yeah, we need to solve this for users. But we weren't really sure exactly the best approach. And let's be honest. Like the Angular team is not huge. Like people probably think, oh, you know, it's Google. So many engineers. You know, it's a big, you know -- must be a huge team. But it's not. You know, there's only like six of us on the Core Framework team. And all of the work we have to do we have to balance across the six people and basically anybody else outside of the Core team that wants to contribute. But it does make it hard for us to make things happen like this that we want to see especially with a lot of other priorities. It took until now for us to have really everything in the right place to make Defer happen. So, and along with this came a new control flow. And as we were kind of working through Defer, we realized the new control flow was a necessary part of how Defers going to work. Because one of the things we originally considered for Defer was like a higher order component kind of approach. Like you see in other frameworks with Suspense and whatnot. But it became kind of clear to us that the answer for us might be to be able to do it as part of a template. Where you can just say, hey! You know, we've got this component and it's got this, you know, HTML in it. What if I just want to deal with a subsection of that? Maybe it's another component. Maybe it's another set of components. Maybe it's, you know, something else. And that's where things kind of started heading in the direction of what we ended up with with Defer. And then from there, we realized well, if we're gonna do this, we also should probably do what we have been talking about with our control flow so that the syntax is the same. Because we didn't want to write something that would then have to be re-written when we decided and what that control flow would look like.
JASON: Right.
JESSICA: And all the churn that would come with that.
JASON: Yeah. And so, you're in an interesting position because Angular is very mature as a framework. And I think that one of its biggest strengths is the fact that it is -- it is a good enterprise bet. Like if you need something that just scales that's gonna work forever, you can pick Angular and you can run with it. Mark talked about this when we had him on the show a couple weeks ago.
JESSICA: Yep.
JASON: That's sort of a core tenant of Angular, build for scale.
JESSICA: As a core tenant, it is always played forward. We don't always go backwards. Yes.
JASON: I just -- my whole brain just shorted out. So, if we look at that as like you have to balance that -- this idea of like lots and lots of people in enterprise teams. And enterprise teams, I think, are a little slower to adapt, a little less willing to take on new changes and new tech because they've got stuff to build. They don't have time to goof around with the latest tech. Like Twitter might make it seem like everything is being rebuilt every five days. But that's not the reality in all companies.
JESSICA: Right.
JASON: As you balance this need, you see things in the future and throughout the community. You're introducing things like Defer, introducing the control flow updates. How are you balancing those decisions as you look at what could the future of Angular be without completely upsetting the apple cart of everybody who relies on Angular now?
JESSICA: The TL;DR is that it's hard. We spend a lot of time thinking about like how can we do this with minimal breaking changes? And part of the philosophy of Angular is that we bring people along with us. We don't just like break them and leave them behind and say, like, tough! You got to fix it yourself. So, like we -- we have these migrations that we write to help that people can just, you know, when they install in the next version they can run it and it's supposed to take your code from the old version and like update it to the new version and have it just work. In, you know, in the ideal situation they don't have to do anything. I mean, in practicality there's usually a little bit people will still have to do. So, what you're talking about, even with Angular, is a very real situation where saying, like, yeah, I would like to get on the latest version of Angular -- or any framework -- can be a really tough sell to a big corporation when, you know, their goal is not getting to the latest version of Angular. Their goal is to sell whatever widgets they're selling so that they can, you know, continue operating as a business and pay everybody in whatever. And while tech debt is a part of every project and eventually we get prioritized, we need to make it easy for people to move forward. So, we do our very best to do that. So, like I said, it's hard.
JASON: Yeah.
JESSICA: And, I mean, I spent three months writing the migration for control flow. So that people can run it and just get switched over to the new version.
JASON: And when you say "Migration," this is something I really do appreciate about the Angular team. You're not just saying like a migration guide. You're saying, I will go in and code mod your codebase so that you don't have to write code.
JESSICA: Yes.
JASON: That's hard. It's time-consuming. But it's such a big deal for I think keeping the trust of the community. Like I don't know, when I'm working with the framework and that framework launches a new feature and it's like, if you want to use this new feature, here's all the things you have to refactor. I'm tired, man. You do this every couple of months. I'm sick of rewriting my codebase. I want to tinker, not deal with the changes in the codebase. The thoughtfulness about API, that matters a lot. It's not just about me now. It's me and my team of five other engineers. It's me and any company with 15 engineering teams and 10 engineers on it. The bigger the teams, the more important this problem is to solve properly. And I think that is something that, you know, the -- working at Google scale I think helps you think through like what does that mean?
JESSICA: Well, and I think knowing the history of Angular, we learned this need the hard way. You know, so --
JASON: I wasn't gonna bring it up.
JESSICA: I mean, it's not like we shy away from talking about that.
JASON: Yeah.
JESSICA: The move and AngularJS to Angular was not a smooth one. It was controversial at the time. And here we are and we're still moving forward. And in that process, we realized how important it is to make sure that we don't break people.
JASON: Yeah.
JESSICA: It also helps that like -- like I think a lot of enterprises turn to Google because -- or to Angular because they know that it's backed by Google and that it's used at Google. And every release that we do has -- is like essentially validated bit fact that it's being tested against a bunch of internal Google projects. So, by the time it hits them, it's pretty well vetted. So, that builds a lot of trust. But yeah. As we think about moving forward and trying to evolve the framework and improve the developer experience and add new cool features like deferrable views, there are the challenges of how do we do this in a way that isn't too hard for people? It doesn't introduce too many concepts at once? That doesn't change the public API such that it's so fast that people can't keep up? That is a big concern that we've had that we're moving a little too fast. So, as opposed to moving a little too slow and people think we're stale. So, that balance in the middle of how you can maintain that is something we think about a lot.
JASON: I do not envy the -- what those meetings must be like. But so, speaking of introducing new concepts, I think I would love to just start seeing this in action.
JESSICA: Yeah.
JASON: I'm really excited to see how this new API works. Let me switch us over into -- let's see... I'm gonna get my screen on here. And then I'm coming over to this view -- not that view. What is that one? Get that one out of here. We want this one. There we go. Okay. So, I'm gonna put this up. And I'm going to remind everyone that this episode, like every episode, is being live captioned. You can see the link to see those captions down at the bottom. I'm still working on figuring out how to get those piped directly in. I'll get it. I'll get it there, I promise. And that is made possible through the support of our sponsors. So, we've got Netlify and Vets Who Code both kicking in to help cover the costs of operating this show. Thank you very much to both. And I'm looking for sponsors. So, if you or your company want to give me some money, I'll take it. Please. We're talking do Jessica today. Here is Jessica's website if you want to go check out -- you can see here. I'm not gonna click on it. I'm gonna make you click on it. Go look at the R2-D2. I'll put the URL up here for anybody not getting the comments posted through. And we're talking about Angular. Angular has a cool new website, Angular.dev.
JESSICA: Yeah, it's a fancy new website as opposed to mine which is really behind. Don't look at the code.
JASON: I like simple. I think simple is underrated.
JESSICA: No, I agree with that.
JASON: Oh, I shouldn't look at how you built it.
JESSICA: Yeah, this is running Angular. But it's running Angular from like 2017. And I can't update it because I think I ejected it from the CLI. There's a whole bunch of reasons why I can't. So, in order to get it updated, I would have it rebuild it. Who has time for that? The problem is it works. The problem is the GitHub link doesn't work. I changed my GitHub username and I haven't been able to redeploy it.
JASON: This is like the classic problem. I'm stuck on an older version of my framework because I did something clever and the migration doesn't work because I did something silly that -- yeah. I feel the pain.
JESSICA: That's exactly it. I think if you want to, you can go click on Connect, and under Connect, that GitHub link probably works.
JASON: There it is.
JESSICA: Is that one works. There grow. That's -- but don't look at that code. Because it's almost 10 years old almost at this point. Or do and feel free to judge me. That's perfectly fine. All right. Yeah. We got this new Angular.dev website. We're really excited about it. It's beautiful. It shows off our brand new branding.
JASON: Which is very nice.
JESSICA: Yes. I am a fan. Except for now none of my -- I can't wear any of the T-shirts I had anymore.
JASON: Another vintage.
JESSICA: Another vintage, yes, yes. But I love that this changes color. Like it's lovely. So, one of the cool things about this website is you can actually go to the tutorials page and actually learn in browser which is something that we've wanted to have available for a long time. And now actually is available. So, and if you're interested in like learning along with us today, you can hop over to that tutorials. Click on "Start coding under learn Angular" in your browser. And up at the top, you can select where it says learn Angular introduction and go down to deferrable views. Which is right here.
JASON: Yeah. So, here we are.
JESSICA: Yes.
JASON: So, I'm ready. Let me make this a little bit bigger. Can everybody see? Why don't I blow this up just a tad? And let's see... if that gets too chaotic, I can make it a bit smaller again. But I think I can make this work. This is nice.
JESSICA: We talk a little bit about --
JASON: Can I just do a little bit of props on the design of this website. Did everybody notice as I resized this browser, I was able to like adjust these panes to make it look the way I wanted to. Instead of like it's blown up and my code is all smooshed. And -- it's little. This is good -- it's just good. Good job on this website, whoever built it. It's nice.
JESSICA: You adjusted those panes with very little pain. All right. Scrolling on. So, the whole concept of deferrable views and Defer is that you are able to put essentially a block within your template using this at Defer. And then everything inside that block --
JASON: Okay.
JESSICA: -- is essentially lazy loaded. It's put into a separate chunk and you are allowed to essentially configure it so that the lazy loading occurs at whatever is your preference for how your users are going to use it. So, we've got a couple of built-in triggers. And we'll go over that in this. The trigger examples are on interaction, which would be something like clicking. Or focusing. On hover. Which is probably fairly obvious, but if you move your mouse over that area or viewport, which is a common, common need. So, once an item enters the viewport it will actually load the content. So, there's a few others. But that's the idea. And yeah. So, let's jump in.
JASON: Let's do it.
JESSICA: So, Andrew Kushner who is the person I worked with most on Defer, and I wrote this tutorial. And we hope it's fun. So, we're gonna start by following our instructions here. It says "Add a defer block around the comments component."
JASON: Okay. So, I just straight up do one of these.
JESSICA: Yep.
JASON: And that's it!
JESSICA: And essentially, that's it. So, the default behavior here is it uses the idle trigger. So, essentially when defer, the request idle callback fires, it triggers the loading of the comments. It's the same thing as if you put in parentheses right after defer on idle. It's the same exact thing.
JASON: Okay.
JESSICA: So, but that is the default behavior. So, from here I think we can keep scrolling down. The defer blocks themselves have quite a bit more to them. So, we actually built in some things like placeholders. Like what do you want to show when this stuff hasn't loaded yet?
JASON: And this is -- feels a lot like how in other frameworks you would have like an is loading kind of boolean and then you would say if it's loading then you show this. Otherwise show the comments or, you know, you end up with some -- you have to build your own control flow to decide --
JESSICA: Yes.
JASON: -- what piece of logic -- or what piece of UI to show. I do like -- this is kind of nice that it has what is effectively feels like an if else to me. But you're abstracting all this logic way. I don't have to figure out, did it load or error, or whatever. I imagine you probably have that handled here for me.
JESSICA: Exactly. With that in mind, we can add a loading block too. That's our next step.
JASON: Great. All right. We've got a loading block. And that goes right down here. Of course it does. Managed to hit buttons that I shouldn't have hit. But that's okay. We're gonna work. So, we'll say loading. All right.
JESSICA: Awesome.
JASON: And then I reload. And it's so fast.
JESSICA: Your idle is so fast.
JASON: Yeah.
JESSICA: We'll get to that. There's a couple other cool things that we added. So, in the case -- there are many times I'm sure you've encountered this where you've got something that like an animation is triggering and happens so fast that you get a flicker instead of -- you don't want it to show if it's that fast. Or make sure it shows at least for a certain amount of time so it doesn't flicker.
JASON: Right.
JESSICA: So, we added the ability to add parameters for this with these placeholders and the loading. So, you have a loading show for a minimum certain amount of time. And loading also has "After." So, the animation flicker, yes. Yes. So, you can add those. So, like to the loading here, the thing is to say, put a minimum of 2 seconds.
JASON: Oh, and then so --
JESSICA: Or adjust for 2 seconds.
JASON: And there are points where I feel like somebody out there screamed at their computer, why would you do that? Why would you make it slower? I actually think it makes the site feel faster if it's intentional. If I look at 1 second of loading versus a flicker, flicker, flicker and be then there's something on screen, it creates this feeling of like solidness in an app. Where it, you know, it's intentionally designed and you be from like view to view to view in a way that it's like the developer clearly thought this through and this feels good, right? I love that you didn't just do after. I like that you can set a minimum. Because I feel like that can create some really good experiences.
JESSICA: Yeah. We thought so too. And like we're definitely thinking about layout shift with this too. Where if you have that weird flicker, you can see content just shifting around. And if it's going too fast, that's just not great. So, being able to configure this in a way such that -- yeah. You don't -- you can control that layout shift to happen at the times that you want it to give the user the best possible user experience in this situation. So, yeah. So, you can also do the after and the after setting is essentially don't start showing this until -- I think you have to put a semicolon.
JASON: Semicolon.
JESSICA: This one --
JASON: This one should not show.
JESSICA: Yeah, it should not show. In this case, it will not show the loading unless it took longer than 1 second. So, don't show loading until after 1 second. And if it loads before that 1 second, it doesn't show it at all. That's essentially the way that configuration works. Placeholder also has a minimum. But placeholder, of course, is not the same as the loading. It doesn't have to wait -- you don't have to worry about waiting for the placeholder because that content is your default content like that shows before the stuff is loaded. So, there's no reason to have an after for that. You just have the minimum for place holder.
JASON: Gotcha. There was a question from LindaKat, does the order matter after the defer? Can you do loading and then placeholder?
JESSICA: It doesn't matter. You can put whichever ones you want in whichever order.
JASON: So, we can pull this one out, drop it right up here and if works exactly the same.
JESSICA: Uh-huh.
JASON: Great.
JESSICA: There is also an error block. So, @error. So, if for some reason you have an issue with your server and let's say you have a component in there that that component is set up wrong or your server dies while you're doing something and it fails to come back, you'll get that error block.
JASON: Gotcha.
JESSICA: At the moment I don't believe we have access to the error. But I believe it's being captured in like logs. So, it just won't show up in your console. You won't be able to like take the error E and do something with the output. So, that's something we've talked about adding in until later. But we have not done that. So, that's essentially the basic structure of how Defer works. So, we got this. But there is one more we can do. So, why don't we... I think there's a next page?
JASON: Yeah. Oh, wait, we missed a --
JESSICA: There's more here. Okay. So, we're going to change the defer block to use one of the triggers.
JASON: Okay.
JESSICA: So... and this is --
JASON: Okay.
JESSICA: -- an incredibly common need, right? That the viewport is like you've got a heavy component. You don't -- it's below the fold. You don't really want to worry about people having to, you know, keep that in your view -- you don't want to have it in your main bundle. You want to defer it to later. So, yes, that is how this is intended to work.
JASON: So, we've pushed the comments down, now when I scroll down, they're already there. So, fast.
JESSICA: Yes. We may need to -- I think we have add content here... scroll down a little bit. Because I know we wrote something to work in a certain way. We even gave you content that you could copy and paste.
JASON: Look at that! That would have been nice for me to actually scroll down and copy and used.
JESSICA: If you read that content, it is definitely honest content and stuff that is important that you should think about.
JASON: Let's do it. Let's see... this is great. So, what I'm going to do is I'm going to actually change the minimum thing so we can see... I'm gonna take this out and leave this on so that we can see when we get to this view that it's actually loading once we get down. Because my guess is, I'm making an educated guess here that you're being a little bit optimistic. You're not starting it when it enters the viewport, you're starting it right before it enters the viewport, it looked like it was here before I got to it.
JESSICA: I think there's a little bit of pixel padding at the top, yes
JASON: See that? There it is.
JESSICA: There it goes.
JASON: Because that was loading so fast, if we could tell that comments to, you know, do a set time out of 500 millisecond we could -- I guess we can. Here's the code. Neat!
JESSICA: Yeah.
JASON: We could if we wanted to add a time out. I'm probably not gonna do that because that would derail us. But that's in action, once this reloads. It didn't reload because I didn't change enough. What if I do this? There you go. Yeah. And as soon as it's in view, it loads. Great! That's really intuitive. That feels -- that feels nice. Like this makes sense to me and I don't write Angular day-to-day. I don't feel like I would need to dive into your API docs next time. I could just do this.
JESSICA: That's awesome. That's part of the goal of what we were aiming for. What's cool is this isn't even where it ends.
JASON: All right, all right.
JESSICA: So, this is where our little tutorial ends. But there's actually -- so, like those are -- the built-in triggers we talked about. So, we've got the on Viewport, we have on interaction, on timer, on hover.
JASON: Can we look at on Interaction? That's really interesting.
JESSICA: Sure.
JASON: If I write on Interaction. It says future comments here and I clicked on it and it loaded the comments. Ooo... I like that. I thought you were going to tell me now I got to create a button and do this whole thing.
JESSICA: Nope.
JASON: And click to view comments. And change this to a button, why not?
JESSICA: Sure.
JASON: And now it's actually -- you got a button, you click the button, the button does stuff, I didn't have to write any logic. That's pretty dang cool.
JESSICA: Right? I think it's awesome. So, yeah, we've got interaction. And that also works with focus. So, it's a set of -- we didn't use on Click because --
JASON: Oh, I see what you mean. On Interaction.
JESSICA: Yeah. On Interaction, like if you were to tab to it.
JASON: There it goes. I think it was on focus leave, it just did it.
JESSICA: Yeah. So, it should be a set of events that triggers the whatever interaction is. We based it off of -- I think we looked at past row and then we looked at some internal stuff for what people are currently using for their interaction-based triggers. So, the things that we can do also is configure pre-fetching.
JASON: I like that.
JESSICA: So, at the top of where you have on interaction, you can actually put a semicolon and go: Prefetch on -- and then give it a different trigger. So, like you would say idle. Prefetch on idle.
JASON: Oh... so, now...
JESSICA: Now when you interact with it, it doesn't actually have to fetch the code, it's already here.
JASON: And note: We have our minimum on here. So, if I come in here and -- let's do this. Let's make it a little bit longer. And two, three -- oh, it was actually so fast that it didn't even do it. Or actually, is it gonna skip around the loading because it doesn't need the -- the loading screen anymore? If it's prefetched?
JESSICA: I think because you have minimum, it likely will skip around loading. So, if you did not have minimum there, it would skip right to it.
JASON: Well, I think -- let me check. I'm gonna make this even longer. Let's make this 10 seconds. And now we've got our thing. I think and because we're prefetching, because it's loaded, it skips right over loading. That's great! That's really cool, actually.
JESSICA: Yeah. So, there's no need for it because the content already exists, that's right. So, yeah. We think that's great. You can actually also do custom conditions. So, we have this on interaction, you can also say "When," and then truthy value.
JASON: Oh...
JESSICA: So, if you are wanting to make this conditional based on something that you have written yourself...
JASON: All right. Let me do something like this. Input type, check box. And we'll give it a name of, like, all right, this is where I'm gonna need help with Angular stuff. But show comments. And we'll do ID of show. And then out here I'll give it a label for show. And it's gonna say show comments. And I think this makes sense. Like this is a interaction that I would create in an app that I built. I'm just gonna put a little paragraph tag around this so that it's... in two lines. Okay. So, we've got a box. When I check this box, I would like to update some value. So, basically, what I would like to do in pseudocode is when show comments is checked -- I don't know how to do that in Angular.
JESSICA: And I'm trying to remember how to do it with a check box input. So, you're gonna have to do a binding on the input.
JASON: Okay.
JESSICA: What we can do is if you scroll down to the actual component. Where it says app component, we can actually create a variable in here that will hold that value.
JASON: Okay.
JESSICA: Yep. And I wonder if we want to make it a signal?
JASON: What did I -- I did something wrong. Do I have to just -- like that? Nope. That's not it.
JESSICA: No. What is it saying?
JASON: Busy -- it says... unexpected --
JESSICA: Get rid of the led.
JASON: Oh, now it's fine. I think it just got out of sync. Okay.
JESSICA: So, here's what I think you'll want to do. I think we want to create our value here as a signal. So, I think we have to import -- I don't use Signals very often because I don't write Angular code very often. I write Angular framework.
JASON: Here I am putting you right on the spot.
JESSICA: Yes. Let's see... where do we import? I think the import signal is from Core. Let's see... signal -- yeah. So, if you go to the top line where it says "Import component," you can just type "Signal."
JASON: Capital?
JESSICA: I don't think you need it to be capital, just regular signal.
JASON: Okay.
JESSICA: And then scroll down and then equals -- let's see... is it new signal? I can't remember. Let me double check so I get it right. Where do we have that? I think you can just say "Signal."
JASON: Like that?
JESSICA: Yes.
JASON: What do you -- yeah, yeah, I gave you one. Leave me alone.
JESSICA: I think that's how it works.
JASON: Okay.
JESSICA: And then if grow back up to your check box... we're gonna need to bind like click to this. So, I think that's --
JASON: Okay.
JESSICA: Parens, click.
JASON: Parens, click.
JESSICA: And then equals and then in here I think you'd want to say "Show comments is equal --" I don't know if we can do this syntax, but do like not show comments. So, invert it. Oh, right. Because it's signal, we actually have to set the signal value. That's right. So, we need to set it to be a writable signal. So, we need to import writable signal. That's right. And it does need to be caps.
JASON: Okay.
JESSICA: And then we'd swap the signal with writable signal.
JASON: And is... writable... writable -- whoa. I can't spell. Writable... signal. No? What doesn't it like?
JESSICA: Yeah, what doesn't it like?
JASON: Only refers to a type.
JESSICA: Let's see... again... I don't -- yeah, I don't write...
JASON: This says signal is a writable signal. So, if I add checkbox in my input, you can access it -- access the value like checkbox.checked.
JESSICA: Give me a second... yeah. And that's essentially what we're trying to do.
JASON: Okay.
JESSICA: All right. Yes.
JASON: Like that?
JESSICA: I was right with signal just being...
JASON: Signal just being single. Signal.
JESSICA: Yes.
JASON: Okay.
JESSICA: And the thing that we need to do is actually do the signal name.set, and then the value name we're setting it to.
JASON: .set. Okay. And then show comments. And is it -- is --
JESSICA: You don't need the equals in not show comments anymore.
JASON: Okay. I got it, got it. Okay. Oh, wait, now I need to actually set it to do this. So, when... show comments. Can I do that?
JESSICA: You would want to do -- that might work. That might work. See what happens when you click -- except for that it's showing comments.
JASON: Yeah, loaded them --
JESSICA: So, that's saying that's grabbing the actual value. Value on the signal and value is equal to true. No, you call like a function.
JASON: Call like a function.
JESSICA: Yeah. It's a -- yes. Yes. But it did not set...
JASON: It did not fit needs brackets --
JESSICA: I think you --
JASON: What needs brackets?
JESSICA: I think when we're doing show comments.set, the not show comments needs to be in parens. The show comments parens because we want to set it to the non-value.
JASON: Oh, there we go! Look at us.
JESSICA: Yeah.
JASON: And it looks like that's okay --
JESSICA: Yeah, it doesn't unload it. That's a one time.
JASON: That's pretty cool. This is great. I think these are the sort of interactions that, you know, this is the stuff we have to build all the time. And being able to, you know, hide away an expensive operation like loading potentially hundreds or thousands of comments on a big enough -- on a big enough article, like that's -- that's a big deal.
JESSICA: It is, yeah.
JASON: And having it --
JESSICA: And what --
JASON: And honestly, the hardest part was remembering the syntax, but this is really straightforward.
JESSICA: And we love it. Like we love it. So, and added to this, you can actually set -- like you can put these together. So, you have when show comment, you could also edit on, you could have prefetch on, multiple, all on one defer block so you can fully customize it. So, like let's say your custom condition is, I don't know, something further up the page. Or someone interacts with it. So, that way you make sure you capture that event appropriately for that particular situation.
JASON: Let's do that. I like that. So, if I come in here. I have a checkbox way up at the top. This one will show my comments. But if I -- if I don't do that, and I... reload this. And I come down. I do want this to still work. So, I can just stack these.
JESSICA: Yeah, you can just put the on interaction back in there.
JASON: And now this is unchecked. I come down here, I click, and there we go. That's slick.
JESSICA: We love it. Now, there's a few caveats to be aware of. And that is -- so, if you're --
JASON: Look what you've done. Look!
JESSICA: Thank you, Brandon, thank you. No, no, you can stay here. The door is open. You can stay here.
JASON: Oh, jeez.
JESSICA: welcome in my house any time. So, we have these things called standalone components, and we have these things called NgModules. And, hey! It's Mark! Good to see you, Mark. So, with modules, there's limitations on how these -- this defer works.
JASON: Okay.
JESSICA: If you try to use a component that is from a module as the deferred thing., so if comments here was inside an NgModule, it would not actually defer.
JASON: Okay.
JESSICA: So, it needs to be a standalone component. Or it needs to be -- like if it's gonna be something that isn't in a module, it needs to be a transitive dependency. You have your comments, component, standalone. It inside there has to have a bunch of dependencies, has to be in modules. That's fine. Just got to make sure that root thing that you're trying to defer is a standalone component.
JASON: Got it.
JESSICA: That is unfortunately, we were trying to make it work for both. But there's some indirection with the ng modules of knowing the dependencies and it makes it really difficult for us to resolve them.
JASON: Okay.
JESSICA: In a way that isn't already eagerly loaded.
JASON: Is there a -- like a best practice for somebody writing Angular. Is the guidance to use the standalone components now? And like to start moving away from modules? Like don't create new modules or something?
JESSICA: Modules will be around.
JASON: Sure.
JESSICA: People will still use them and there's purposes for them. But we recommend standalone. And I think standalone is the default generation for Angular CLI. It used to create modules, but now new are standalone by default. We encourage everyone to do everything with standalone components. But with that said, if you have a library you're using, sometimes people still want to use modules for that. And we don't plan to remove standalone modules. They'll be around.
JASON: They'll work forever, but they're not necessarily like what you should start with today.
JESSICA: Yes. That's a good way of putting it. It's definitely not what you should start with today.
JASON: Got it, got it. That's great. I like that. And so, if you find yourself in a situation where you are trying to defer some code that's built in an ng module, you can just wrap that with a standalone component to get the --
JESSICA: Yes.
JASON: Deferral. Okay. Perfect.
JESSICA: Yes.
JASON: Caveat, but easy work around, that's good news. And we don't break backward compatibility ever. That's very nice.
JESSICA: Yes.
JASON: I hope you're proud of yourself, Mark is in here doing puns in the chat too.
JESSICA: Like I mean, got say that before I joined the team, there just weren't any puns. And now that I'm on the team... everybody's doing it.
JASON: Yeah.
JESSICA: So, I'm gonna take responsibility for that and I'm not ashamed. So, a couple other things is that people want to be curious. Like what's eagerly loaded and what's deferred given the different blocks. So, there's the @defer section, there's the place holder and the loading and the error in your defer block. The deferred content is just the stuff that's in the top main defer block. The loading block, the placeholder block with the error block, those are eagerly loaded. So, that might seem obvious to some people, but it's good to be clear about it. Like that -- if you have these really heavy loading and placeholder components, you know, it kind of defeats the purpose of defer loading your content. So, just think about --
JASON: So, keep these ones as lightweight as you can because they're going to be loaded no matter what.
JESSICA: Or if they are heavier, try to load them early on in your application because then they're loaded and you don't have to worry about future loading of that content. But yeah. It's just good to note that about how this works.
JASON: Got it.
JESSICA: And it's also worth noting that this isn't the end of defer as far as improvements we're looking at. So, we're definitely thinking about using this as kind of a foundation to build other things on top of.
JASON: I just thought of like -- you know on the D&D alignment charts, there's chaotic good, chaotic evil, that kind of stuff.
JESSICA: Yes.
JASON: I like to think of myself as chaotic good, but this idea I just had I think is chaotic evil. What happens if I start nesting defer blocks? As an example, in here I am deferring comments. But let's say I've got a loading spinner. But inside this I have a loading component then. And inside that loading component, I start deferring things in there. What happens? Like is that just gonna work? And if I've got my loading component inside of the defer block, it will be deferred but it could do like loading, loading, loading, and then my final thing? Or like what -- yeah. What's the below gonna be?
JESSICA: You can do that.
JASON: Should I do that?
JESSICA: It will work. So, you know, it's best to avoid the cascade effect because what people could potentially do is they could use the on immediate trigger. Which on immediate is intended to essentially be like, this isn't in your main bundle, but I want it to load right away. So, essentially your page renders and it starts fetching. That's how on immediate works. If you were to put a defer block on immediate, and you have code that has another defer and another on immediate. You get this weird cascading effect. The first on immediate finishes loading and the second one appears and finishes loading and the third one appears. So, we advise not doing that. And we do have some things -- we have like a -- the equivalent of a lint rule or a diagnostic --
JASON: Oh, good.
JESSICA: That will catch it if you do it in the same template. But we can't catch it if it's in a separate component.
JASON: Sure.
JESSICA: So, like, yeah. There's -- I think we actually have it in the deferred guide. There's the reference in the docs section for it. We have a -- I think it's under docs, might be under reference. I can't remember how we have this all -- yeah, I think it's under -- go -- deferrable views. That top one I think is what you want. Not that one.
JASON: Not that one.
JESSICA: That one will work because this is all the same page.
JASON: Oh, got it.
JESSICA: So, on here, on this page, we have some things about like patterns to avoid. But this is pretty fleshed out as far as how all of this works. So, it should be really helpful. Yeah. Nested defer blocks and avoiding cascading loads. That's exactly -- that's exactly the thing to avoid. And like the Aurora team has worked with us and they are on the Chrome side. And deal with all the Core web vitals and whatnot. And they have also made strong recommendations of like, you know, don't -- try not to affect your CLS with where you're putting these defer blocks.
JASON: Is this the right thing to link to for Aurora?
JESSICA: Yeah. That is the Aurora team's page.
JASON: Yeah. We'll start here. Yeah. So, this is just for anybody who has never heard that name before. Aurora is -- what?
JESSICA: Aurora, you know, I don't know that I know their exact definition. But they're a team that is part of the Chrome team and they interface with a lot of outward-facing projects. They're kind of like a -- I don't know. I don't know how you would describe them. Liaisons, possibly? And they work --
JASON: Their focus is like helping everybody make the web more performant, right?
JESSICA: Yes.
JASON: That's sort of the overarching mission?
JESSICA: Yes. And that's across frameworks. They work with the React team, Vue team, Solid. They have connections to all the teams, they work with us. They are very much focused on improving web vitals and makes the web good for everyone. They were calling out, like, yeah, you probably don't want it to be like your main content that you're deferring on your page. So, like that like, you know, the thing that Core Web Vitals is gonna look at is like, you know, your main content. That would probably cause your -- your Core Web Vitals to drop in that case and take a hit to your layout shift as well. So, yeah. Avoid those. On content that would be loaded during the initial render of the page that's in the viewport. Because that's going to be a negative impact on your Core Web Vitals.
JASON: Got it, got it. Very cool. So, all right. Chat, we've got a little bit of time left. Now is your time if you have specific questions, if you want to see specific patterns, start dropping those questions now. Jessica, is there anything else that we should look at in this API? Any other features that we should dig into to make sure that people get the full picture?
JESSICA: I mean, this is basically how -- how Defer works and all the features of it. We can talk a little bit about kind of maybe directions we're thinking of going.
JASON: Oh, I like that.
JESSICA: So, if you are doing server side rendering right now, these will hydrate after they finish loading. So, you don't have to do anything special there. One of the things that we are currently investigating is essentially progressive hydration using Defer as kind of the backend. Or the foundation for that. So, we're kind of exploring how you would define how the content would render on the server. For example, maybe on the server, since everything is faster on the server, you actually want the main content to render on the server side. But not have that component fetched and have the actual component fetched as it deferred. You know, like defer loaded. So, the comments block, the comments would be rendered on the server side. And then you would get that content on the client side, but you would still have it deferred loaded. So, when you started interacting with it, then that actual content would fetch. So, you would have dehydrated content on the page.
JASON: Oh...
JESSICA: So, the cool thing about that is that there would be no concerns about layout shift. Because your placeholder is your content.
JASON: Right. That's a -- that also -- I really like that strategy for a lot of content because I think -- I think that as an industry we've trended a little toward like -- we got worried about stale content. Everybody was all static all the time, right? And so, I think there's been a bit of an overcorrection where we're now, now we're all servers all the time. It feels like we're putting a lot of work on to the computers that we don't need. Especially for stuff that isn't mission critical. If I'm showing a comments section. If I'm showing some supplemental information on the page, I don't really need to load all of it. I can show the state from a few minutes ago. And that's okay. I don't need to like fresh render that every time, we don't need to do that data load. And having this ability to display that on the page with, I don't know, a little note that says, there's five new comments. You want to to show them? And then it loads the new stuff. I don't have to load that data, do that work, put that load on my user's computer, really, I feel like that's respectful design, right? We should do as little as we need to, to get somebody the information they asked for and then be thoughtful about the UX to let them get the things they might want when they actually want them or when they actually request them.
JESSICA: Right. I think that's a driving factor behind Defer in the first place. We defer to our users.
JASON: I like it. I like it. That's a respectful pun.
JESSICA: Thank you.
JASON: So, this might not be a question that you want to take. So, please feel free to defer this question, ha, ha. Should people be looking at using signals instead of RxJS? Or when would you draw that line, I guess?
JESSICA: So, yes and no. It depends on what you're doing. For the average thing, like what we did here, where we're just interacting with an input or whatever, signals are perfect for that. observables and RxJS are really for your complex data and especially data that needs to be updated. Like in the -- like streaming data kind of situations. Because that's what observables are for, really. Observables are pretty heavy for the average need of what somebody's doing on their Angular app. Or any app, really. And by default, we think signals is the right approach for most things that we're doing here. Like right now we're working on how signals can be used as part of inputs. And there is -- signals is a big foundational element of our system now. And we think it's much easier to write. It's much easier to follow. And if you can remember the syntax, like clearly I did when we were working on this. But yeah. Use signals and then use RxJS when it's appropriate is essentially the answer here.
JASON: And the when is it appropriate is always the $10 million question.
JESSICA: Yes. Yes.
JASON: Yeah. But that's our job as developers is to determine where the tradeoffs start to lean one way or the other. And, you know, it -- my gut is almost always like, lean simpler. Because we think -- we think we're gonna build something highly complex. But in reality, usually what we're doing is not that wild. It's, you know, two or three things moving on a page at a time. And, yeah, I didn't need to bring in 45 kilobytes of JavaScript to update these for pieces of text. Probably wasn't really the right idea there.
JESSICA: Exactly. I tend to --
JASON: And by the way, 45 kilobytes is something I pulled out of the air. I have no idea what these weigh. How dare you! RxJS is not that big. I have no idea how big RxJS is.
JESSICA: Yeah, I tend to lean leaner too. Yeah.
JASON: Just... just... just... god.
JESSICA: Especially when rendering. I prefer it leaner than, you know, fattier. Just tastes better.
JASON: I do appreciate a cooking pun. Brandon says to defer those kilobytes, correct, correct. Rafael is asking, is 2024 Angular's year to propel? What are the plans this year? Do you have anything big in store?
JESSICA: Well, we don't actually have a store. That would be really cool if we did. People could get their new Angular merch in there.
JASON: I need a new Angular hat.
JESSICA: That's something I would love to see us do. We have official Angular merch and all the profits would go to helping some underserved community learn how to code or something like that. I would love to see something like that.
JASON: I do like that.
JESSICA: I mean, we've got a lot of underlying things related to like signals as inputs. That's a huge thing that's coming soon. A lot of people are really interested in that. Zones has been something that we've wanted to get closer and closer to being an opt in sort of thing and not required for those who are not familiar, zone.js is the thing that kind of powers change detection in Angular. And Signals is our slowly maneuvering to be able to not need zone.js anymore so we can do more granular change detection.
JASON: I was told, though, that I should aim to be in the zone.
JESSICA: I mean, you should definitely get into the zone. Wait... that's the -- that's the Autozone, isn't it?
JASON: Chat was right with you on that one.
JESSICA: As long as they're not zoning out.
JASON: I mean, maybe we are zoning out. We're looking for the signal in the noise here.
JESSICA: We are, we are. Signal-to-noise ratio is -- yeah.
JASON: Sorry, were we talking about something important?
JESSICA: So, yeah. We're trying to move towards a more zoneless future. That's something we're interested in. It's gonna be a much more performant approach. We're eager to get there. Signals is a change detection driver. We're looking at obviously I mentioned earlier, progressive/partial hydration is on our roadmap. We're looking at server side rendering and our overall experience there. Which is something we're already focusing on, but we're continuing to try to focus on to improve that experience. And I think there's probably going to be a bit about authoring format. And how Signals impacts that so that we can continue to -- our focus is really like fast at the start. And then also, like, just continuing to improve that developer experience. So --
JASON: Yeah, interesting. I'm really interested to see how this plays out. Got another question from Linda. Did Signals start with Angular? Or is that name/idea from somewhere else and this is Angular's implementation?
JESSICA: That's a great question. Signals did not start with Angular, it actually started with Batman. [Mic drop!] No, it didn't start with Angular. I think Preact is where it began? Maybe even started before that. But it's been kind of a trend in -- and there is work being done to make it more of like a standard. And that's happening across frameworks. There's a working group that's kind of discussing Signals as something that would be a very good -- I mean, it is a very simple concept in theory as far as like what a Signal actually is. And so, it would make a very good underlying web standard. So, Angular has its own implementation internally. It is a shared implementation that's used not just in Angular, but it's used in other parts of Google by other frameworks as well. So, it has a lot of investment. But there are other Signals libraries. And I know that Solid has one. And we've spent time collaborating with Ryan on our own implementation. Like he was a collaborator on us kind of coming up with the way our library works. So, yeah.
JASON: Yeah, yeah. No, I think that's -- I mean, I feel like Signals have sort of taken the hearts and minds of developers recently and I think it's -- for good reason, right? Like we've felt a lot of pain around state management. And I think that part of that was because, you know, we -- we learned about observables, but a lot of us never got our head around them entirely. I was one of those. And then we saw the other ways that people were managing state and it felt very -- it's tough when you start trying to think of the -- like the Redux flow or some of the ways that React implemented it where it's very like cyclical and you feel like you're running loops to make things work.
JESSICA: Yeah.
JASON: And you have a view and that value is reactive as long as you have followed the Signals pattern. That's really powerful stuff and I'm happy it's showing up everywhere. And I'm happy that it's being driven toward a standard. Because that's sort of -- in my mind, that's really the end game that any -- any framework should be playing is like how do we get everybody to standardize on a primitive so that it can go into the platform. We don't have to ship the code anymore. It's just there.
JESSICA: Right.
JASON: We can delete 5,000 lines of code out of the framework. It changed the way we wrote JavaScript and we don't technically need it anymore.
JESSICA: Exactly.
JASON: So, we have a couple questions here. Wait...
JESSICA: And gave us the sizzle selector too.
JASON: Oh, yeah.
JESSICA: Which is one of my favorite names.
JASON: Very, very, very good.
JESSICA: It goes along with rendering too. Always have a lot of things sizzling whether you're rendering.
JASON: Any plans to have Signals as a separate package to the framework? so, I guess if it becomes a standard, it obviously separates. But you mentioned it's a shared implementation. Is there an intention to offer that shared implementation as a separate part from Angular?
JESSICA: As it is rights now, the Signals library is a part of Core. Part of Angular's Core. I think there is some desire to have it be a separate publishable package. But I don't think the conversation has happened yet. So, I think we're -- it's possible. It's possible that would be something that you could just use. I think that would probably be really nice because I think it's a great library.
JASON: Excellent. Well, we are coming up on time here. So, chat, you got like a couple more minutes if you want to start getting any last second questions in. Jessica --
JESSICA: Angular, otherwise. You can ask about robots. You know, what have you.
JASON: Also that. Yeah. We can go off topic. Linda wants bacon. I want bacon.
JESSICA: Always.
JASON: While we're waiting to see if any other questions come in, let's do one last round of for somebody who wants to take this and go further, I'm gonna link again to the deferrable views here. So, this is where you can find it in the Angular tutorials. And you can play with them right in the browser. If somebody wants to go beyond, where else should they go? What other resources should they be looking for?
JESSICA: They can use the guide we looked at. The defer guide. You can also -- like there's also instructions here on how you can actually start working with the Angular CL I and play with it locally on your machine. And start building with -- with this on your local machine to start like actually building an app if you would like to. So, that's probably the best place to get started with Defer. I know Mark Thompson has some really great fundamentals out there. So, if you want to play with this content, which is fantastic content. Mark's an incredible educator. Highly recommend trying out his compensate here too.
JASON: Yeah, let me find... when Mark was on, we talked about a bunch of Angular stuff. So, if you want to dig in there. Lots of good stuff to learn from that episode. And then we also have...
JESSICA: Someone may have crashed that episode too.
JASON: Yeah. There was a surprise visit from you'd never guess who.
JESSICA: You have no idea. Nope.
JASON: And then, let's see -- one more shoutout to Jessica. So, go find Jessica on all the places.
JESSICA: I am on Threads, Mastodon.
JASON: Is it okay to pun on an empty stomach? Only if you can digest the humor. Just all of you -- just all of you. You know what? Today I would be okay with zero viewers. Like all of you get out. I'm just kidding.
JESSICA: I don't think you can stomach all of this fun.
JASON: Okay. All right. So, Jessica, we've shared all your links. This is such cool stuff. I feel like if you have been looking at Angular as something that you don't think you should worry about, I think it's worth giving it a look. It's just got a lot going on. There's a lot of cool innovation happening in this space. And it's not the Angular that you might remember from 2017. So, give it a shot. If you're enjoying these episodes, please do let me know who you want to see on the show. You can leave a comment. Please, you know, like the video, subscribe, share it with your friends, because that helps me make more of those. Jessica, any parting words for anybody before we wrap this one up?
JESSICA: Um... I don't know. Be kind. Be kind to everyone. It's probably the easiest thing that you can do. It takes very little effort to just be kind. And please take care of yourselves. It's rough out there. And also...
JASON: I love it. I love it. I'll get one over there. Well said. I have nothing to add to that. So, I'm just gonna say, this episode, like every episode, was lived captioned. We have had Amanda here with us from White Coat Captioning all day, thank you so much, Amanda. That's made possible through the support of our sponsors, Netlify and Vets Who Code. With that, we'll call this done. Go to the Learn with Jason site, next week is special. Tune in, Adam Argyle in studio with me. It's going to be ridiculous. Make sure you tune in, see you everyone.
JESSICA: Live long and prosper, everyone.