I realize I should've add more context at the beginning of this video. Inversify helps you achieve architectures that require inversion of control, like Clean Architecture. This is part of my live stream series in which I tried implementing my own solution to this (a service locator), but it turned out it's more complex and not a good idea to maintain that part as well. So, inversify took care of that. Inversify lets you register different implementations of a service or simply a class under the same interface (or Symbol) at runtime, which you can later use in your app without needing to know which implementation got registered. That means you can write a mock implementation of your database repositories for unit testing, because you don't want to spin up a database, or you don't want to hit a paid API, or you don't have access to a certain functionality during testing. That also means you can have different implementations of your services based on the logged in user. If your app needs to do different things for enterprise / high paying users, you can split up that logic into different services and register the correct one the moment you get the user's session. This library is not for simpler Next.js apps. Clean Architecture is basically a discipline, a set of rules and principles that help you write testable and more maintainable apps. It is definitely an overkill for simpler apps, but a necessity for larger ones. Even if you don't explicitly use Clean Architecture, you'll end up coming up with something similar that solves all the issues you'll be faced with as your app grows. In order to achieve clean architecture, you need an inversion of control mechanism like inversify. I have a video on explaining Clean Architecture coming up on Thursday (18 July), so make sure to check that out as well. Hope this gives you all the context for this video. If you want to see more content like this, please give this video a like and subscribe to my channel. Thanks for watching!
I swear I didn’t watch this video before I published mine on my channel. Great video I have my own reservations about inversion of control containers but I think if that’s what you want I think inversify does a good job doing it.
Thank you both 🙏 Having had experience with IoC in dotnet core, the solutions in TS/JS leave a lot to be desired syntax wise, especially when you mix Class based and Function based style of organising/modularsing code. But great to see these patterns being discussed in the JS/TS ecosystem.
Great video! Congratulations, I've been searching for something like this for my Javascript projects. Like we have in Kotlin with Koin. I didn't know Inversify, keep up with the content! Subscribed 🔥😉🧑🏽💻
I’ve been trying to solve the issue between Next and reflect-metadata for the longest while, I was happy to hear you resolved it for yourself. I just tried replicating what you did but I’m getting a TypeError: Native module not found: reflect-metadata. This is after running npm run dev
@@nikolovlazar Hmm, our configs are identical - that’s very odd. Based on what I see in the error stack it doesn’t seem to like reflect-metadata being used within the edge runtime. I happened to try bundling with turbopack and that seemed to address the issue - maybe it’s smarter about not bundling certain pieces of code within that runtime?
Hello Lazar! I think you will like diod - dependency injection on demand, it is done with the clean architecture necesities in mind and it uses decorators to inject the dependencies
I just took a look at this. It's definitely interesting, but I also have some thoughts about it: I like the concept of not mixing DI within your application/domain layer, but in order to achieve that you'd have to register your use cases as services, and that could become too much. I already have 15 use cases in my (semi-refactored) simple CRUD app, and I keep them as plain functions. In order to achieve the "no DI in application layer", I'd have to refactor them to Classes, use the @Service decorator (still depending on DI directly with this btw), and register all of them in the container config file. I like that it only uses one decorator (@Service) and no constructor injection decorators. It looks like it's much simpler to use than Inversify. If I understood correctly, it achieves that through constructor injection, which forces you to use Classes for everything. I like that it uses abstract classes than interfaces for the services and repos. You can simplify the implementations a bit with abstract classes by defining shared properties and even methods, so the implementations won't need to. This is not a "major" benefit - it's more of a "nice-to-have". Definitely a fan of the "2kb minified" aspect of it! To be fair, I haven't actually tried this library, I just read through its documentation, but these are the things that I can say about it so far. Thank you for sharing it with me!
Hey, thanks for the great content. For the reflect-metadata part, have you tried the root layout? Working with Tsyringe in the past I managed to make it work by importing it in the root layout.
just curious, how does the inversify DI container get initialised in the nextjs app? I noticed the initializeContainer method within the `container.ts` file that exports getInjection and ApplicationContainer..but i didn't find any usage of ApplicationContainer...so i'm assuming it's when getInjection gets called which means it get's loaded by the first import usage of getInjection? and then any subsequent getInjection may also repeat tthe ApplicationContainer.load methods of inversify? (I'm looking at the source code from your clean code architecture) btw great videos!!
Thanks! Yeah the initialize method gets executed when the getInjection gets called. For serverless node environment you’d want to initialize the container every time because it’s serverless. If you’re on a long-running node server you can conditionally initialize based on the container value.
Thanks! There's no repo just yet. I plan on making a "Clean Architecture in Next.js" course that you can follow along, and this will be part of it. Along with the course I'll also publish a github repo.
Hi, I've been following your stream since episode 1 and I wanted to implement this in my own side project. I was trying to add reflect-metadata in the next config but I am having some issues with types. I am not getting types in the config parameter also where did the new webpack come from? I am confused.
What do you mean by “the new webpack”? Next.js allows you to override the default webpack config: nextjs.org/docs/app/api-reference/next-config-js/webpack Are you not getting the types inside next.js config? Also, did you try my approach? Does it work?
@@nikolovlazar Thanks for the quick reply, I was talking "new webpack.BannerPlugin". I did not find any import for this package in your next config in your video, also at webpack: (config, { isServer }) the config is typed as any so I am getting type errors when I try config.plugins.push because of course it is typed as any. I searched this issue on next js docs but found no solution. Maybe I am missing something here.
@@nikolovlazar Update: I managed to get this working by installing webpack (as dependency) and importing inside next config, for the type issue I imported webpack configuration type from the webpack but had to use in JsDoc since we can not use type imports in js or mjs files. Please let me know if I am doing something wrong here or if there is a better way to implement this, by the way thanks for making this valuable content on UA-cam 🫡.
@@Its-InderjeetSinghGill I got the types the same way. it's an mjs file with a jsdoc @type tag above it. Also yeah, I forgot to mention it but you do need to install webpack as a dependency in order to pull in the BannerPlugin.
What is the use for doing this in Next.js? Isn't Next supposed to abstract away complexity? If OOP is the key, I would just use PHP with Symfony or Laravel.
It's just a tool that solves a specific problem. You definitely don't need to implement DI if you application doesn't have a need for it, but it's good to know that such a thing exists for when you need to.
Hi Lazar! Why not just use a React Context API "DependencyContext" as a dependency injection container, wouldn't that be simpler than using classes and Inversify?
It's definitely more straight forward with OOP languages like C# (my background is in .NET actually). But it's great that such a solution exists for the JavaScript ecosystem. Sometimes you can't choose the language, and if that's JavaScript, this will still have you covered 😀
I realize I should've add more context at the beginning of this video. Inversify helps you achieve architectures that require inversion of control, like Clean Architecture. This is part of my live stream series in which I tried implementing my own solution to this (a service locator), but it turned out it's more complex and not a good idea to maintain that part as well. So, inversify took care of that.
Inversify lets you register different implementations of a service or simply a class under the same interface (or Symbol) at runtime, which you can later use in your app without needing to know which implementation got registered. That means you can write a mock implementation of your database repositories for unit testing, because you don't want to spin up a database, or you don't want to hit a paid API, or you don't have access to a certain functionality during testing. That also means you can have different implementations of your services based on the logged in user. If your app needs to do different things for enterprise / high paying users, you can split up that logic into different services and register the correct one the moment you get the user's session.
This library is not for simpler Next.js apps. Clean Architecture is basically a discipline, a set of rules and principles that help you write testable and more maintainable apps. It is definitely an overkill for simpler apps, but a necessity for larger ones. Even if you don't explicitly use Clean Architecture, you'll end up coming up with something similar that solves all the issues you'll be faced with as your app grows. In order to achieve clean architecture, you need an inversion of control mechanism like inversify. I have a video on explaining Clean Architecture coming up on Thursday (18 July), so make sure to check that out as well. Hope this gives you all the context for this video.
If you want to see more content like this, please give this video a like and subscribe to my channel. Thanks for watching!
Looking forward to the 18th!
I swear I didn’t watch this video before I published mine on my channel. Great video I have my own reservations about inversion of control containers but I think if that’s what you want I think inversify does a good job doing it.
Woah what a coincidence 😅 I'll check out your video right now. Curious to hear your thoughts in IoC containers.
Thank you both 🙏
Having had experience with IoC in dotnet core, the solutions in TS/JS leave a lot to be desired syntax wise, especially when you mix Class based and Function based style of organising/modularsing code. But great to see these patterns being discussed in the JS/TS ecosystem.
Absolute legend. Been trying to find a solution for this for years 🎉
Great video! Congratulations, I've been searching for something like this for my Javascript projects. Like we have in Kotlin with Koin. I didn't know Inversify, keep up with the content! Subscribed 🔥😉🧑🏽💻
Thanks!
nice video !
I’ve been trying to solve the issue between Next and reflect-metadata for the longest while, I was happy to hear you resolved it for yourself. I just tried replicating what you did but I’m getting a TypeError: Native module not found: reflect-metadata. This is after running npm run dev
Sounds like you have misconfigured tsconfig. Here's mine for comparison: gist.github.com/nikolovlazar/31d39910035add6994aa242638717382
@@nikolovlazar Hmm, our configs are identical - that’s very odd. Based on what I see in the error stack it doesn’t seem to like reflect-metadata being used within the edge runtime.
I happened to try bundling with turbopack and that seemed to address the issue - maybe it’s smarter about not bundling certain pieces of code within that runtime?
@@klvb-m Great that you solved it. And thanks for the turbopack tip! I'll keep that in mind. Not sure how turbopack works to be honest.
Hello Lazar! I think you will like diod - dependency injection on demand, it is done with the clean architecture necesities in mind and it uses decorators to inject the dependencies
I just took a look at this. It's definitely interesting, but I also have some thoughts about it:
I like the concept of not mixing DI within your application/domain layer, but in order to achieve that you'd have to register your use cases as services, and that could become too much. I already have 15 use cases in my (semi-refactored) simple CRUD app, and I keep them as plain functions. In order to achieve the "no DI in application layer", I'd have to refactor them to Classes, use the @Service decorator (still depending on DI directly with this btw), and register all of them in the container config file.
I like that it only uses one decorator (@Service) and no constructor injection decorators. It looks like it's much simpler to use than Inversify. If I understood correctly, it achieves that through constructor injection, which forces you to use Classes for everything.
I like that it uses abstract classes than interfaces for the services and repos. You can simplify the implementations a bit with abstract classes by defining shared properties and even methods, so the implementations won't need to. This is not a "major" benefit - it's more of a "nice-to-have".
Definitely a fan of the "2kb minified" aspect of it!
To be fair, I haven't actually tried this library, I just read through its documentation, but these are the things that I can say about it so far. Thank you for sharing it with me!
Hey, thanks for the great content.
For the reflect-metadata part, have you tried the root layout?
Working with Tsyringe in the past I managed to make it work by importing it in the root layout.
I tried adding it in the root layout, but it kept breaking the build process.
just curious, how does the inversify DI container get initialised in the nextjs app? I noticed the initializeContainer method within the `container.ts` file that exports getInjection and ApplicationContainer..but i didn't find any usage of ApplicationContainer...so i'm assuming it's when getInjection gets called which means it get's loaded by the first import usage of getInjection? and then any subsequent getInjection may also repeat tthe ApplicationContainer.load methods of inversify? (I'm looking at the source code from your clean code architecture)
btw great videos!!
Thanks! Yeah the initialize method gets executed when the getInjection gets called. For serverless node environment you’d want to initialize the container every time because it’s serverless. If you’re on a long-running node server you can conditionally initialize based on the container value.
@@nikolovlazar good point regarding difference between hosting options.. keep up the great work
I can't understand what's going on, but it sounds cool
I wrote and pinned a comment at the top with more context as to what this is, why or when you might need it. Hope it helps!
This video is awesome man! can you share to use the git repository of this? thanks
Great solution! Been trying to find something for a while.
Do you have this example in a github repo somewhere?
Thanks! There's no repo just yet. I plan on making a "Clean Architecture in Next.js" course that you can follow along, and this will be part of it. Along with the course I'll also publish a github repo.
Hi, I've been following your stream since episode 1 and I wanted to implement this in my own side project. I was trying to add reflect-metadata in the next config but I am having some issues with types. I am not getting types in the config parameter also where did the new webpack come from? I am confused.
What do you mean by “the new webpack”? Next.js allows you to override the default webpack config: nextjs.org/docs/app/api-reference/next-config-js/webpack
Are you not getting the types inside next.js config? Also, did you try my approach? Does it work?
@@nikolovlazar Thanks for the quick reply, I was talking "new webpack.BannerPlugin". I did not find any import for this package in your next config in your video, also at webpack: (config, { isServer }) the config is typed as any so I am getting type errors when I try config.plugins.push because of course it is typed as any. I searched this issue on next js docs but found no solution. Maybe I am missing something here.
@@nikolovlazar Update: I managed to get this working by installing webpack (as dependency) and importing inside next config, for the type issue I imported webpack configuration type from the webpack but had to use in JsDoc since we can not use type imports in js or mjs files. Please let me know if I am doing something wrong here or if there is a better way to implement this, by the way thanks for making this valuable content on UA-cam 🫡.
@@Its-InderjeetSinghGill I got the types the same way. it's an mjs file with a jsdoc @type tag above it. Also yeah, I forgot to mention it but you do need to install webpack as a dependency in order to pull in the BannerPlugin.
@@nikolovlazar Yeah that’s what I thought, but I’m very happy with the overall architecture. Thanks for your kindness keep doing what you doing.
What is the use for doing this in Next.js? Isn't Next supposed to abstract away complexity? If OOP is the key, I would just use PHP with Symfony or Laravel.
It's just a tool that solves a specific problem. You definitely don't need to implement DI if you application doesn't have a need for it, but it's good to know that such a thing exists for when you need to.
Thanks ❤
why not using typedi package ?
Haven't used that one before, but I guess it should work just fine.
@@nikolovlazar ok sure, just check it in ur free time it s good package too
Hi Lazar!
Why not just use a React Context API "DependencyContext" as a dependency injection container, wouldn't that be simpler than using classes and Inversify?
Hey! This is for the backend part of Next.js, so we can't use the Context API in that case.
At some point people will realise you might as well use a good language like DOTNET
It's definitely more straight forward with OOP languages like C# (my background is in .NET actually). But it's great that such a solution exists for the JavaScript ecosystem. Sometimes you can't choose the language, and if that's JavaScript, this will still have you covered 😀
Is this overengineered or am I lack of context? I have no idea whats the reason for all of this stuff :D
Hey sorry I added more context in the pinned comment at the top. Hope that helps.