Node.js Masterclass

Rate this content

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

109 min
19 Apr, 2023

AI Generated Video Summary

Welcome to the NojectCants backend masterclass! In this workshop, we will cover key aspects of building robust and flexible Node.js applications, including test-driven development, avoiding global state, and splitting business logic across multiple modules. We will also discuss the importance of project structure and how most tutorials can lead to unmaintainable code. Additionally, the workshop covers topics such as choosing the right testing framework for Node.js, mocking and global state, module singletons and avoiding global state, structuring applications and implementing caches, and implementing graceful shutdown for servers.

1. Introduction to NojectCants Backend Masterclass

Short description:

Welcome to the NojectCants backend masterclass! In this workshop, we will cover the key aspects of building robust and flexible Node.js applications, including test-driven development, avoiding global state, and splitting business logic across multiple modules. We will also discuss the importance of project structure and how most tutorials can lead to unmaintainable code. Test-driven development is a design methodology that involves writing tests first to drive the design of your code. It is not just a testing methodology. So, let's dive into the details and start with a quick poll to see which test frameworks you use. Good, it seems like most of you are already using Jest, which is great. Now, let's talk about the flow of test-driven development and the different types of tests you can write.

OK, so welcome everybody, this is my NojectCants backend masterclass. So you can take a look and keep... 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 questions that you ask me. So to some extent I am... I'm almost going to fix your printer for you during this workshop. So if you have a printer to fix or a brushing node, to... of 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 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 system 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% 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. For all the folks that just joined, if you can start your camera so that I see you, it's way better if I see you so that I can... Oh, more people joining. Okay. Is this stopping at all? Amazing. So, for all the people, let me flip it back. 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've run through all the stuff that I want to tell. So, and as I said before, this will be probably the only time that you can get me fixing printers. So ask me whatever 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 workshop, and I'm going to try to demonstrate that 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, so the three, so there is three things that we're going to cover. The first one is test-driving, test-driven development, then 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. Okay, 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? Writing in the chat, what test framework do you use? And you can say none if you don't do any test driven development. Jest, Nock, Mocha, Jest, VTest, Cypress, Jest, Jest, Mocha, Jest, Jest, Jest, Jest, everybody's using Jest. Good, okay. 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 is 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's 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. Okay, so first of all, what kind of tests do you write? So, okay, I have a clear rule.

2. Automated Testing and Components

Short description:

The most important part of automated testing is understanding the components your team is responsible for. Use the live system for components your team maintains, and mocks for external services. Testing APIs and avoiding flakiness are crucial. Global states will also be discussed.

So, there 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, okay? Okay, 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, okay? 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, okay? And don't use Mox. However, if you're calling an external service for something that's not maintained by your team, you probably want to use a mock. So, this is very, very important because if you do 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, the mocks are not great. Then you should typically, when you've read this kind of test, you should test the APIs of your modules, of your functions, okay, and not really 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.

3. Choosing the Right Testing Framework for Node.js

Short description:

Do not use Jest for testing Node.js servers. It is not built for that purpose and can lead to many problems. Instead, consider using Vtest, Notetap, Jest Lite runner, or the Node test library. These options provide better alternatives for testing Node applications. Additionally, Tape and Moccam are also good choices. If you're using TypeScript, there will be Node compatibility in the future. Thank you.

So, it seems that most of you are using Jest. Am I wrong? Okay, 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, not just applications? No. Yeah, you already, you know, you know the problem. Yeah, yeah. Okay, I'm going to show you why it's not and what you can use instead, okay? So, let me put it clear, do not use Jest for testing Node.js servers. Full stop, don't do it. Okay, you are setting yourself up for a world of pain for no specific reason, but cargo carting something that's built for browser stuff. Okay? So, let me show you the problem.

So this is, this is a test file on the right written in Jest. What does it do? It try to read a non-existent file, okay? And verifies is 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 no jest folder and we run that, we will get that error is not instance of error in jest, but if I do, it node, it's passing, okay? 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 expect to throw maybe. The inspect? Yeah, you can wrap the call that you are 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 that it's wrong. But this is throwing an error, sorry. If the error is created, it is not an error. But it's an error. Yeah, but what I'm saying that you can test that it throws an error in the code that you're running, but not fixing it 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 jest globals and inject like node globals into your jest. Yes, there is, okay. There, there is. So okay, going back here. So there is this issue is issue 2549. It's very old, it's from 2017. 2017 in jest where it exactly described 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, okay, so this, we cover. You're going to, so it is the jest what I'm telling. You are, you will keep using jest. Now after the, after you've talked, you've been to this workshop, you will probably regret your life choices in a few days, weeks or years. Okay? But you will keep using jest because people keep using jest. So, I'm just I'm basically speaking to the right 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, okay. Then we have another library called Notetap, which is great, I use it over 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 with all the problems that come with Jest. And it's been what is being used, sorry, with what is being used by Babel, sorry not Babel, what is this one? Yeah, by Babel. It's being used by Babel, dichlorobut," is the maintainer by Babel, of Babel. So, yeah. And there is some features that are unsupported and all the features that are unsupported are really the things about jazz that you should not be using and you're probably using it everywhere. Make sense? Now, my actual favorite is the Node test 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 all timers, like Tape and Moccam. And basically almost anything is perfect than testing Node applications than just like everything. Don't you just. Does it make sense? I know we're not talking about TypeScript, but if we were to eventually use, you know, the built-in test runner with Node, would we do something similar? Like, you know, registering something to just transpile those tests or would you just recommend Node test for just plain JavaScript? Again, I know it's not a TypeScript that we're talking about here today. It's just more curiosity, so. Yeah, this is a good question. I don't know the exact answer. I think it will play out. So we will, at some point, we will ship some Node compatibility with TypeScript. So once it's done, we are good, okay? Cool, thanks. Okay.

4. Jest Mocking and Global State

Short description:

The use of mocks in Jest can be problematic, especially when it comes to mocking modules. It's generally not recommended to mock a module, as it indicates a potential design issue. However, mocking HTTP requests, especially when targeting a server that you don't control, can be useful. Knock is a mocking utility for HTTP that can be used to mock HTTP clients and plug into the desired behavior. When working with serverless applications, such as those using AWS Lambda, using Knock to mock calls to DynamoDB is also recommended. The use of global state and singletons can lead to difficulties in refactoring applications. Instead, it is advisable to use local stack to manage state. In terms of testing, the node: test framework is stable and provides a reference pattern for testing Node.js applications. Local stack can also be used to run tests locally. Now, let's delve deeper into the topic of module singletons.

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, okay? And it's, 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, okay? That doesn't make sense.

Sorry, what if I need to mock some HTTP requests? HTTP requests are great, because it's especially if you are targeting a server that you don't control, they are great to be mocked. So I can mock the server, not the HTTP client. Of course, yes. Because, so not the server. So in, it depends. So I can also mock the HTTP client. So it depends on what things are easier. So typically we mock the HTTP client. So to use knock or use un-dim-mock and stuff to mock the thing and so on.

So where do you draw the line? Because here in this line, we are saying that mocking all modules is an anti-pattern, but then we 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. Okay. So, what I'm saying is, so mocking a module is typically say, if I am a and I require b, okay, and this required is hidden, I have some code that let me require that does all of these things for you without any change whatsoever, okay? 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 hidden on the topic.

Okay, 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 would 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 beast, the value of the beast to get that done.

So sorry, beginning question. What is Knock? Knock is a mocking utility for HTTP that works on top of the HTTP core module.

Okay, can I make the question slightly more complicated? Yeah. No. It's a serverless break, it's all AWS Lambda. What do you do there? What does it change? It ain't change nothing. You would also use Knock to mock calls to DynamoDB. Sorry, no, no. So if DynamoDB is under the purview of your team, okay? 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. Okay, well, then I would have to look up. Okay, thank you.

Alright, great. Make 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 role application. Then if you have a lot of singletons, then you can't refactor your application because then 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, then you want to do singletons towards the state and so you don't want to do that. And what do you use instead? It's... Yes, local stack. So, this is the questions.

Yeah, so I was looking at the questions in the chat. So, there was a question on node 20. And for project 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 test is scrambled and used under the hood eventually? I don't know, to the point where... Like, we had to add node test because the values node test, we're taking a very specific opinion and the node team want to say, yeah, look, this is how you should be testing node, okay? 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, okay.

Talking about module singleton, okay? Let's go a little bit more on this topic.

5. Module Singletons and Avoiding Global State

Short description:

Module singletons can cause problems in the long term, especially when multiple versions are used simultaneously. GraphQL is a major offender in this regard. To avoid this, it is recommended to export functions instead of using singletons and global state. Dependency injection by constructor is a formal name for this approach. Splitting into multiple packages is also beneficial, as it helps avoid relying on global state and mocking globals. Mono-repos can alleviate some issues but are not a complete solution. The model-view-controller pattern is widely known but views are no longer used.

So, talking about module singleton, okay? Let's go a little bit more on this topic. So, the typical module singleton, okay? Is as 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, okay? And then you have a shared object, a shared object, yes, which export stuff that use 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 didn't, you never did something like this. There is Carlos at the all reliable DB connection. Ha ha ha, yeah, pretty much that's what I'm taking, okay? Yeah, that's exactly that. So this usually is DB dot JS and you have a database connection. And then you have all those tree depending on that, but then you can have a lot of other things that are just singletons here, okay. It's really a problem, okay. And why it's a problem, and what is causing problems long term.

So let's move forward, okay? So now, somebody had the good opinion to put shared dot JS in each module because, well, I wanted to use that in another application. So I'm going to move shared dot JS in another module. And this goes at the point that my utilities. Now, my utilities now evolves on it's own path, and it becomes version two. And at some point, I need to add another dependency, and then I have version one and version two running at the same time. And now, you're pretty much screwed because it's not a singleton anymore. OK. The major, the biggest offender of this problem is GraphQL. By 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 do a lot of instance off, and it's designed like, it's coded like Java or something like that. And because of that, it has this problem, but don't do this. OK, this is absolutely bad practice. Don't use Singleton, don't use Singleton and not make your application require that there is another version of it, somewhere or whatever. Now, peer dependencies can possibly catch this, this kind of situations, but 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, no. But this is essentially a big, big, big issue. And especially in larger projects, when you start having, you're 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? My answer to this was, is essentially to develop most code as exporting a function to build this stuff 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 things that are needed here are passed 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 wanted 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 stopping the specific connection, I pass through the function from the point where it started. Yeah. Brainpower saved. Yeah, I solved 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 dependency injection by constructor. So this is typically a way that has a formal name. So, so, so Jannic is asking, is it the only reason for not doing singletons in modules? For example, if you're not publishing external library. Example, if you're using a mono-repo. So, there is no guarantee that your singleton is not getting, becoming unique. Okay. 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. Okay. It's just mocking, it's mocking globals. Okay. Again, just is still mocking stuff and out there. So, essentially you don't want to do that. And this pattern provides a good solution on what to do when that's the case. Okay. A mono-repo, alleviates some of the problems, but don't, don't make them go away. So, it's a different, band aid. Now, new question is why should we split into multiple packets instead? So, okay. This is probably my favorite block of slides. So, I, I've been, you have probably have seen them a few times already. So, let's consider the, let's consider the most infamous model view controller mode to my pattern, which more or less everybody has familiar with or has used 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 a prisma or prisma or Mongoose or objection or whatever. There are plenty of ORMs in the Node world, but that's the point okay. We don't do views anymore.

6. Structuring Applications and Implementing Caches

Short description:

To structure your application in a scalable way, divide your code into sub-components based on their domain. This allows for easier scaling and potential migration to microservices in the future. When implementing a cache in Node.js, it's important to consider that the code stays alive for more than one request, so a different approach is needed. Instead of using a global state, create a cache and pass it as an option to different modules. This way, you can explicitly share the cache between specific parts of the system. By passing dependencies as core structures, you can avoid memory leaks and ensure easier garbage collection.

To be honest, like views where, when we used to render HTML directly now we don't anymore. So, cool. Yeah. 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 2,000 models, okay? 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 2,000 models very quickly. Which is a massive issue in practice, okay? It does not scale well in the increase of complexity 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 their domain. So essentially you want to say, oh, this is the cart and I'm putting everything off the cart into its own folder, or it's on, if I'm using a mono repo tool, even it has its own package Jason in that monorepo, okay? And typically that is an owned by a team or a little bit of a sub team, something like that. This is very, very important for getting building scalable apps, okay? Divide your code into sub components, because ultimately these will enable you to just move to microservices later on. So just split into two multiple files, okay?

Now there is was a question of a cache, okay? So the question from Alberto was, I fully agree with adding global state. However, how would I implement a cache? I am all the JS which obtains the action token, which I want to cache. Normally we'll define a let us enter a variable and have a support and function that are not available or obtain 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 will work well in a browser. When something changed, you can just refresh the browser and everything will work. In node.js, your code stays alive for 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, okay? We were talking about the cache. So what you do instead is you create a cache, okay? So in this example here, okay? Okay, so you had this, right? Yeah, yeah. So what I would do is instead of doing that, export. So, do do, do do. Async function build access build get token. Okay. Here we go, somebody entered the room. Okay. 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 this kind of information around. Because when you want different part of your system to be able to do things independently. So all 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. And this is easy doable because you typically, what you can do is then you can, if this is example, this is example two. Okay? And here you do export a sink function, do something. And here you get token. Okay? And here is literally, okay? And here you do... Okay? And what a mistake did I do? Oh I sink abc. Okay. Something like that. Note that I passed it in as an option. Okay? So now I can, I need to do... Here, I just do import example one. Then example two. And then I can do const get token await. Example where I can just to build a token. And here, I can do build to something. okay. Then I can do do something at token. And then I can just call the usage of something. So... Okay, and then if someone else is using a big token, it will not share the cash, right? That's what you said. Yes, but I will need to pass my thing, my cash, through. Like, I will need to pass these objects around, okay? Okay, so in the example that you have on the right, imagine that you're importing, also, build do something two from somewhere else. That also takes getToken. Yes, exactly. Are they going to share the cash, in that case? Yeah, if you pass the same getToken multiple times, yes. But you are explicitly doing it, okay? Okay, okay, okay, okay, thank you. Otherwise, you end up in a situation where you can also 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 getToken function, it will essentially be garbage collected, which is also great for tests and a lot of other things, okay? So if I try to run this, let's see if it runs. Oh, it doesn't run. Oh, inside of a module, so. Move example. Doesn't this just move the state to example, the file on the right? Now the global state is you have a reference to getToken and that's essentially encapsulating that global state. Yes, but this is in the main, okay? It's my main file, which is the only place where I have, which I know then, okay, controlling things. So then you have to have a, like a dependency injection framework to register that getToken if it's meant to be used elsewhere. Oh, typically passing down like what you want, you really want it to pass down your dependencies as core structures.

7. Dependency Injection Frameworks

Short description:

You don't need a big complex dependency injection framework. In a simple setup, you can use a context to share dependencies. If your codebase becomes complex, you may consider a dependency injection framework, but it's not necessary. Inversify is not recommended. There's no reason to use it, unless you have a personal preference or come from a Java project.

So you don't need a big, a big complex dependency injection framework to do that. You can just literally, I can down here. True, in a simple setup, but if it gets complicated, you have lots of different bits of code, you'll 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 context. And you put getToken in there, okay? And then everybody kind of get it, okay? 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 massive Node.js application never had a needle of one. So I don't know if you get your answer, if that will be your answer or not. I hate Inversify. I want reasons to drop it. There's no reason whatsoever to use any of those, apart from I want to use them, okay? Or I come from a Java project. Thank you.

8. Caching and the Problem with Fat Models

Short description:

Here we have NSync fancy call console log fancy call. We have created our system where we can pass things through and it will just cache. The concept of fat models is fundamentally wrong for most computer engineering reasoning. ORMs have multiple responsibilities, especially the fat model objects. You want everything that you are manipulating between some part of your app to be something that you can feed JSON stringify and be done with it. The live example is the one developed together with the token. You could provide this with the class, but I think using plain functions is more readable. Let's try to rewrite this in functions and I'll show you why it's less readable.

Oh yeah, there is fancy call, which is not defined. Where is it? Fancy call, okay. So this is a wait for two, okay? So this does console. Oh, I just defined fancy call. Here we have NSync fancy call console log fancy call. Okay, here we 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, you just want to... Yeah, I need to wait. So it's because you are requiring that module and you're not initializing it in any way. So at that point it's just a plain utility and then you need a global cache. Oh, I'm doing something wrong in example two? Oh yeah. Okay. Okay. Oh, what is token? Let's see. Undefined, so let's fix it. Okay. And okay. Sorry, let's... So we have get token and we have our fancy token, fancy call in there, and here it is. So why? Why this is not getting it? Okay. Oh, no, it's working. Okay, I didn't save... I just didn't save the file. Okay, so you can see here, only one time, we get fancy call called, but three times the execution. Okay. 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 entity-oriented architecture, Juan? Sorry. I think they might mean like using an ORM stuff, like I used to do a lot, and there's like the entity framework, and... Don't do that. Big time. Even, don't do that. So I'm not... The concept of fat models is just fundamentally wrong 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. Ultimately, the problem with ORMs is that they have multiple responsibilities, especially the fat model objects, okay? And not the DTO, like the data-transfer object, type of patterns. Yeah, the fat models... So a fat model is typically an object. So you have an object that 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 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, everything that contains that you move objects, if you move data around should not have method attached. And otherwise, they think we become very, very complex long-term, okay? 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. Okay, if you can't feed it to JSON stringify, you're probably screwed. Okay, yeah, the live example, sorry, what is the live example you are referring about, Christof? The one you just showed we developed together with the token. Oh, yes. This one, yeah. Yes, yes, you could. You could provide this with the class. Yes, absolutely. Would you usually do that or do you prefer to have it with plain functions? I think this is more readable, but you know, pick your poison. I'm not like again, none of these, those, these will be. So, okay, so you have this, okay? This is more readable. Let's try to rewrite this in functions and I'll show you why, with classes, and I'll show you why it's less readable. Okay? So let's see. This is, okay, let's close it up so that I can get it done here. Okay, these are the classes, the first file. Okay. So these will be a class and I'm calling it example. Okay. We forget token. Okay. This now cool. And it also has a sync. Hopefully this works. And this is this, hopefully it makes sense. Let's do it.

9. Using Async Functions and Passing Parameters

Short description:

Instead of using the synchronous approach, we can use an async function to return a new example. This is a more verbose solution, but it allows us to avoid the problem of mixing synchronous and asynchronous code. Another option is to pass the example object as a parameter, which can make the code more readable. It ultimately depends on personal preference and the complexity of the object being used.

And instead we do export default. Okay. 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 keep it as external things. Okay. So we have the fancy call here and okay. And this is export default example. And this is fancy call. Okay. We have this. And then we have this one, which is class do something. Okay. 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 something. Okay. And I can not even use this kind of destructuring. Oh, sorry. This is, I need, yeah get talking. 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. So if I go back to this block, I can't use this. I can still need this async here, because here I can put a wait something. It doesn't make sense. You would need an initialization function that async, or so that you would call explicitly, so you would have two calls, yeah. Yeah, so in reality, I can do that. So what I will do here, so I will not do this. So I will do export default, async function, return new example, okay. And it's just more verbose. Also, in order to do this, oh, build GetToken, okay. In order to do this, I would need to, this is, I'm calling it example. In order to do GetToken, I would note to the example, GetToken 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 okay. Kind of the same, I'm going to change this up. So this is a sync function, build.something, and you get the example. Here, you get the example. These example. Then these example. Okay. You could but why? Again, I'm not. It's not defined? Yeah. Yeah. Your hero and this is built to somebody. And. Build yet token. And here, oh, yeah. Why would I do this is way more complex and harder to read than. At least for me. Kind of the same, but you could do the same is just it's just a matter of preference and exactly what you're doing. So there are cases where I do this pattern mainly because this object is actually very complex. So and it has a state. So if these objects had a. Stop method. Then it would be very useful to keep it as an object. OK. Does it make sense. Thanks. OK. Hopefully I answered on the top of classes. OK. And.

10. Structuring Code and Using Static Analysis

Short description:

Create a folder for a domain, like inventory or product catalog, instead of by entity. Use a static code analysis tool to check for misuse of global state. Start structuring your code gradually and easily turn things down.

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 lead or something like that. And. Are that any static code analysis tool to give feedback if you are misusing global state should be a simple listing you. 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. Okay, so. But yeah anyway, you, you, you have seen what I meant with with the example and how you could start structuring your code bit by bit. And especially you could easily to turn things down.

11. Implementing Graceful Shutdown for Server

Short description:

To properly shut down your server and ensure all incoming requests are processed without any issues, it is important to implement a graceful shutdown. This involves using modules that can be used to close your server and handle the shutdown process. By installing these modules, you can ensure that your server is shut down properly, even in the event of a CD and sick term on context section. This helps maintain the integrity of your server and prevents any broken requests from occurring.

Okay, so why do you need to tear things down? Let me see if I have it somewhere in here. And no. Okay, I'm going to talk a little bit about it. So if you structure the code in this way, okay, where do you have example? Okay, example, true. And and so on. Okay. You could potentially also add a stop method here. Okay, so you have a sync function stop and this is yeah. Okay. And console log, 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. Okay. Here we could do. And then you have stopped. Stop. Stop stop one. Now, once you're done, you could do. Stop I wait stop one. So you could stop your things properly. OK. And in order. Why is this important? Because you might want to implement. What I call the. Graceful shut down what we call graceful. Done I don't know if you've ever talked about graceful shut down in your code, but that is essentially. These module here. So, it's mental. They are doing this and others like that which you can just use to close your your clothes your server. And these install public? This store guy announcing your process so that whenever there is a CD and sick term on context section and everything, everything every stuff that you do is you can shut down your server properly. Making sure that for example all incoming requests are being processed in there is no broken requests 11 seat happens. Does it make sense? So this is the module that I'm talking about and passing it in here chat. Oh wait a second. Everyone okay. Cool.

12. Interacting with SQL Databases and Fastify Plugins

Short description:

There are two modules, AT Database and NearForm-SQL, that can be used to interact with SQL databases. Prisma can also be used, but it can become problematic if abused. The key part of Fastify is its plugins, which are just exported functions. These plugins are a core primitive of Fastify and are used to define the main app and register routes.

So okay. There was a few questions in the chat. What is the turn into fat models. If you are interfacing with a sequel to be. Do you write your SQL predict query? Um, I'm using type where am, but I ATT with a passion. I don't know how to get away from it. Yeah, I still can use a fatter and without models. Not sure if still an anti pattern.

So, um. The other question. So, you mean to have to keep using those objects the same and such without adding business logic? Yeah, look it's. Yes. So, I so whenever you are looking at this diagram. Okay. When you're structuring your application in different modules. What you want is that the boundaries between those modules are not those 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 you don't create super interdependent interlocks. Interdependencies between those main models, which make your process really hard to maintain long term. So, I will stay away from it and I will just use a few modules to do to interact with your SQL databases. My favorite one is called AT Database, it supports MySQL, Postgres, SQLite, a bunch of stuff, you can essentially do a wait to be query and pass your SQL. And you can even support the SQL injection protection, it's great. Another module like that is called NearForm. NearForm... NearForm-SQL? What's the name of the first one? It's hard to read your screen. OK, sorry, it's AT Database. I'm just zooming in, sorry. I wanted to do something different, but I was stopped. So here you go. The first one, this is what I'm doing. This is one of the things I recommend. This is the other one. Kinect is also good. So if you want to use Kinect, it's also a good module. It's very old. Prisma can be good or not good, depending on how you are using it. So you might be stuck with something bad there. So if you don't abuse it, Prisma can be good. But if you start abusing it, then you are a little bit in trouble. Okay. Hopefully this makes sense. Okay. 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. Okay. You see that how this would work or how these would work. Okay, this is how you do you do something like this and you get the data. Okay. And I really like this. This this thing, by the way. It's it's great.

So. Good. OK. So part of this it's OK, MP 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 am going to interact this is to explain a little bit the design philosophy of fastify. Fastify is a web framework 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, how 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 fasify 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 this is those plugins. And then those plugins are literally just functions that are received.


Implementing Context Dependency Injection System

Short description:

Implement the type of context dependency injection system we discussed. Use the decorate function to add properties to the fastify app. Test the app by creating a test app and injecting dependencies. It's fast and does not require compilation. Q&A: Euan asks about using the system in the app's execution context.

The fastify app has been now fastify. Implement the type of context depend easy or dump dependence injection system that we talked about. So if I want to expose something inside my fastify app, I 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, okay. I can also see show this to you. So in here you have we have fastify plug-ins and you have, oh, Mamoud. So we have our this is our our app. Okay. Look at what we are doing. We are instance. We have a main a main function here. And we have we have our main function which shows the we have register and we have the shared we have shared and the routes. Okay. Two plug-ins. Now. And those are. Sorry. And those are one is the declaring route 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 the routes, I could do curl localhost 3000 and we'll get a lower. And if I change in shared I see a low node main. Node Congress, I can, I need to restart this up. I could see this updated, okay. Note that if you are running our 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. Okay. So it's actually pretty, it's actually plenty of cool. There is no compilation, no 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. Okay. 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 NPM test is the configure, yeah, no. So NPX. ytest. Oh, yeah, it's not Congress is not. That's not shared, this should be word. So here you can see now is passing. So this is the test in up in VTEST 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 await main cost, and I actually prefer it, to be honest, E tier after app.close. And now you can do node test, domain test 2 and it's failing. Oh, expecting not define. So here now you do assert, from node assert. And here you do assert strict equal, 200, and then here you do a strict, deep or deep strict equal, deep strict equal actual. So response dot JSON, expected LO word. And now we have run our tests and you see it's, it's over there. And if we want, you see it, my test now, it's can just run it. I could even do test, reporter spec. And now it's even better. Okay. I.

Euan, you have a question. Uh, can you hear me? Yeah. Okay. Yeah. Uh, I was gonna ask, uh, I mean, the so I went to the, if I mean, did you think is a good idea to use it in the context of the app? I mean, not in testing context, but yeah. In execution context.

Using Fastify WebSocket in a Serverless Context

Short description:

You can use a cert for assertions. When using low-level libraries with raw queries, it's important to convince your teammates of the benefits. Mapping from objects to domain models is crucial. Use JavaScript objects and JSON strings for better results. Fastify WebSocket offers route-based routing and multiple WebSocket endpoints. It works well in a serverless context, especially on AWS Lambda. It is significantly faster than serverless HTTP and even faster than Express.

In execution context. Yeah. Assert. No, you can use a certain, whatever you want is fast. So you can just use a cert if you need that, you need to have an assertion on to very something you can just use a cert. It works just fine.

Oh, okay. Thank you so much. Yeah. That's great. Okay. So there is, there was a thing personally went back using low level libraries with raw queries, my SQL two in my case, how 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. Okay. What does it happen when your application use an ORM it hibernates. So that's my job. That's my job for them. Okay. 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, Nathalie, I hope it's not Elisa, is Elisa not Eliza. But if it's Eliza, please let me know. And I, I, in Italy in Italian, that's how it's pronounced. I assume you're talking about hibernate. I think it's the same problem. You need to map from your mobject to your domain model. Essentially. Yes. That's the core concept of it. You want to con, you want to, convert to 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 didn't get that, that data out, it's way better than anything else.

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. Oh, we can move a little bit. That's a little bit more light, it's getting darker. And I was doing that. And we actually built something around those lines. So yay, Salma's your co-worker. Yeah. We were 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 PubSub part of it. So basically you sum those two bits and it also, you can also bake it by radius and I 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, it's the GraphQL adapter for Fastify and 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 like looking at it strongly at 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 that it does routing also on the WebSocket endpoint so you can have multiple WebSocket endpoint registered in your app. Other frameworks do not offer that. You see that you can, 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 serverful? That is a nice adaptor. It works for, it works better than Express in a serverless environment or at least on AWS. So on AWS Lambda. We have only an AWS Lambda adaptor. So yes, in on AWS Lambda it was better. The on the rest is probably requires a probably 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. Okay, so it's significantly faster than serverless HTTP but and impressively faster, even from the official one for express. Note that there is a catch you can even get a completely remove with fastify.

Asynchronous Boot Logic and Fastify Routing

Short description:

You can implement an asynchronous boot logic pattern with plugins to avoid cold starts. Fastify's declarative routing model using a Radix prefix tree is more flexible and efficient than Express's array of regular expressions. Fastify Autoload simplifies routing with file system-based routing. Fastify automatically shuts down plugins in the reverse order they started for a graceful shutdown.

You can implement this asynchronous boot logic pattern with the plugins. If you define it as ESM, you can completely avoid the cold start by using provision concurrency. When you define your lambda and rely on the fact that there is an await in your entry point, your fastify application will boot, create the connection to your database, and perform any necessary tasks. After it's all done, everything will be started up, reducing the cold start close to zero.

My recommended project structure is to create route folders and directories that map the routes of your application. This helps keep your code organized and manageable. If you need behavior that is shared between routes, you can put it inside a plugin. Fastify Autoload is a useful tool that provides file system-based routing, allowing you to have multiple nested folders for easy routing. When you start your application, Fastify automatically shuts down all the plugins in the order they started, ensuring a graceful shutdown.

The key difference between Fastify and Express is the routing model. Fastify uses a declarative routing model where routes are assembled in a Radix prefix tree, making it more flexible and efficient compared to Express, which uses an array of regular expressions evaluated in order. Fastify's routing model also allows for metaprogramming on the routes, providing more flexibility and control.

Project Structure and Routing in Fastify

Short description:

We discussed the project structure and recommended organizing code into 12 routes folders that map the application's routes. Behavior shared between routes can be placed inside plugins. Fastify Autoload provides file system-based routing, allowing for easy routing. Fastify's declarative routing model, using a Radix prefix tree, is more flexible and efficient than Express's array of regular expressions. This enables metaprogramming on routes and simplifies tasks such as creating an open API definition and adding authorization checks.

We talked a little bit about the testing part. Okay. 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. Okay? Now you can, these make sense for Fastify app, but it can be very, you can adapt 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 routes.js file that is between a few thousand to 20 thousand lines of code. I don't know if you ever seen a routes.js file that is 20 thousand lines of code. I hope you haven't, but I did and it's not fun. Did you? Did you, somebody ever route.js file that is a monster of a file? What's your strategy to splitting that file.

Okay, my recommended project strategy is to have. To create 12 routes folder and use, actually, folders and directories and everything structured 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 plugin thing. So in. In here. And which segment is it? Mm hmm. Yeah, this is we cover this, so this is a simple app. OK, so you see we have our main file, OK, which uses yes, 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 a 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. In this simple app I could do no domain. 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, for example, add nested, something. good.js, and here I could just... copy this up and paste it down. Didn't copy. OK and then. here and I... OK. So now I can run it again. You see that it started good. If I can call localhost. But then if I do nested, good, nested something. I get my value. OK, and note that I defined my plug-in 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.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 the 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 inverse order on which they started. So that everything can be started down in a graceful setting, OK? So it's a nice, easy setup, OK? So, oh yeah, does it make sense? Cool. This kind of open ended question, obviously you're biased towards Fastify. But. Oh, yeah. But, like, what, but like 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. Well, it's it's it's Fastify is almost no over at compared to Node 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, they're out of just an array of regular expression evaluated them evaluated in order, which is. OK. 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 your routing, what your route structure at any given point. OK. Because your route 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 from doing any sort of metaprogramming on the routes such as creating an 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 harder to do. So yeah, essentially that's probably the second model apart from that the press is great. Like the study of node, so it's fine. Yeah. OK, cool. Thanks. Cool, right. OK. Cool. Not the stuff in here.

Remaining Time and Recording Availability

Short description:

We have limited time remaining for questions. The recording of this workshop will be available on the JS Nation website. There is an interesting article by Netflix about a memory leak caused by a wrong assumption about Express and the internal routes array. Please share the link. Thank you.

Not the stuff in here. OK. So how much time do we have? We have probably this was supposed to run one hour and and a half. Right. More or less. What time did you have? How much time have you got left, folks? Is anybody can keep going for another half an hour at least, if not more, there is I still have it's still six in my car or so. I'm personally OK for another 20 minutes, then I'm actually jumping on it. Yeah. OK. So. Yeah, pretty perfect. OK. So have you got any questions about this, about the about the about any of this stuff? I need to leave soon, and I wanted to ask where there will be the recording. Yes, there will be. 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? You will find the recording at in the JS Nation website. So you should have access to the JS Nation website. Sorry, not just to the GIT Nation website. So you will be able to join it to see it that way. OK. Good. Thank you very much on this occasion. Thank you, Udio. Yeah. OK, oh, interesting. So there is a discussion from Arya and there is so I'm sorry. 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. I tune bye bye.

Project Structure and JWT Authentication

Short description:

Regarding project structure, microservices are popular, especially for authentication using JWT. Fastify JWT and JWKS modules can be used to set up and verify JWT tokens. Instead of creating a separate microservice for each step, you can verify the token at the beginning of the request, discard it, and move relevant information to HTTP headers. This allows for validation at the edge and avoids unnecessary validation within the microservices.

Then there are a few questions. OK. Regarding the project structure, this plate one large up into several micro services, I am winning, so the approach to the authentication part I rely on a kind of DDT, zero flow, and most of the logic is duplicating the 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 the same logic and we ended up reusing it in an internal module. I will probably need to expose it and so that you can just use the thing. So most of this 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 JWKS and in something like of zero, you can essentially are at a point of. You can probably you can point out a richer situation where it's completely that's almost, you know, that requires very little work to accept the 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 relevant information on HTTP headers. And in that way, because you can validate it at the top, like if the microservices is not exposed to the public, you can skip that validation afterwards and just do the validation at the edge and then internally you're good. So yeah, that would be another option.

Express Article and Plugin Contracts

Short description:

Here is a link to an article about why you should not use Express. There is a way to define a contract for a plugin, specifying dependencies and required decorators. I recommend checking out the 'But' framework for more features and easy implementation. Thank you all for joining the workshop. If you're interested, we can continue with a demo. To start, use 'npm create platform attic' to create a basic application. Install the necessary dependencies, run migrations, and generate types.

Okay, here is the link from the Netflix. Whoa! Okay, this is old stuff. It's still true, this is express. Okay, look, look, this is express. You see this tower? How many cold 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, yeah, 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, like how to define what decorations it requires for correct work? Yes. Yes, there is. So if especially if you use, so there is. So in here, for example, you have this greeting. And here you have this 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 auto load. 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. To where is it? So yes, you see dependencies. You can even say that you want certain decorators being present. OK, and so. 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, Mahmud and thank you Kodor and herb. And yay. Amazing, folks, I hope you you enjoyed it, OK? Did you enjoyed 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 But from attic, it allows you to do most of what I showed and and everything very easily yourself in the code. So it's it's great. Just a small pitch and and so on, and I don't have time for the demo now, but it will be fun. Cool folks. Thank you for for watching for being here and I'll in order, if more people are interested in part of my and give you a little bit of a demo, otherwise I can. We can all part ways what would you prefer? That tennis numbers dropping so it's it's. Personally, I'm curious about what for magic so I can keep going. Okay, 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 and. To stay on, you can see owner job, 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 the basic first platform I think application can do some p.m. create platform attic. And at latest Xian is. Nice job, thank you. And we can go ahead and start playing around with our custom network option again by. Once you have my app. N. P. M. create platform attic and at latest. And we want to create D. B. because that's the most complete thing. And you want some default migration default plugin and you want to use typed like TypeScript TypeScript. You like TypeScript, okay, so we are doing Test Script. I'm coding TypeScript, so everything can go wrong now, so now it's installing NPM. We run the migrations. Generate the types.

Deploying the System and Generating Routes

Short description:

We can deploy our system using the NPX PLT DB starts command. It automatically generates routes for us, such as movies with GET, POST, PUT, and DELETE methods. We can add movies using this system and even have GraphQL support. The configuration file controls all of these features. We can customize the graphical schema and extend it as needed. Folders can be used to organize routes and plugins, allowing for easy loading and customization. However, refactoring may require a restart. Note that the application is fully typed and works correctly with TypeScript.

We are we 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 SQL database here. By default, you can configure it to be Postgres or whatever you want. To be honest, we have a platformatic dot DB dot 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 stuff in here and you can you get out of completion, essentially via via 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? I can just do NPX PLT DB starts to start my system. Oh, and PMI platformatic. Need to add this thing. And here we go. These are started, oh, sorry, I am not in the right folder, that's why it didn't start. So my app, OK. 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, hi Mark, we have automatically generated some routes for us, so we have movies, get post put and get put delete on everything. So it's actually very cool. Very nice. And we can, you know, for example, we can use this 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 of that. Does it make sense? So cool stuff about it is that you can we even have GraphQL support. So here you can just do. Title. So we we can save a movie called The Wizard of Oz and we have mutations and then we have the. Movies. Title, for example. And all of these was automatically it was automatically under for us like there is no actual code that does this. Okay all of these is controlled by the configuration file. What's cool though is that I could add more stuff into my into my. Hello so into my into my application so what I can do is for example at the low route and now I can curl localhost 3042 low and get to the word. Know that I didn't have to restart everything get compiled automatically and so on hooked up correctly and if I go to my swagger. Okay, I can refresh and now I also have a low at the bottom. So it automatically gets everything done and I can. For example, I could add a title trout so I can just want to get all the titles of my movies. And I could do cost. This is movies. I wait up platformatic. The entities okay movie. Find. And then I could do a return moving movie title not that all of this is type scripts. 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. And this is the benefit of the true 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. As we did before, so it's just that the basic stuff just have a plugin.js file. But all of you can specify a folder in here so we can try to do that and lets say let me do routes and here we are moving. We are changing this and calling paths routes. And we can move this into routes. Okay. Now this failed badly so I probably need to restart everything. Because doing this kind of refactoring is not really liked by the logic. But. Ouch! Ah yeah, it doesn't work because routes I need to load dot dot global. This gives me the types of my application.

Using Fastify Express and Platformatic

Short description:

The types of the movies and everything are the same as before. The code is compiled automatically in the DCS folder. When it comes to using the AWS SDK or local stack, I prefer to use cloud resources for development against the real thing. Mocking is not practical in most cases, and it doesn't make much sense from my point of view. Fastify Express is an adapter that allows you to mount an Express application within a Fastify application. It's good for migrating things and has been used for big migrations. Platformatic is a production-ready out-of-the-box Fastify experience that allows you to create a service without the automatic API. It provides environment variable substitution and is easy to run with the MPX platformatic command.

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. Now that all of this is getting compiled automatically in the DCS folder. And yeah, that's a 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. I bet that you still around? Yes, OK, sorry for going back to the topic, but do you use it do a wide marking the WS SDK is it local stack or something else? If yes, what do you do? Do you use it local stack or something else? If yes, what do you do when you're using something local stack does 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 AWS 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. 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. True mocking means testing something is true. That seems true equals true. It doesn't make much sense from my point of view. And Kate put it very stupidly so you need I need to so you need actually Internet to run your test right because you're going to of course, but that's the price you pay to use AWS. So you know sorry, sorry, sorry. No sorry about it. Yeah, it's it's it's very nice when did to be sure that they understand understood you correctly thinking so. Yeah. It's yep. Yeah, something that it's fun here. So any tips from again from Express to fastify is by using fastify express. So yes, so this is 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. used to register your module. You just have a full middleware system deployed. 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. There are limitations, but it's rock solid. I don't think it's slowing down performance. The Express 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. It will be as fast as Express for the old things and fast as Fastify for the new things. If you get what I mean. Yay, bye bye Nick, your nick is gone. Cool. A question about platformatic. Yeah. So what do you think? When should we use platformatic instead of PerFestify? So it's. To be honest, if you want to use. So. You 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 platformatic if you want or just make first if I in we've wrote OK that as a main file. Structured in this way, OK? And you have this oh sorry no? OK, you have a main file structuring 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 go. Simple up to. And see this simple up to OK, and now what you can do in simple up to it's NPM create platformatic. At latest OK. So platformatic is a production ready out of the box fast. If I experience so if you don't want the automatic API created for you, you can just build platformatic service and if you pick platformatic service you. Want to run? Oh yeah, this is not needed, OK? Yeah, just put it but it's not needed, OK? OK so. I don't want this config. OK. And here. OK, we have the routes and we have the plugin 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 environment variable substitution, so these are just environment substitutions and it's great. So in order to run this I can just MPX platformatic.

Platformatic Service Features

Short description:

The Platformatic service has no limitations and comes with many features out of the box, such as logging, graceful shutdown, and automatic reloading. It provides a lot of functionality that you would otherwise need to implement yourself. If you want to explore more, visit the website, join the Fastify Discord server, or connect with me on the Platformatic Discord server.

Service start. And. Look this is this works exactly as it was working. Oh no, it's different port so is work exactly as it was working before. So I actually had to do literally nothing. To change system. So basically it has no limitations compared to first right? Nope, you can use Platt formatic 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. The falls and stuff and it just works.

And you can just as you said, you can you can see the error is just. Yes, we're fine, OK so it's. You can. Hello, git Nation. And if you do you see this is automatically reloading everything you would expect from good Dex now, it adds a few more things here so you could. For example, you you 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 shot shutdown. It provides a lot of stuff that automatically you wouldn't. You you will need to implement yourself, OK, so it's. That's the difference between the two. OK. And if you want to spell traumatic DB, you get all that 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 resolve few resources for fast if I. If you want to to reach it, Why is of course the website OK. And there's a bunch of stuff here. We have a discord server so you can go and get up and you're redoing the website. So if you get if you want to join this this chat here and it goes into our discard server. This is the fastify discord and you could just join that OK, and we also have a platformatic this code server that you can 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.

Watch more workshops on topic

Node Congress 2023Node Congress 2023
63 min
0 to Auth in an Hour Using NodeJS SDK
Passwordless authentication may seem complex, but it is simple to add it to any app using the right tool.
We will enhance a full-stack JS application (Node.JS backend + React frontend) to authenticate users with OAuth (social login) and One Time Passwords (email), including:- User authentication - Managing user interactions, returning session / refresh JWTs- Session management and validation - Storing the session for subsequent client requests, validating / refreshing sessions
At the end of the workshop, we will also touch on another approach to code authentication using frontend Descope Flows (drag-and-drop workflows), while keeping only session validation in the backend. With this, we will also show how easy it is to enable biometrics and other passwordless authentication methods.
Table of contents- A quick intro to core authentication concepts- Coding- Why passwordless matters
Prerequisites- IDE for your choice- Node 18 or higher
JSNation 2023JSNation 2023
104 min
Build and Deploy a Backend With Fastify & Platformatic
Platformatic allows you to rapidly develop GraphQL and REST APIs with minimal effort. The best part is that it also allows you to unleash the full potential of Node.js and Fastify whenever you need to. You can fully customise a Platformatic application by writing your own additional features and plugins. In the workshop, we’ll cover both our Open Source modules and our Cloud offering:- Platformatic OSS (open-source software) — Tools and libraries for rapidly building robust applications with Node.js ( Platformatic Cloud (currently in beta) — Our hosting platform that includes features such as preview apps, built-in metrics and integration with your Git flow ( 
In this workshop you'll learn how to develop APIs with Fastify and deploy them to the Platformatic Cloud.
JSNation Live 2021JSNation Live 2021
156 min
Building a Hyper Fast Web Server with Deno
Deno 1.9 introduced a new web server API that takes advantage of Hyper, a fast and correct HTTP implementation for Rust. Using this API instead of the std/http implementation increases performance and provides support for HTTP2. In this workshop, learn how to create a web server utilizing Hyper under the hood and boost the performance for your web apps.
React Summit 2022React Summit 2022
164 min
GraphQL - From Zero to Hero in 3 hours
How to build a fullstack GraphQL application (Postgres + NestJs + React) in the shortest time possible.
All beginnings are hard. Even harder than choosing the technology is often developing a suitable architecture. Especially when it comes to GraphQL.
In this workshop, you will get a variety of best practices that you would normally have to work through over a number of projects - all in just three hours.
If you've always wanted to participate in a hackathon to get something up and running in the shortest amount of time - then take an active part in this workshop, and participate in the thought processes of the trainer.
TestJS Summit 2023TestJS Summit 2023
78 min
Mastering Node.js Test Runner
Node.js test runner is modern, fast, and doesn't require additional libraries, but understanding and using it well can be tricky. You will learn how to use Node.js test runner to its full potential. We'll show you how it compares to other tools, how to set it up, and how to run your tests effectively. During the workshop, we'll do exercises to help you get comfortable with filtering, using native assertions, running tests in parallel, using CLI, and more. We'll also talk about working with TypeScript, making custom reports, and code coverage.

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

Node Congress 2022Node Congress 2022
26 min
It's a Jungle Out There: What's Really Going on Inside Your Node_Modules Folder
Do you know what’s really going on in your node_modules folder? Software supply chain attacks have exploded over the past 12 months and they’re only accelerating in 2022 and beyond. We’ll dive into examples of recent supply chain attacks and what concrete steps you can take to protect your team from this emerging threat.
You can check the slides for Feross' talk here.
Node Congress 2022Node Congress 2022
34 min
Out of the Box Node.js Diagnostics
In the early years of Node.js, diagnostics and debugging were considerable pain points. Modern versions of Node have improved considerably in these areas. Features like async stack traces, heap snapshots, and CPU profiling no longer require third party modules or modifications to application source code. This talk explores the various diagnostic features that have recently been built into Node.
You can check the slides for Colin's talk here. 
JSNation 2023JSNation 2023
22 min
ESM Loaders: Enhancing Module Loading in Node.js
Native ESM support for Node.js was a chance for the Node.js project to release official support for enhancing the module loading experience, to enable use cases such as on the fly transpilation, module stubbing, support for loading modules from HTTP, and monitoring.
While CommonJS has support for all this, it was never officially supported and was done by hacking into the Node.js runtime code. ESM has fixed all this. We will look at the architecture of ESM loading in Node.js, and discuss the loader API that supports enhancing it. We will also look into advanced features such as loader chaining and off thread execution.
JSNation Live 2021JSNation Live 2021
19 min
Multithreaded Logging with Pino
Almost every developer thinks that adding one more log line would not decrease the performance of their server... until logging becomes the biggest bottleneck for their systems! We created one of the fastest JSON loggers for Node.js: pino. One of our key decisions was to remove all "transport" to another process (or infrastructure): it reduced both CPU and memory consumption, removing any bottleneck from logging. However, this created friction and lowered the developer experience of using Pino and in-process transports is the most asked feature our user.In the upcoming version 7, we will solve this problem and increase throughput at the same time: we are introducing pino.transport() to start a worker thread that you can use to transfer your logs safely to other destinations, without sacrificing neither performance nor the developer experience.