Dependency Injection Made Easy for VueJS and Vuex with TypeScript
I have to admit it (and this is my personal point of view). Dependency Injection is not popular in the VueJS Ecosystem and, dare I say, in the JS ecosystem. People want to get stuff done quickly and nicely and that is absolutely fine but I feel that most of the SOLID and OOP principles are lost in the JS ecosystem but let’s talk about that in another post 😛
To understand Dependency Injection and its benefits, I absolutely recommend you to read this post first:
Dependency Injection was kind of hard to implement in a VueJS application since it required to do a couple of tweaks to the codebase. One of the DI (Dependency Injection) solutions for JS and TS out there is InversifyJS which is my favorite DI container but still hard to use with VueJS. Fortunately, that is no more and one person give us, which is to me, the solution to implementing DI in our VueJS Apps.
In this guide/practice, I want you to learn about how to implement Dependency Injection easily into your VueJS project with TypeScript using the library Inversify Props
Wrapper of Inversify to inject your dependencies in the components, made with TypeScript and compatible with Vue, React…
If you want to take a look into the complete example, you can go directly to this link!
VueJS with Vuex and TypeScript example to use Dependency Injection — jefer590/vuejsdepencyinjectionexample
What do I need?
- Install the latest version of yarn and Vue CLI
- An editor compatible with TypeScript (I love WebStorm for this)
- Clone the base repo for the exercise.
What are we building?
A super simple app that:
- First, will use a service that connects to https://api.kanye.rest through a component
- Then, the same behaviour but through a Vuex Module
Clone the next repo in your machine:
VueJS with Vuex and TypeScript example to use Dependency Injection - jefer590/vuejsdepencyinjectionexample
and then instal the dependencies using
$ yarn install
Creating the Service
/src folder, create a new folder folder called
services and inside the new folder, create a folder called
/servicesroot will be used to expose easily the Service Interfaces
/services/implwill be used to add the concrete implementations of our interfaces/services
/services folder create the file
IKanyeWestService.ts with this shape:
We return a promise since we will retrieve the quote from an external service.
It’s time to do the concrete implementation! Create a file called
KanyeWestService.ts in the
/services/impl folder. It should have this shape:
In this class service, what basically does is a wrapper of our axios HTTP call which will return the object data that corresponds to the quote. You might ask:
Why didn’t you do the http request inside the required component?
The answer is easy! It’s easier to maintain. By creating a decoupled service from our codebase and injecting it in the whole codebase, let us have our code in only and only one place. If for some reason the library changes in the future (maybe they change from HTTP to Protobufs) we need to only do the change in one place and will take effect basically in every part where the dependency is injected. We will be using the abstraction over the concrete implementation.
The Dependency Container
Create the Container
/src folder, create a file called
app.container.ts which will be the file where we are going to register all of the dependencies with its abstractions. the file should look like this:
Let’s bind our dependencies!
In the same file, import
inversify-props and both files that we did for the
KanyeWest service. Inside of the function we will use
container to register our service in this way:
To this to take effect in our codebase, in the
main.ts you will import the function from
app.container and use it inside the
Injecting a service into a VueJS Component
Our dependency container ir ready! Now it’s time to use it inside a Vue Component.
Go to to
/App.vue and start by importing the
IKanyeWestService and then a decorator from
And to inject this service, just simply add this piece of code in your Component class:
and… That’s it! It literally take a few lines of code to use a dependency by using DI with this library. The only things left are:
- Fetch the quote when you click the button.
- Fetch the quote when the component is loaded.
To tackle both cases, in the method
getQuote use the injected dependency and set the quote text into the data which is called
and to execute this when the component is loaded, just put it in the
mounted hook method. At the end, your script should look like this:
Now that we have a fully functional component with an injected dependency, we can do the same for Vuex using
Use Vuex in App.vue
Let’s first remove the content of the method
getQuote, remove the injected dependency from the class and then remove the imports associated to the injected dependency.
Now import the Action and Getter decorators from
vuex-class and use Getter above the
quote data to bind it to the
quote getter in the store:
For the Action, since we are binding functions, we will need to match the function type in the next way:
And use it inside the
getQuote method. The component script should look like this:
DI inside a Vuex class module
The last part of this guide is doing DI in a Vuex module using
inversify-props which is as easy as the component approach and, dare I say, the same code.
/store/modules/KanyeWest.ts and import the same inject and Interface service that we used in the component into this file
And using the same approach as the component, Inject the dependency:
and that’s pretty much it! Let’s us it in our
And voila! Our project is finished and using DI!
And that’s it for today! I hope you learned a little bit about Dependency Injection on VueJS and TypeScript. Feedback is welcomed!