Importing from node_modules in Ember

April 30, 2018

As of Ember CLI 2.15, we can import files from the node_modules directory using app.import() in ember-cli-build.js. How you call app.import() depends on the module system of the file that you are trying to import.

Importing as Global Variable(s)

Let’s say you have the following file:

// node_modules/acme/global.js
const something = {
  some: 'key'
};

const somethingElse = 5;

We can import it in our ember-cli-build.js file as such:

app.import('node_modules/acme/global.js');

In our application, we’ll have global variables something and somethingElse.

Importing an AMD Module

Let’s say we have the following file containing an AMD module:

// node_modules/acme/amd.js
define(function() {
  return {
    some: 'key'
  };
});

In ember-cli-build.js, we can import it as follows:

app.import('node_modules/acme/amd.js', {
  using: [
    { transformation: 'amd', as: 'acme' }
  ]
});

Then in our application, we can import acme as an ES6 module:

import acme from 'acme';

Out of the box, I believe amd is the only option for transformation at the time of this writing.

Importing a CommonJS Module

We can also import CommonJS modules using app.import() in our ember-cli-build.js file.

Let’s say we have the following file containing a CommonJS module:

// node_modules/acme/common.js
module.exports = {
  some: 'key'
};

In order to import CommonJS modules, we need to install ember-cli-cjs-transform. Note that this addon requires Ember CLI 2.16.

ember install ember-cli-cjs-transform

Now we can import it by specifying cjs as the value for transformation:

app.import('node_modules/acme/common.js', {
  using: [
    { transformation: 'cjs', as: 'acme' }
  ]
});

Then in our application, we can import acme as an ES6 module:

import acme from 'acme';

Importing Only for Tests

We can also import a Node module only for our tests so that it doesn’t get bundled in our production build. For example, let’s import the testdouble library:

npm install [email protected] --save-dev

Modify ember-cli-build.js as follows:

app.import('node_modules/testdouble/dist/testdouble.js', {
  using: [
    { transformation: 'cjs', as: 'testdouble' }
  ],
  type: 'test'
});

Testdouble also uses CommonJS. Here we’ve added type: test. Now in our test files, we can import testdouble as an ES6 module as follows:

import td from 'testdouble';

Conclusion

Recently I was able to change the importing of a handful of npm libraries from using ember-browserify to one of the approaches above in an Ember CLI 3.1 app. I think all of the approaches above work as of Ember CLI 2.15. Please reach out if I am wrong and I will update this post.

Disclaimer: Any viewpoints and opinions expressed in this article are those of David Tang and do not reflect those of my employer or any of my colleagues.