Importing from node_modules in Ember

Last reviewed on January 18, 2020

This post was written prior to ember-auto-import, which is now included when you generate a new Ember project. If you need to import a Node module, I recommend looking at that first before reading on.

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 testdouble@3.7.0 --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";

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.