Taming the Imports

Introducing explicit imports without needless confusion

Thursday, Jul 28th, 2016

Mixmax is a communications platform that brings professional communication & email into the 21st century.

Performance is critical to every web application, and something we care deeply about at Mixmax. That's why we invest in performance best-practices, such as limiting the size of the Javascript that we serve for our application. We use a tool called rollup.js, which performs code "tree-shaking" at build-time. Tree-shaking, in contrast to dead code removal, uses explicit imports to only include what you use in the resulting code bundle.

When we adopted Rollup, we were happily forced to adopt ES6 imports. However, referencing specific modules threatened to become a relative-pathing nightmare. Our codebase lives in a directory structure which includes subdirectories for things like views and models, and has grown pretty deep, so we have to use paths like:

import UserModel from '../../../../../../../models/user';

However, some tools like Babel have plugins that support an absolute-style import, where the absolute path refers to the root of the project. This would reduce our relative import, above, into simply:

import UserModel from '/models/user';

We couldn’t just use Babel's plugin, because rollup.js needs to resolve the modules and shake the tree before Babel runs, so we wrote our own plugin for rollup that supports importing from the root of the project. Cheers!

README

Add the ability to import modules by the root path, like babel-root-slash-import.

// import a module relative to a specified root directory
import UserModel from '/models/user';

// illustrative - if we were in /views/user, we can reference a model's module
// using an absolute path from the root of the project, rather than relative to
// the current module
class UserView {
  // ...
}

Install

$ npm install --save-dev rollup-plugin-root-import

Usage

import {rollup} from 'rollup';
import rootImport from 'rollup-plugin-root-import';

rollup({
  entry: 'client/src/main.js',
  plugins: [
    rootImport({
      // Will first look in client/src/* and then common/src/*
      root: 'common/src',
      useEntry: 'prepend',

      // If we don't find the file verbatim, try adding these extensions
      extensions: '.js'
    })
  ]
});

API

rootImport([options])

Creates a rollup plugin to resolve absolute-pathed imports relative to the project's entry or specified root directory/ies.

Options:

  • root an optional string or ordered array of strings, which represent the roots from which to try and resolve imports.
  • useEntry if provided, should be either 'prepend' or 'append', where each signify that the directory containing the entry should be prepended or appended to the array of roots, respectively. By default, if root is provided and useEntry is not provided, the directory of the entry module will not be used to resolve absolute-pathed imports.
  • extensions, if provided, specifies a string or ordered array of strings, each of which represents an extension to append to the resolved file if the import isn't found verbatim.