Node.js Masterclass

Bookmark

Have you ever struggled with designing and structuring your Node.js applications? Building applications that are well organised, testable and extendable is not always easy. It can often turn out to be a lot more complicated than you expect it to be. In this live event Matteo will show you how he builds Node.js applications from scratch. You’ll learn how he approaches application design, and the philosophies that he applies to create modular, maintainable and effective applications.

Level: intermediate



Transcription


OK, so welcome, everybody. This is my NojeCants backend Masterclass. So you can take a look and keep looking. Hopefully you like this content. Let me know if you have any questions. A good chunk of what you get from this workshop, from this thing, is about the question that you asked me. So to some extent, I am almost going to fix your printer for you during this workshop. So if you have a printer to fix or a bug in Node to offer questions about Node to get answered, you can probably ask me. A little bit about me, you probably know, you joined this workshop, so probably you know, but if you don't, I'm part of the Nojest Tech steering committee. I am the board member on the OpenJS Foundation. I've also spent eight years as a consultant focused on node.js at a company called NearForm. It's an amazing consultancy services company. So you could check them out. They're great. And created a thing called fastify and other P&O. I have a newsletter. I stream on Twitch every week. I don't know. There's a bunch of stuff. Why you need to follow what I say? I don't know. I've been deploying node.js systems for more than 10 years, so I probably gathered enough experience on how to master this beast. So essentially, that's the gist. Also, because probably you are running my software anyway. So, oh, Steve Jobs that entered my room. I knew Steve Jobs one day will come learn node.js. So it's fantastic. So 17 billion downloads per year. That's more or less my overall input on the stuff that you have on your computer. So there is a good chance that at least one of these downloads is you. Pretty much 100 percent, I would say. So happy days. So after all of that is over and all of that is done, let's start talking about the core of the topic. Oh, please, please start your camera. You just follow the folks that just joined. If you can start your camera so that I see you, it's way better if I see you. And so that I can. Oh, more people joining. OK. Is this stopping at all? Amazing. So for all the people, let me flip it back. For all the people that. For all the people that just joined, we have a discord. Channel discussion, whatever, of this URL, then we have a GitHub repo with all the examples that I'm going to do. But to be honest, most of this thing is coming from your questions. So please prepare some questions to get answered later on after I run through all the stuff that I want to tell. So and as I said before, this is will be the probably the only time that you can get me fixing printers. So ask me whatever you question you have and I will answer my best in real time. Cool. So. What is the key thing for building robust and flexible node.js applications? It's the project structure and you probably. And I'm going to say in this in this workshop and I'm going to try to demonstrate that you what most tutorials are saying is completely wrong. They're great for the tutorial point of view, like it's great to get started, but things become quickly become unmaintainable and then you are stuck with a gigantic ball of mud. So. Let's talk about the trip. So there is a three things that we're going to cover. The first one is test driven, test driven development, then avoid global avoid global state and then split the business logic across multiple modules. So three things that we're going to cover in this in our workshop. So let's get into it. Let's get into it on the first one. So it is a quick poll. Let's do if you can see if I can do a quick poll. OK, let me see if I can do a poll here. And let's see, where is the polls and. Is it here? I don't see the polls. Whatever, can't see the polls, so let's do a quick raise by hand or raise by finger, whatever, how many are right in the chat, what test framework do you use? And you can say none if you don't do any test driven development. Jest, Noc, Mocha, Jest, VTest, cypress, Jest, Jest, Mocha, Jest, Jest, Jest, Jest, everybody's using Jest. Good. OK, so you are actually in the right spot. So what is the flow for test driven development? You want to write a test that fail, make the test pass and then refactor. That's the key, the gist of test driven development. Test driven development is mostly a design methodology, not a testing methodology. So it's to create code that is easy to test. And that's why you write the test first. This is important to be clear to all of you. So it's not a design, it's not a testing methodology. It's you write the test first because in that way it will drive your design for your code. OK, so first of all, what kind of tests do you do with write? So, OK. I have a clear rule, so that is you will find a lot of discussions about what is a unit test, what is an integration test, what is an acceptance test, what is an end to end test. OK. OK, so but the most important part, to be honest, is not that. The most important part about automated testing is about what are the components that your team is maintaining and is responsible for. So for the things that your team is maintaining, you want to use the live system. OK, so let's say that your team is maintaining a network of three microservices and two databases for whatever reason. You probably want to run that same thing on your machine when you are developing. OK. And don't use mux. However, if you're calling an external services for something that's not maintained by your team, you probably want to use a mux. So this is very, very important because once you do, if you don't do that, you will try that you will start testing the true equals true type of situation. And then when you go and deploy, you're kind of screwed because things will not work. Have you ever been in that position? Yeah, pretty much everybody, right. So mux are not great. Then. You should typically when you've read this kind of test, you should write the test, the APIs of your modules of your functions, OK, and not really and treat the APIs kind of on a black box. On top of that, test flakiness is the most problematic thing of this approach. So there is basically a flaky test base is useless. So you really need to get that done, that flakiness away. Then last but not least, there is global states too. We'll talk about that in a moment. So it seems that most of you are using Jest. Am I wrong? OK, a few people are, you know, Mocha friends, but most of you are using Jest. Do you think Jest is the right framework for testing node.js applications? No. Yeah, you already you know, you know the problem. Yeah. Yeah. OK, I'm going to show you why it's not and what you can use instead. OK, so let me put it clear. Do not use Jest for testing node.js servers. Full stop. Don't do it. OK, you are setting yourself up for a world of pain for no specific reason, but cargo-culting something that's built for browser stuff. OK. So let me show you the problem. So this is a test file on the right written in Jest. What does it do? It tries to read a non-existent file. OK, and verifies that the error is of instance of error. Does it make sense? What do you think that will execute? If I execute this. What do you think will happen? The error will be from different type. Pretty much. So if we go in here, this is my. So if we go in the node.js folder and we run that. We will get that error is not instance of error in Jest. But if I do. It knows it's passing, OK? And here's a question for you. How do you solve this? Because I couldn't have a question. I don't know how. You can use the inspect to throw maybe. The inspect? Yeah, you can wrap the code that you're expecting to throw something in a function and a misfunction. And then you can say that it expects to throw an error. And you can check the error that it's thrown. But this is throwing an error. Sorry if the error is created. This is not an error. But it's an error. Yeah, but what I'm saying that you can test that it throws an error. The code that you are running, but not fixing directly to check the equality. Oh, yeah, I understand it. Yes. But to be honest, if I want to verify this for whatever reason, I'm screwed. Like if in your code you have you do an instance of error for whatever reason or a dependency, you are screwed. You cannot fix it. I think there's a way to override just globals and inject like node globals into your Jest. Yes, there is. OK. There is. So, OK, going back here. So there is this issue. It's issue 2549. It's very old. It's from 2017 in Jest where it exactly describes this problem. And this is true for all the primordials in Jest. So basically, and for a lot of things, this will just create so much problem. And even if it passes, it doesn't guarantee you that the behavior actually passes in broad. Like it's just nonsense. So. This should not be used. So there is a way to do it, and we'll talk a little bit about it in a second. So, OK, so this we cover. You're going to. So it is the Jest what I'm telling you. You will keep using Jest. Now, after you've been through this workshop, you will probably regret your life choices in a few days, weeks or years. But you will keep using Jest because people keep using Jest. So I'm just I'm basically speaking to the void here. Don't you Jest, but you will anyway. So what should you use instead of Jest? So the first one that comes to my mind is called vite, VTest. Sorry about this. And VTest is great because it has mostly an api similar to Jest. But it's actually way, way better in that sense. OK. Then we have another library called Notetap, which is great. I use it all the time. It's probably my favorite for a long time. But there is something better now. There is this Jest Lite Runner, which is essentially Jest, but without all the problems that comes with Jest. So it's been what is being used by Babel. Sorry, not Babel. What is this one? Yeah, by Babel. It's being used by Babel. The color about is the maintainer by Babel. So, yeah. And there is some features that are unsupported and all the features that are unsupported are really the things about Jest that you should not be using. And you're probably using it everywhere. Make sense? Now, my actual favorite is the NodeTest library. This is part of Node Core and it just got rated stable in Node 20. So you should really be using this. This is my take. Then we have old timers. Like Tape and Mocha. And basically almost anything is perfect in testing Node applications than Jest. Like everything. Don't use Jest. Does it make sense? I know we're not talking about typescript, but if we were to eventually use the built-in test runner with Node, would we do something similar like registering something to just transpile those tests? Or would you just recommend NodeTest for just plain javascript? Again, I know it's not a typescript we're talking about here today. It's just more curiosity. Yeah, this is a good question. And I don't know the exact answer. I think we'll play out. So we will at some point, we will ship some Node compatibility with typescript. So once it's done, we are good. OK? Thanks. OK. Cool. So talking about stuff, the next one, the next problem we have with Jest, it's the use of mocks. And you don't really want to mock a module. OK? And if you need to do that, typically it's because a function has some unobservable side effect or unobservable behavior internally. And you should really not be using this. This is just a code smell for a bad design. Now, some function might need this kind of stuff, but most won't. So don't just do it. OK? Does it make sense? Sorry, what if I need to mock some HTTP requests? HTTP requests are great because it's especially if you're targeting a server that you don't control, they are great to be mocked. And you mean you would mock the server, not the HTTP client? Of course, yes. Because, so not the server. So it depends. So I can also mock the HTTP client. So it depends on what things are easier. So typically we'll mock the HTTP client. So use knock or use undici mocks and stuff to mock the thing and so on. So where do you draw the line? Here in this line, we are saying that mocking other modules is an anti-pattern, but then you have a module which is called HTTP client.ts. And this is what I am going to mock now. No, no, no, no. Wait, wait, wait, wait. I told you that mocking a module is an anti-pattern. OK. So what I'm saying is the when you, so mocking a module is typically say if I may and I require B. OK. And these are quite easy then. I have some code that let me require that does all of these things for you without any change whatsoever. OK. So if you look at here, I just said that you want to mock these libraries. Sorry. These sound player library. And that would be completely. Eden on the topic. OK, let me put a very practical example, right? I'm using Axios to call a remote server that I don't control. So what would you do in that? I would just use knock. I probably won't use Axios to begin with, but I will just use knock to mock the thing. I would not mock the module or mock Axios. I would just use knock or something like that to plug into the value of the beast to get that done. Sorry, beginning question, what is knock? Knock is a mocking utility for HTTP that works on top of the HTTP core module. OK. Can I make the question slightly more complicated? Yeah. No, no. I mean, it's a serverless project. It's all aws lambda. What do you do there? What does it change? It changes nothing. You would also use knock to mock calls to DynamoDB. Sorry, no, no. So if DynamoDB is under the purview of your team, OK, which typically is the case for serverless based apps, I would not mock it at all. I would just use the whatever thing I can run my test against locally and in the cloud. And that's it. Yeah, I mean, locally is not an option, right? Because it's serverless. Yeah, there is an option to run the test locally if you want to. If you look into it, there is a demo that you can run locally to get it done. OK, well, that I would have to look at. But OK, thank you. Great. Makes sense. So the next thing that we're going to talk about is global state. Now, what is the problem with global state? Is if you start using singleton everywhere in your code, you know what a singleton is, right? It's an instance of an object that's unique for your whole application. Then if you have a lot of singletons, then you can't refactor your application because then you don't you don't know when one module start and one module end. Anybody can typically get that singleton one way or another. And you are more or less screwed big time because people will just jump cut corners. So if you have a chain of A, B, C, D, and you might have that D goes back depending on A and A doesn't even know that this is like nobody else is doing anything with it. So it's pretty bad. So it's then you want to do singletons to all the state. And so you don't want to do that. And what do you what do you use instead? OK, it's yes, local stack. So it's these are the questions. OK, yeah. So I was looking at the questions in the chat. So there was a question on Node 20. And for projects that start to use Node 20 at some point, is it recommended to use Node colon test? I believe it's stable in Node 20 now. Do you think other types of scraming will be used under the hood eventually? I don't know to the point where like we had to add Node test because the various Node tests were taking a very specific opinion. And the Node team want to say, yeah, look, this is how you should be testing Node. OK, and set kind of a reference pattern. So I hope somebody else, some other framework will start using it internally, to be honest. It's just great. So. And yeah, it's stable. Yeah, absolutely stable. And yeah, we talked about that. And there is this thing called local stack to run things locally. Cool. OK, so talking about module singleton. OK, let's go a little bit more on this topic. So the typical module singleton, OK, is this kind of pattern. And you can see that you've done this multiple times before. So you have A, B and C. These are three files. OK. And then you have a shared object, a shared object, yes, which export stuff that's used everywhere. How many of you have used this pattern before? All of you? Is there somebody that have not done something like that before? Yeah. Oh, you didn't. You never did something like this. There is Carlos said they all reliable DB connection. Yeah, pretty much. That's what I'm taking. OK. Yeah. That's exactly that. So this usually is DB.js and you have a database connection. And then you have all those three, depending on that. But that you can have a lot of other things that are just singletons here. OK. It's it's really a problem. OK. And why it's a problem and what is causing problems long term. So let's go. Let's let's move forward. OK. So now. Now somebody adds the good opinion to put shared.js in its own module. Because, well, I wanted to use that in another application, so I'm going to move shared.js in another module. And and these goals that deployed at my utilities. Now, my utilities now evolves on its own path and it becomes version two. And at some point I need to add another dependency and then I have version one, version two running at the same time. And now you are pretty much screwed because it's not a singleton anymore. OK. The major, the biggest offender of this problem is graphql. Like graphql, once you use graphql, you can only have one version of graphql required in the system or everything will fall apart very quickly. The reason is because graphql internally does do a lot of instance of and is designed like it's coded like Java or something like that. And because of that, it's it has this problem of that. But don't do this. OK, this is absolutely bad practice. Don't use singleton. Don't make, don't use singleton and not make your application require that there is another version of it somewhere, whatever. OK. Now, now, peer dependencies can possibly catch this, this kind of situations. But, you know, still don't put yourself into having this problem to begin with. Have you ever saw this problem? Did it ever bite you? Yeah, somebody, somebody, yes, somebody now, but this is essentially a big, big, big issue. And especially in larger projects, when you start having your running your code for a while. So. If you're just a slow developer, this is not going to happen, of course, a small team is not going to happen, but bigger team, this is bread and butter. So what do you do instead? OK, my answer to this was is essentially. To develop most code as exporting a function, OK, to build this stuff, OK, and not have any global state. So you have, for example, a start function that returns an object with a stop function. So and all the all the all the things that are needed here are passed in my in my start options. Then when you want to use it, you could get your main and you can start it and stop it and run everything in between. Does it make sense? I can't read you so much well, so if you can react a little bit, that would be great. I want to say I really like this approach of returning the stop function in the end. It can save a lot of brainpower. I used it very often for database connections and so on. All the information I need for the for stopping the specific connection, I pass to the function from the point where I started. Yeah, brainpower save. Yeah, I solve all the problems to begin with, to be honest. It's actually very straightforward to compose stuff. To be honest, also, this is typically defined as a dependence injection by constructor. So this is typically a way it has a formal name. So. So so Janik is asking, is it the only reason for not doing Singleton in modules? For example, if you're not publishing external library, example, if you're not using if you're using a monorepo. So. There is no guarantee that your Singleton is not getting becoming unique. OK, I'm going to talk about so the other reason to avoid global state is if you have if we talked about that in a second, it's this. This is also relying on global state. OK, it's just it's mocking global. OK, again, Jest is still mocking stuff and out there. So. Essentially, you don't want to do that. And this pattern provide a good solution on what to do when that's the case. OK. A monorepo alleviate some of the problems, but don't don't make them go away. So it's it's a different bandaid. Now, new question is, why should we split into multiple packages instead? So. OK. This is probably my favorite block of slides, so I've been you probably have seen them a few times already. So. Let's consider the let's consider the most infamous model view controller module pattern, which more or less everybody as familiar with or as use them in the past. So. You have your clients and you're getting your requests and your request, typically goes into some level of a web framework that has the concept of a controller, a view and a model. The model could be, you know, typically it's something like prisma or. prisma or Mongoose or object objection or whatever, there are plenty of ORMs in the node world, but that's the point. OK. We don't do views anymore, to be honest, like views where when we used to render each email directly, now we don't anymore. So. Cool. Yeah. Yeah, I'm going to answer the question on the cache, Alberto, just in a second. Take your time. Thank you. Yeah. So the problem with these MVC pattern is you will soon get 2000 models. OK. Why? Well, because if you structure your application with controller view and model, if you fast forward with a team of 10 developers, you will in a year or two, you will have 22000 models very quickly, which is a massive issue in practice. OK. It does not scale well in the increase of complexity of modern of modern application. It's not great. So what can we do instead? Well, what we can do is essentially structure my application in modules or in other say in features or in packages, or you can call them the way you want. But you want to structure them by by their domain. And so essentially you want to say, oh, this is the cart and I'm putting everything off the cart into its own folder or its own. If I'm doing using a monorepo tool, even it has its own package in that monorepo. OK. And typically that is owned by a team or a little bit of a sub team, something like that. This is important, very, very important for getting building scalable apps. OK. Divide your code into into sub into sub components. Because ultimately, these will enable you to just move to microservices later on. So just split into two multiple files. OK. Now, there is was a question of a cache. OK. So the question from Alberto was, I fully agree with adding global state, however, how to implement a cache. I have all the JS which obtains an action token, which I want to cache. Normally, we'll define a let us into a variable and have a spot in fashion that is not available or obtains one if not. So the typical thing that you want to do, especially when you're building stuff with Node, you cannot use that pattern mainly because it's it will work well in a browser. When when something change, you can just refresh the browser and everything will work. In node.js, your code stays alive for more requests than one more than one request. So you typically want to have some handle for all of that and make sure also it's testable without mocking stuff. OK, we were doing we were talking about the cache. So what you do instead is you create a cache. OK, so in this example here. OK. And. OK, so you had this right here. Yeah. So what I would do is. Instead of doing that export. So do a sync function, build access. Build get token. OK. OK. Here we go, somebody entered the room. OK. Something like that or even better. This. And then if I import build get token into different modules. Yeah. Are they going to share the cache? That's my question. They aren't. That's the key point. You want to pass that this kind of information around because when you want different part of your system to be able to do things independently. So. Or in other terms, if you want two parts of the system to share the same thing, you want to do it explicitly, which is also. True on that base level. OK. And this is doable, easy doable because you typically what you can do is then you can if this is example, this is example two. OK. And here you do. Export a sync function, do something. And here you get get token. OK. And here is literally. OK. And here you do. OK. And what a mistake did I do? Oh, I think ABC. OK. Something like that. Not that I passed it in as an option. OK. So I definitely need to do something like that. Not that I passed it in as an option. OK. So now I can I need to do. Here I just do import. Example one. Then example two. And then I can do cost. Get token a weight. Example, I can just do build a token. And here I can do build do something. OK, then I can do do something, get token. And then I can just call this is just something. So. So. OK, and then if someone else is using. Being a token, it will not share the cash, right? That's good. Yes, but I will need to pass my thing, my cash through. Like I will need to pass this object around. OK. OK, so in the example that you have on the right. And imagine that you're importing also build do something to from somewhere else. That also takes get token. Yeah, I think I'm going to share the cash in that case. Yeah, if you if you pass the same token multiple times, yes, but you are explicitly doing it. OK. OK. OK. OK. OK. Thank you. Otherwise, you end up in a situation where you can you can also get get a situation where you have essentially big memory leaks and stuff in this way. If you release if you stop having a reference of the get token function. It will essentially be garbage collected. OK. Which is also great for tests and a lot of other things. OK, so if I try to run this, let's see if it runs. Oh, it doesn't run. No, it's side of a module, so. Move. Because I think this just move the the state to the example, the the file on the right. Now, the global state is you have a reference to get token, and that's essentially encapsulating that global state. Yes, but this is in the main. OK, it's my main file, which is the only place where I have, which I know then. OK, controlling things. So then you have to have like a dependency injection framework to register that get token if it's meant to be used elsewhere. Oh, I'm typically passing down like what you want. You really want it to pass down your dependencies as constructors. So you don't need a big, a big, complex dependency injection framework to do that. You can just literally get down here. True, in a simple setup, but if it gets complicated, you have lots of different bits of code you need to. And different places have to have access to that. If you have a very complex places, if you have a very complex set like that, yes, you probably need some dependency injection framework. Or typically what I do is I do something like that, which is cost context. And you put. Get token in there, OK, and then everybody. Kind of get it, OK? If you were to use a dependency injection framework, do you recommend one like Inversify or something or do you never use those? I have built a massive application, never had a need of one. So I don't know if you if you get your answer, if that would be your answer or not. But I hate Inversify. I want reasons to drop it. I there's no reason whatsoever to do use any of this or any of those. Apart from I want to use them. OK, or I come from a Java project. Thank you. Oh, yeah, there is Fancy Call, which is not defined. Where is it? Fancy Call. OK, so this is a wait for teacher. OK. So this does console. Oh, I just define Fancy Call. Here we have NSync. Fancy Call. Console log. Fancy Call. Here you go. You see, this is getting the data and I can do. Like it's again, the part of the biggest problem of not being able to of why you need a global cache in that way, it's because you are maintaining global state. So you just want to. I need to wait. So it's because you you you are requiring that module and you're not initializing it in any way. So at that point is just a plain utility and then you need a global cache. Oh, I'm doing something wrong in example two. Oh, yeah. OK. OK. What is token? Let's see. Undefined. Undefined. So let's fix it. OK. And. OK. Sorry, let's. So we we have. Get token and we have our fancy token Fancy Call in there. And here. So why? Why this is not getting it. Oh, no, it's working, OK, I didn't save, I just didn't save the file. OK, so you can see here only one time we get fancy called, but three times the execution. OK, so essentially we have created our system where we can pass things through and it will just cache. Does it make sense? Yes. What is an entity oriented architect, Joanne? Sorry. I think they might mean like using an ORM and stuff like like I used to do a lot of.NET and there's like the entity framework and. Don't do that big time, like even in.NET, don't do that. OK, so I'm not. It's the concept of fat models is just fundamentally wrong for most. Computer for for most computer engineering reasoning, even from the people that promote object oriented programming, you can use their reasoning to debate the fact that ORMs are just bad. OK. Ultimately, the problem with ORMs is that they have multiple responsibilities, especially the fat model objects. OK, and not that kind of the DTO, like the data transfer object type of patterns. So if you. Yeah, the fat models. Yeah, so a fat model is typically an object. So you have an object that is you map from an ORM. Now you are tended to have that as a class and you are tempted to have this thing with a save method, but also a way to add more methods, more properties to that thing, more functions. So you add more business logic to that component. Now, the way the moment you do more than one thing at a time is just wrong. And if you are moving objects, the responsibility of this piece of like every every type, everything that contains that you move objects, that you move data around should not have metal attached. And you otherwise they think we can very, very complex long term. OK. You want everything that you are manipulating between some part of your app, you want them to be essentially just something that you can feed JSON stringify and be done with it. OK, if you can't feed it to JSON stringify, you're probably screwed. OK. Yeah. The live example, what is the live example you're referring about, Christoph? And the one you just showed we developed together with the token. Oh, this one. Yeah. Yes, yes, you could. You could provide this with the class. Yes, absolutely. But you usually do that or prefer, do you prefer to have it as plain functions? I think this is more readable, but, you know, pick your poison. I'm not like again, none of these, those of these will be so. OK, so you have this. OK, this is more readable. Let's try to rewrite these in functions and I show you why with classes and I show you why is less readable. OK. So let's see, this is OK, let's close it up so that I can get it done here. OK, this is the classes for the first file. OK, so this will be class and I'm calling it example. OK, we forget token. OK, this now pool and it also as a sink. Hopefully this works. And this is this. Hopefully makes sense. OK. And instead we do. Export default. OK. Is this the same? Possibly, I don't know, let's do remove this, so it's actually simpler. Actually, I can. I'm going to do to do to keep it as external things. OK, so we have the fancy code here. And OK. And this is export. Default example. And this is fancy. OK, we have this now if we and then we have this one, which is. Class. Do something. OK, and it's the same. Export default, do something. And now we are here. Ouch, now can do that. I need to do example. I need to do do something. OK. And I cannot even use this kind of destructuring. Oh, sorry. This is I need to get to. Yeah, now. The problem is that if I want to do so, this is the. So I need to do. New example, but look, sorry, I have a problem now. You know why I have a problem. Because this is synchronous. And here I was using a wait. Wait. So if I go back to this block, I can't use this. I guess still need this async here, like because here I can put a wait something. You would need an initialization function that async or so that you call explicitly. So you would have two calls. Yeah. So in reality, I can do that. So what I can do, what I will do here. So I will not do this. So I will do export default. Async. Function. Return new example. OK. And it's just more verbose. Also, in order to do this. Oh, build get token. OK. In order to do this, I would need to. This is I'm calling it example. In order to do get token, I would know to the example, get token bind. Example. Which is audible to read. So the solution would be instead of doing that would be to pass example in. And now everything is essentially. OK. Kind of the same, I'm going to change this up. So this is a sync function, build do something and you get the example. Here you get the example. This example. And then these example. OK. You could. But. Why, like again, I'm not. And oh, it's not defined. Yeah. Cool. And yeah. So here and this is build do something. OK. And. Build get token. And here. Oh, yeah. Why would I do like this is way more complex and harder to read than. At least for me, OK. OK. Kind of the same, but you could do the same is just it's just a matter of preference and exactly what you are doing. So there are cases where I do this pattern mainly because these objects is actually very complex. So and it has a state. So if these objects and. Stop method. Then it will be very useful to keep it as an object. OK. Does it make sense? Thanks. OK. Hopefully, I answered on the topic of classes. OK. And. So there is. So. Yeah, I mean, create a folder per entity contains. OK, I typically don't do it by entity. I typically will create a folder for a domain. So it can be your your inventory or your product catalog or your order management or your I don't know. I will create around that. But it's probably more following a pattern like kind of domain driven design led or something like that. Are there any static code analysis tool to give feedback if you are misusing global state should be a simple reason. Yeah, I don't know if there is a if there is a some known thing that you can use, but I don't, to be honest. It probably could. It's just that I just don't know if it exists. OK, so. But yeah, anyway, you have seen what I meant with the example and how you could start structuring your code bit by bit. And especially you could easily turn things down. OK, so why do you need to turn things down? Let me see if I have it somewhere in here. And no, OK, I'm going to talk a little bit about it. So if you structure the code in in in this way, OK, where do you have example, example two and so on. OK. You could potentially also add a stop method here. OK. So you have a sync function stop and this is. Yeah. OK. And console log. Start access token stopped. Right. And then you have. You can have the same thing. In here, this is the second module. And. This is something stopped. Now, in your in your main OK, here we could do. And then you have stop. Stop, stop one. Now, once you're done, you could do a wait stop, a wait stop one. So you could stop your things properly. Oh. OK, and in order, why is this important? Because you might want to implement what I call the. Graceful shutdown, what we call graceful shutdown, I don't know if you ever talked about graceful shutdown in your code, but that is essentially these module here. So it's man, Colina, close with grace, but there are others like that which you can just use to close your your close your server. And these install public this stop announcing your process so that whenever there is a sick term on context, exception and everything, everything, every stuff that you do is you can shut down your server. And so making sure that, for example, all incoming requests are being processed in there is no broken request. One once it happens. Does it make sense? So this is the module that I'm talking about and passing it in here, the chat. OK. No, wait a second. Everyone OK. Cool. So OK, there was a few questions in the chat. What is the turning to fat models if you are interfacing with a SQL DB? Do you write row SQL query? I'm using type of them, but I ate it with a passion. I don't know how to get away from it. Yeah, I still can use a factor. I know I am without models. Not sure if still an anti pattern. So. The other question, so you mean, you can use a fat model to get away from it. So. The other question, so you mean to keep using those objects with the same and such without adding business logic? Yeah. Look, it's yes. So so whenever you are looking at this diagram, OK, when you're structuring your application in different modules, what you want is that the boundaries between those modules are not those fat models. So the fat models stays in the control of one domain or one team. So in that way, you are not creating a network of of you don't create super interdependent interlocks, interdependencies between those main models which make your process really hard to maintain long term. So I always stay away from it and I will just use there are a few modules to do to interact with your SQL databases. My favorite one is called at database. It's pro support my SQL, Postgres, SQLite, a bunch of stuff you can essentially do a way to be query and pass your SQL and you can even support. Safe injection of the SQL injection production, it's great. Another module like that is called near form. Near form SQL. What's the name of the first one? It's hard to read your screen. OK, sorry, it's at databases. I'm just zooming in. Sorry, I want to do something different, but I was stopped too. So here you go. So the first one is what I'm doing. This is what I want to think I recommend. This is the other one. Kinect is also good. So if you want to use Kinect is also a good module. It's very old. prisma can be good or not good, depending on what you are now you're using it, so I might be you might be stuck with something back there. So. If you don't abuse it, prisma can be prisma can be good, but if you start abusing it, then you are. You are a little bit in trouble. OK. Hopefully this makes sense, OK? It does, thank you. So, again, the type of thing is that you do you run a query and you get, for example, the rows, OK? You see that you see how this would work or how this would work. OK, this is how you do you do something like this and you get the data, OK? And I really like this, this this this thing, by the way, it's it's great. So. Good. So part of this, it's OK, I'm add more people to the team, so to the group, so part of the reason why we are doing all those bits and why I'm going to interact with this is to explain a little bit the design philosophy of fastify. fastify is a web framework for Node that I probably bothered you a little bit already, and it's it's great. But the key part here is talking about the fastify plugins. Now you see what is a fastify plugin. A fastify plugin is, to be honest, just a function exported. So now you can see like, you know, it's this is a core primitive of fastify. So you define your main app as in here, you get the app fastify and you start registering routes. OK, and then with those routes. Sorry, keep moving. I don't know why. And then those routes are. Sorry, so this is those plugins and then those plugins are literally just functions that are received the fastify app as in. Now, fastify implement the type of context depend, easy or dumb. Dependence injection system that we talked about. So. If I want to export something inside my fastify app, outside of my fastify app, I should just can just use the decorate function to add the property and that can be used elsewhere in another plugin. Hopefully it makes sense. So, OK, I can also see show this to you. So in here you have we have fastify plugins and you have oh Mahmood. OK, here we go. So we have our this is our our app. OK, look at what we are doing. We are instance. We have a main a main function here. We have we have our main function, which shows the we have register and we have the shared we have shared and and the routes. OK, two plugins. OK, now and those are sorry and those are one is there declaring routes, starting routes, and the other one is the shared stuff with the decorator. So here I can go and do fastify plugins. And I could just not run node main. And you see this is starting up and I could in in in the routes, I could do curl localhost 3000 and we'll get a lowered. And if I change in shared, I see a low node congress. I can I need to restart this up. I could see these updated. OK, note that if you are running a latest node version, you could even do node watch. And you could change this to word. And it will automatically reload, so it's fun. And look at this is fast, it's fast after loading, OK? So it's actually pretty it's actually plenty of cool. There is no compilation, nothing behind it, so it's super fast. Does it make sense? Now, what is the other reason to do all these shenanigans with plugins and stuff? Because I could actually test all of this. OK. And I could write my test by having some sort of an app and close the app and then. And then create in my test, I can create my app and then I can inject things. Does it make sense? So here what I can do is I can. And test is that yeah, no. So NPX vitest. Oh, yeah, it's not congress is not. That's not shared, this is should be word. So here you can see now is passing, so this is the testing up in the test that just works and do its job. And it's great, OK? Now, let me show you how that would look like with. And. OK, I'm going to call it main test two, and instead of that, I'm going to use test from. Node test. And instead. I think it's test like that. And here instead, we can do a weight main cost. And I actually prefer it, to be honest. It here a tear after. App dot close. And now you can do node test. The main test show and it's failing or expecting not define. So here now you do assert. From node assert and here you do assert strict equal. Two hundred and then here you do a strict. Deep. Or deep strict equal the. Strict equal actual. So. Response Jason. Expected a low word. And. Now we have run our test and you see it's over there. And if we want, you see my test now, it can just run it. I could even do test reporter. Spec. And now it's even better. OK, I. OK, you and you have a question. Yeah. Yeah, can you hear me? Yeah. OK, yeah, I was going to ask. I mean, I never use the test or as a most. From this, so I wanted to know if. I mean, did you think is a good idea to use in the context of the app? I mean, not in testing context, but yes, in execution context. From what I assert. Yeah, yeah, I assert no, you can use a certain whatever you want is fast, so you can just use assert. If you needed to have an assertion on a verify something, you can just use a certain. It works fine. OK, thank you so much. Yeah, that's great. OK, so. There is. There was a thing personally went back using low level. Libraries with raw queries, my sequel to my case, I want to convince my teammates of going that way. Knowing that they have a very, very strong Java background. Well, I have a joke for them. OK, what does it happen when your application use an ORM? It hibernates. So that's my job for them. That's my job for them. OK, so don't you know, it's if you want to hibernate, then. Yeah, but you probably will not. So. Yeah, it's yeah, essentially the answer that Elisa Elisa Natalie is not Elisa is Elisa, not Elisa. But if it's Elisa, please let me know. And I need to in Italian. That's how it's pronounced. I assume you're talking about hibernate. I think the same problem you need to map from your object to your domain model. Essentially, yes, that's the core concept of it. You want to you want to convert your like this. Essentially, the way you're doing the implementing those things, it's kind of an implementation detail and you want to have clear transferable objects at the border. At this point in time, you can just avoid the problem and just move on using just javascript objects for everything. Essentially anything that you can just JSON string if I can get that that data out. It's way better than anything else. And. Can you link any reference to good example of fastify plus WebSockets? Well, you know, I was doing a stream this morning using with a friend of mine, Salma, I stream on Twitch so you can watch me streaming on Twitch every now and then. I can we can move a little bit at a little bit more light getting darker. And I was doing that and we actually build something around those lines. So, yeah, Salma is your co-worker. Yeah, we are doing some some fastify WebSocket stuff and you can. So there is this module called fastify WebSocket and the way I implement this, I pair this with this other thing called MQ emitter. Which does the pub sub part of it. So basically you sum those two bits and it also you can also make it by radius and they also need to add a Postgres when I have the time. So it works and it solves the problem so damn well. I don't have a good example of it. Probably the best example right now. It's inside a library called Mercurius. It's the graphql component of. Is a graphql adapter for fastify and it's it it uses it to implement the subscription. So. Literally, where is this subscription? And this is probably the best use case of fastify WebSocket, essentially, that you can find right now. In the public. Hopefully it's big enough so I can make it bigger. I see somebody looking at it strongly on the screen. Nice, thank you. Hopefully I give you the answer. So know that fastify WebSocket offers a route based fastify route like does HTTP. It does routing also on the WebSocket endpoint so you can have multiple WebSocket endpoints registered in your app. Other frameworks do not offer that. You see, you can you you can just generate a WebSocket route in this way. I had a quick question. I've never used fastify yet, so does it work in a serverless context as well or is it only server full? There is a nice adapter. It works for re it was better than Express in a serverless environment. Or at least on aws. So on aws lambda. We have only an aws lambda adapter, so yes, on aws lambda it was better. The on the rest is probably requires a little bit of work. This is this module and if you are using Express. And or serverless. You can see the numbers for yourself, essentially, I just. Thanks. OK, so it's significantly faster than serverless HTTP. But and impressively faster even from the official one for for Express. Note that there is a catch you can even get completely removed with fastify. You can and the fact that it has these implement these asynchronous boot logic pattern with the plugins. If you use define it as ESM, you can completely avoid the. Cold start by using provision concurrency. When you define your lambda and and relying on the fact that there is an await in your putting an await up ready inside your entry point. So you have your fast if I application to boot, create the connection to your database, do the things that he needs and then after it's all done and then it's all done, it will be used to to get the to get everything started up. It's great and it completely reduce basically cold start close to zero. So and these are techniques that you can use anywhere, but it's useful only if like if this is kind of a synchronous type of thing. Does it make sense? Cool, I see no other questions so I can keep going. Yeah, we talked a little bit about the testing part. OK. So. Let's talk a little bit about the testing part. So. Let's talk a little bit about the test the project structure and how I would structure my I would recommend structuring the code. OK, now you can. These make sense for fast if I have, but it can be very. You can adopt this type of reasoning anywhere you want. So what you want is a lot of a lot of people that use Express, for example, tend to have a route.js file that is between a few thousand to 20,000 lines of code. I don't know if you ever seen a route.js file that is 20,000 lines of code. I hope you haven't, but I did and it's not fun. Did you? Did you? Somebody have a route.js file that is a monster of a file? What's your strategy to splitting that file? OK. So OK, my recommended project strategy is to have. To create to have a routes folder and use actually folders and directories and everything structured in in a way that maps the routes of my application so I can get everything done. And if I need behavior that is shared between everything, I put it inside this plugins thing. So in. In here. And wait a second, what is it? Yeah, this is we cover this. So this is a simple app. OK, so you see we have a main file, OK, which uses ES main, fastify. We have a cross with grace and we use this thing called fastify autoload. fastify autoload does what next, next, next and a lot of other things do. They provide file system based routing. So what this means is that we can have multiple folder, multiple nested folders in there. So and that will make your routes easy, our routing easy. So if I do if I go inside. See this simple app I could do node main. And this is basically we have our shared routes here and we have our routes, which is get so I could do curl localhost. 3000 and it's my yellow word like it was before, but then I can do a shared route. Which is get so I could do curl localhost. 3000 and it's my yellow word like it was before, but then I can, for example, add nested something. Good dot JS and here I could just. Copy this up and passed it down. We didn't copy. OK, and then. Here and I. OK. So now I can run it again. You see that he has started good. If I can, I can curl localhost. But then if I do nested good nested something I get I get my value. OK, and know that I define my plugin as a slash here, but the rest of the components come from the folder structure. And if I want to browse my application routes, I can do app dot print routes. And just console log them. OK. So when I start, I could just you can see that I have my routes. So I have the get then I have nested then I have something then I have a get two more mature things in there. Does it make sense? Note that when I stop this kind of application and this is what fastify does for us, it automatically shut down all the plugins in the order in reverse order on which they started so that everything can be started down in a graceful way. OK, so. Oh, yeah. OK. OK. So. OK. OK. OK. OK. OK. OK. OK. OK. OK. OK. Yeah. Does it make sense? Cool. OK. This kind of open ended question, obviously, you're biased towards fastify. Oh, yeah. But but like what are what are like main differences between like if you were using something like Express still is it is it the plugin architecture? I'm assuming it's faster to begin with. But well, it's it's it's fastifies almost no overhead compared to no core. So this is the starting point. And it's the key difference is the routing. You can fastify as a declarative routing model in the sense of the routes in fastify are assembled in what is called a radix prefix tree, which while in Express, the routes are just an array of regular expression evaluated them evaluated in order, which is. OK. And. Fundamentally, it's extremely more flexible and fundamentally more inefficient, fundamentally inefficient. And also it prevents you to generate to do any sort of metaprogramming on the routes because you don't know what's your routing to one, what's your route structure at any given point. OK, because your structure is evaluated at runtime every single time a request comes in. So you don't know what's the structure of your routes at any point, which prevents you for doing any sort of metaprogramming on the routes such as creating. And creating. Open api definition or implementing an open api definition or creating, adding some authorization checks automatically for certain things like it's so horrible on that front that it's so inefficient and so, so harder to do. So, yeah, essentially, that's probably the second model. Apart from that, Express is great. It's the story of Node, so it's fine. Yeah. OK, cool. Thanks. Cool, right? OK. Cool. Cool. A lot of stuff in here. OK. So how much time do we have? We have probably, this was supposed to run one hour and a half, right? More or less. What time did you have? How much time have we got left, folks? I can keep going for another half an hour at least, if not more. I still have it till six in my calendar, so. I'm personally OK for another 20 minutes, and I'm actually jumping on it. Yeah, OK. So, yeah, perfect. OK. So have you got any questions about any of this stuff? I need to leave soon. I wanted to ask where there will be the recording. Yes, there will be the recording. Because it was quite a lot of information. But there will be, because like I said, it was recorded, but where will it be posted? It will find the recording in the JS Nation website. So you should have access to the JS Nation website. Sorry, not JS Nation, to the Git Nation website. Yeah. So you will be able to find the recording. OK, cool. Thank you very much on this occasion. Thank you, Udia. Yeah, OK. Oh, interesting. So there is a discussion from Aria and there is, sorry, Alicam. Sorry, there is an interesting article by Netflix about the Memory League that they had co-authored. And they are talking about the memory leak. And they are talking about the memory leak. There is an interesting article by Netflix about the memory leak that they had caused by the wrong assumption about Express and the internal routes array. Can you send me the link? That would be fine. iTunes, bye bye. Then there are a few questions. OK. Regarding the project structure, I did split one large app into several microservices. I am with the initial approach, the authentication part. I rely on a kind of JDT 0 flow and most of the logic is duplicating on microservices. For instance, throwing out error, blah, blah, blah. OK. So. So, yes, that kind of architecture is very popular, especially on the JWT side. I ended up having to write kind of the same logic and we ended up reusing it in an internal module. I will probably need to expose it so that you can just use the thing. So, most of the stuff, though, it's kind of governed by if you use this, there is a module called fastify JWT that you can use. And you can just use this. To to set it up and especially if you use the if you combine it with these other module. So there's a module called the JWT, yes, and in something like zero, you can essentially are at a point of. You can probably you can point out a situation where it's completely that's almost, you know, that requires very little work to accept that JWT and verify it. So it's not such a big of a cost in that sense. I would not, especially when using JWT, I will not create a north microservice and then at every step. OK, something that you could do instead is verify the JWT token at the beginning of the request, then discard the token and move that information, the relevant information on HTTP headers. And in that way, because you can validate it at the top, like if the microservices are not exposed to the public, you can skip the validation afterwards and just do the validation at the edge and then internally. You're good. So, yeah, that would be another option. OK, here is the link from the Netflix. Whoa, OK. This is old stuff. It's still true. This is Express. OK, look, look, this is Express. You see this tower? How many call stack is there? This is Express. Express as it's worst. And why you should not use Express. As you can see, it's in this thing, so it's so bad. So. Cool. Yunong. It was written by Yunong. Oh, my goodness. Yay. Amazing Yunong. Yunong is a friend of mine. So. Cool. Oh, it's amazing. Amazing article. OK. So, cool. Is there any other question? I have a question about plugins. Cool. Yeah. OK, so is there a way to define a contract for a plugin? How to define what decorations it requires for correct work? Yes. Yes, there is. So especially if you use. So there is. So in here, for example, you have this greeting. OK. And here you have these other module here. OK. So if we go inside, let me make this smaller. So hopefully you folks can actually read it better. Is it better? So if you go inside fastify autoload. Oh, probably too big now. OK. There is. Sorry, where is it? Dependencies. OK. So you could say you could specify the dependencies here and or you could use these other thing. And it's inside fastify plugin. And it's inside fastify plugin. To. Where is it? So, yes, you see dependencies. You can even say that you want certain decorators being present. OK. So, yes, you could do all sorts of things and it actually works. Cool. Thank you. So, yeah, I would recommend doing this kind of stuff and that will. Make sure that everything is loaded in order and properly. Perfect. OK, thank you, Mahmoud. And thank you, Khoder and Herb. And yay. Amazing, folks, I hope you enjoyed it. OK. Did you enjoy it? Yeah, no, thanks for much for digging into all this for us. So to be honest, again, if you are looking for for some new stuff, you can check out Platformatic. It allows you to do most of what I showed and everything very easily yourself in the code. So it's great. Just a small pitch and so on, and I don't have time for the demo now, but it would be fun. Cool, folks. Thank you for for watching, for being here. And I'll in order if more people are interested in platformatic and give you a little bit of a demo. Otherwise, I can we can all part ways. What would you prefer? I would prefer to be able to show you the code. We can all part ways. What would you prefer? The attendance number is dropping, so it's it's. Personally, I'm curious about Platformatic. I can keep going. OK, let's let's do a little bit of let's do a little bit of a thing. And if you want to stay on, can stay on. Otherwise, I can my app. My app. OK, and. If you want to stay on, you can stay on or drop whatever, and I cover all the topic I wanted to cover and cool. So what you can do here is if you want to start with a basic first platformatic application, you can do some PM, create platformatic. And at latest. And we want to create DB because that's the most complete thing. And you want some default migration, default plugin, and you want to use type. Do you like typescript? typescript. You like typescript. OK, so we are using typescript. I'm coding typescript so everything can go wrong now. So now it's installing npm. We run the migrations. Generate the types. We are going to deploy things maybe. Maybe. OK. OK, so. Now let's look at what it was generated for us. We have a database, a SQLite database here by default. You can configure it to be Postgres or whatever you want, to be honest. We have a platformatic.db.json, which has a config file, which is a nice scheme at the top. What does it mean? We have a schema. It means that you can essentially add stuff in here and you can you get out of completion. Essentially, if we are the language servers of VS code. So it's actually nice to edit. It's nice to add it. OK, so. OK, so what does this do? OK, so what does this do? I can just do npx.plt.db.start to start my system. npm.i.platformatic. Need to add this thing. And here we go. This has started. Oh, sorry, I am not in the right folder. That's why it didn't start. So my app. Cool. It started. Yeah, you see that it did a compilation stuff and watch mode and so on and so forth. So I can go open up my browser. Can you see my browser? Yes. Cool. So it's as big as the other thing. OK, now I can, for example, look at it and we have automatically. Hello, Mark. We have automatically generated some some routes for us. So we have movies get past put and get put delete on on on everything. So it's actually very cool, very nice. And we can, you know, for example, we can use this to to add a movie. OK, so we can try it out. And if I want to try it out. I can not have an ID and just specify, for example, here, Star Wars. And here I'm getting my outcome ID, one title Star Wars, and I get my title here. This is another route for getting all my movies, a lot of request stuff, and then I can just execute it. And you can see that I am getting the value out of that. Does it make sense? So cool stuff about it is that you can even have a graph support. So here you can just do. Title. So we can save a movie called the Wizard of Oz and we have mutations and then we have the. Movies. Movies. Title, for example. And all of these was automatically was automatically handled for us like there is no actual code that does this. OK, all of this is controlled by the configuration file. What's cool, though, is that I could add more stuff into my into my. So into my into my application. So what I can do is, for example, at the slash low route and now I can curl localhost 3042 a low and get a low word. Note that I didn't have to restart everything, get compiled automatically and so on, hooked up correctly. And if I go to my swagger UI. OK, I can refresh and now I also have a low at the bottom. So it's automatically get everything done and I can. For example, I could add a title route so I can just want to get all the titles of my movies. And I could do cost. This is movies. A weight up platformatic. The entities. OK, movie. Find. And then I could do a movie movie title. Not that all of this is typescript. So all of this is typed and correctly working. And then I could just go in here and go titles and I get the title of my movies. And this is, as I said, this is fully typed. So. You see, I have the title and all the things that they want to have here. Hopefully it makes sense. I can also extend the graphical schema and completely customize everything, which and this is the benefit of the two word. So I can have api done very quickly on when I don't need them, but I can also have the full power of fastify and everything to be to begin with. If I have things done correctly, note that I can also use folders in my. Like I could essentially have a routes and plugins folder in here and everything will be loaded correctly. So and as we did before. So it's just that the basic stuff, just have a plugin that they as five. But all of you can specify a folder in here so we can try to do that. And say that we do routes. And here we are moving. We are changing this. And. We can move this into routes. OK. Now, this failed badly, so I probably need to restart everything. Because doing this kind of refactorings doesn't seem to work. So I'm going to restart everything. And. This failed badly, so I probably need to restart everything. Because doing this kind of refactorings doesn't it's not really like by the logic. But. Oh, yeah, it doesn't work because. Routes I need to load dot dot global. This gives me the types of my application. So the types of the movies and everything. So here you go, you see, this is the same and I could run it and it's all working in the same way as before. Know that all of this is getting compiled automatically in the disk folder. And yeah, that's. Kind of it. I can keep going forever. OK. And. So there is a few questions in here. From Alberto and sorry for going back to that topic. Are you still around? Yes. OK. Sorry for going back to the topic. But do you use do a wide market? The WS is decay. Is it a local stack or something else? If yes, what do you do when you're using something local? So there's not support. I typically what I do is I tend to use. So I am. So if you're dependent of a cloud server for running your system, you probably want to have an account for each one of your devs. And you want to use cloud resources for each one of those cases. So you are developing against the real thing. OK. So. Hopefully that answer your question in a better way. So I don't I I typically don't do mocking unless it's in it's extremely needed. It just doesn't work in practice. I can test through mocking means testing. Something is true. testing is true equals true. It doesn't make much sense from my point of view. And to put it very stupidly. So you need actually Internet to run your tests. Right. Because you're going to. Of course. But that's the price you pay to use a WS. So, you know, sorry. Fair enough. Fair enough. Sorry about it. Yeah, it's it's it's fair enough. I just wanted to be sure that they understood you correctly. So, yeah, it's. Yeah. Yeah, something that's fun here. So any tips from again from express to fastify is by using fastify express. So, yes. So this is this is actually very interesting. So we have these adapter called fastify express. That allows you to mount express application within a fastify application. And that's it, really, you just register it. You just have fastify express and then you can just use that to use to register your module. You just have a full middleware system deployed. Now, should you do that? Probably not, but it's going to be a very interesting thing. So, yeah, I think that's it. So, yeah, I think that's it. So, yeah, I think that's it. Now, should you do that? Probably not, but it's good for migrating things. And there have been quite big migration done via this module. So it's rock solid with some quirks and other limitations, but it's rock solid. And. I don't think is slowing down performance. It's like this press application is what will be slow. But if the routes if you're not matching the routes, then it's great. So to be honest, it's probably fine. Like if it will be as fast as express for the old things and fast as a fastify for the new things. If you get what I mean. Yay, bye bye Nick. Nick is gone. Cool. A question about what's for magic. Yeah. What do you think? When should we use what's for magic instead of fastify? So it's to be honest, if you want to use. So. You don't get. So if you if you're if you need to choose, you don't need to choose. So you can just use platformmatic if you want or just wait for it. In the sense that let's consider this simple app that we've wrote. OK, that has a main file. Structured in this way. OK. And you have this. Sorry. No, wait. You have a main file structure in this way where you have these things and so on and so forth. Now, this setup requires a little bit of modules to begin with. So but you have your shared and your good and all these routes and stuff. So what you could do instead is let's call simple up to. And see the simple up to. OK, and now what you can do in simple up to it's npm create platformmatic. At latest, OK, so platformmatic is a production ready out of the box fastify experience. So if you don't want the automatic api created for you, you can just build platformmatic service. And if you pick platformmatic service, you want to run. Oh, yeah, this is not needed. OK, yeah, let's put it, but it's not needed. OK. OK, so. I don't want the test. OK. And here. OK, we have the routes and we have the plug in and we have. OK, so here you see that we have plugins and routes. OK, they're really created and we don't need typescript. So and so you see that it also has the environment valuable substitution. So these are just environmental substitutions and it's great. So in order to run this, I can just MPX platformmatic service start. And look, this is this works exactly as it was working. Oh, no, it's different port. So it's work exactly as it was working before. So I actually had to do literally nothing to change the system. So basically, it has no limitations compared to first. No, you can use platformmatic service and it has absolutely no limitation. It just comes with a lot of things out of the box so that you don't need to worry about them. Keep them up to date, keep them good defaults and stuff. And it just works. And you can just as you said, you can you can see the error is just. That's what's fine. OK, so it's. You can. Hello, Git Nation. And if you do, you see this is automatically loading everything you would expect from a good DAX. Now, if you want to run this, you can do it. And if you do, you see this is automatically loading everything you would expect from a good DAX. Now, it does a few more things here. So you could, for example, you can get it. It adds a few more stuff. So it has the it has nice logging, as you said, you can see. It provides a graceful shut down. It provides a lot of stuff that automatically you wouldn't. And. You you will need to implement yourself. OK, so it's. That's the difference between the two. OK. And if you want to use PlasmaDB, you get all that stuff. So hopefully. That's the good that the good explanation. So have fun and was a pleasure to have this here. Let's see if you can join the. So if you want to reach me, we have a few good resource, few resources for fastify. If you want to to reach it. So one is, of course, the fastify. OK, and there's a bunch of stuff here. We have a discord server so you can go and get up and we are redoing the website. So if you get if you want to join, there is this chat here and it goes into our discord server. This is the fastified discord and you could just join that. OK, and we also have a platformatic discord server that you can get in in here. So if you want to join, you can join. This course server that you can get in in here. So and you can find me in both. So you can just ask me questions every time. So, yeah, that's it really. So have fun.
109 min
19 Apr, 2023

Watch more workshops on topic

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career