7

Is it possible to inject dependencies into ES2015 modules like in other programming languages like C# or Java? If I import a module I create a hard dependency to it and can not change it later at runtime. For example I have following JavaScript code:

import Animal from './dog';

class Person {
  feedAnimal() {
    new Animal().feed();
  }
}

I am importing the dog module. But what if I want to change it to a cat? At the moment I have to modify line 1 by hand but in some situations I want it configurable from the outside so that under some conditions there should be a cat and under some other conditions it should be a cat. All that things that can be done with classical dependency injection.

I know there are some DI frameworks out there like Scatter, Electrolyte, Wire and so on but unfortunately most of them require some special syntax and are not made for ES2015 modules.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
LongFlick
  • 1,129
  • 1
  • 12
  • 21
  • 1
    How would you want dependency injection to work? You could do `class Person { constructor(Animal) { this.Animal = Animal; } feedAnimal() { new this.Animal().feed() } }`, but it sounds like you expect something more advanced. – lyschoening Aug 14 '15 at 13:17
  • I am not sure if [`require-inject`](https://www.npmjs.com/package/require-inject) supports that, but you might want to take a look. – thefourtheye Aug 14 '15 at 13:42
  • @lyschoening thank you but I want to change internal module dependencies like I would write an unit test. – LongFlick Aug 14 '15 at 14:52
  • @thefourtheye thank you but the thing is that I do *not* require anything. Requiering is a CommonJS related thing. I use the shiny new ES2015 import feature. – LongFlick Aug 14 '15 at 14:53
  • 1
    You could probably hijack the module loader one way or the other. Not that I recommend doing that. – Felix Kling Aug 14 '15 at 15:17

3 Answers3

2

You cannot dynamically define dependencies. See this question and its accepted answer:

Question: ES6 variable import name in node.js?

Answer: Not with the import statement. import and export are defined in such a way that they are statically analyzable, so they cannot depend on runtime information.

Community
  • 1
  • 1
sdgluck
  • 24,894
  • 8
  • 75
  • 90
  • Hmm ok. Too bad. Do you know any workaround or something like that for this? – LongFlick Aug 18 '15 at 06:27
  • A module loader like [SystemJS](https://github.com/systemjs/systemjs/blob/master/README.md) would allow what you want. – sdgluck Aug 18 '15 at 07:15
  • 2
    I ask myself how do the all write unit tests if I can't mock any dependencies in my module to test? – LongFlick Aug 18 '15 at 14:55
  • 1
    Mocking a dependency means replacing or altering the actual dependency without affecting the code that uses it, not altering the code that uses a dependency to use a different dependency. I hope that makes sense, please ask if you need clarification. – sdgluck Aug 19 '15 at 09:19
  • I know that. Because of this I created the question above ;-) – LongFlick Aug 20 '15 at 07:00
  • @sdgluck: I think OP is asking exactly for this kind of dependency-*injection*, from the outside, which does not need dynamic/variable import names. It just needs a mocking module name *resolver*. – Bergi Sep 09 '15 at 10:40
2

You can use inject-loader to achieve this if you are bundling with Webpack.

Hopefully this helps someone who stumbles upon this old post.

0

I moved over to SystemJS. With SystemJS you can make dynamic imports like System.import('foo').then(() => console.log('Loaded));

Another advantage is that System will be the new ECMAScript standard module loader system.

LongFlick
  • 1,129
  • 1
  • 12
  • 21