Easy dependency injection in Next.js

Поділитися
Вставка
  • Опубліковано 11 лис 2024

КОМЕНТАРІ • 44

  • @nikolovlazar
    @nikolovlazar  3 місяці тому +13

    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!

    • @NaniwaRocky
      @NaniwaRocky 3 місяці тому +1

      Looking forward to the 18th!

  • @WebDevCody
    @WebDevCody 3 місяці тому +3

    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.

    • @nikolovlazar
      @nikolovlazar  3 місяці тому

      Woah what a coincidence 😅 I'll check out your video right now. Curious to hear your thoughts in IoC containers.

    • @danialkhosravi6296
      @danialkhosravi6296 3 місяці тому

      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.

  • @joshiboshi6140
    @joshiboshi6140 3 місяці тому

    Absolute legend. Been trying to find a solution for this for years 🎉

  • @wiilamaral
    @wiilamaral 3 місяці тому

    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 🔥😉🧑🏽‍💻

  • @celsoernani3271
    @celsoernani3271 Місяць тому +1

    nice video !

  • @klvb-m
    @klvb-m 3 місяці тому +1

    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
      @nikolovlazar  3 місяці тому

      Sounds like you have misconfigured tsconfig. Here's mine for comparison: gist.github.com/nikolovlazar/31d39910035add6994aa242638717382

    • @klvb-m
      @klvb-m 3 місяці тому

      @@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?

    • @nikolovlazar
      @nikolovlazar  3 місяці тому +1

      @@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.

  • @javiervazquezfernandez1872
    @javiervazquezfernandez1872 3 місяці тому +1

    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

    • @nikolovlazar
      @nikolovlazar  3 місяці тому +1

      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!

  • @jasonsuarez6439
    @jasonsuarez6439 Місяць тому

    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.

    • @nikolovlazar
      @nikolovlazar  Місяць тому

      I tried adding it in the root layout, but it kept breaking the build process.

  • @wingy3181
    @wingy3181 Місяць тому

    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!!

    • @nikolovlazar
      @nikolovlazar  Місяць тому

      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.

    • @wingy3181
      @wingy3181 Місяць тому +1

      @@nikolovlazar good point regarding difference between hosting options.. keep up the great work

  • @isaacjon
    @isaacjon 3 місяці тому +5

    I can't understand what's going on, but it sounds cool

    • @nikolovlazar
      @nikolovlazar  3 місяці тому +1

      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!

  • @lawliet.fortyfour
    @lawliet.fortyfour 15 днів тому

    This video is awesome man! can you share to use the git repository of this? thanks

  • @dmaksimov
    @dmaksimov 3 місяці тому

    Great solution! Been trying to find something for a while.
    Do you have this example in a github repo somewhere?

    • @nikolovlazar
      @nikolovlazar  3 місяці тому

      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.

  • @Its-InderjeetSinghGill
    @Its-InderjeetSinghGill 3 місяці тому

    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.

    • @nikolovlazar
      @nikolovlazar  3 місяці тому

      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?

    • @Its-InderjeetSinghGill
      @Its-InderjeetSinghGill 3 місяці тому

      @@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.

    • @Its-InderjeetSinghGill
      @Its-InderjeetSinghGill 3 місяці тому

      @@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 🫡.

    • @nikolovlazar
      @nikolovlazar  3 місяці тому

      @@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.

    • @Its-InderjeetSinghGill
      @Its-InderjeetSinghGill 3 місяці тому

      @@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.

  • @MarosiMate-sq2wm
    @MarosiMate-sq2wm Місяць тому

    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.

    • @nikolovlazar
      @nikolovlazar  Місяць тому

      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.

  • @Deus-lo-Vuilt
    @Deus-lo-Vuilt 3 місяці тому

    Thanks ❤

  • @kamalkamals
    @kamalkamals 3 місяці тому

    why not using typedi package ?

    • @nikolovlazar
      @nikolovlazar  3 місяці тому

      Haven't used that one before, but I guess it should work just fine.

    • @kamalkamals
      @kamalkamals 3 місяці тому

      @@nikolovlazar ok sure, just check it in ur free time it s good package too

  • @xmarkclx
    @xmarkclx 3 місяці тому

    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?

    • @nikolovlazar
      @nikolovlazar  3 місяці тому +1

      Hey! This is for the backend part of Next.js, so we can't use the Context API in that case.

  • @kashnigahbaruda
    @kashnigahbaruda 3 місяці тому +1

    At some point people will realise you might as well use a good language like DOTNET

    • @nikolovlazar
      @nikolovlazar  3 місяці тому +1

      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 😀

  • @Famouzi
    @Famouzi 3 місяці тому +1

    Is this overengineered or am I lack of context? I have no idea whats the reason for all of this stuff :D

    • @nikolovlazar
      @nikolovlazar  3 місяці тому

      Hey sorry I added more context in the pinned comment at the top. Hope that helps.