"Unexpected Token Export" error

When trying to utilise the ES2015 export/import statements (aka ES2015 module syntax) in Node.js we are presented with the "Unexpected Token Export" error. There's a reason why this error appears and in this article we'll investigate why this is happening.

Module syntax

There are multiple module syntaxes that we can use in JavaScript, which include the CommonJS module syntax, ES6 / ES2015 module syntax (and there are some others as well, for example AMD - Asynchronous Module Definition)/

So let's assume that you've just learnt how to use ES2015 and you've learnt about its module feature that uses export/import statements. Off you go and you try to create a new class (beacuse, hey, that's something else that you've just learnt as your ES2015 upgrade) and you try to export that class so that you can reuse it in your main application file:

// hero.class.js
export class Hero {
    constructor(name) {
        this.name = name;
    }
}
// app.js
import { Hero } from './hero.class';
const superman = new Hero('Superman');

Now if we try to exacute the above, we'd get 'unexpected token "export"' appearing.

The reason behind this is simple - Node.js uses the CommonJS Module syntax which assumes two other keywords: require() and module.exports.

We have two options at this point, we can rewrite our code so that we actually use the CommonJS module syntax:

// hero.class.js
class Hero {
  constructor(name) {
    this.name = name;
  }
}

module.exports = Hero;
// app.js
const Hero = require('./hero.class');
const superman = new Hero('Superman');

But should we have a large codebase this may not be an applicable solution.

Transpile using Babel

The other option that we have is to transpile the code that uses the export/import syntax using Babel.

In order to achieve this we need to install the appropriate Babel plugin: npm i --save-dev transform-es2015-modules-commonjs.

Once we have this in place we can transpile our files by executing the following command (this assumes that you have Babel installed globally on your system): babel --plugin transform-es2015-modules-commonjs *.js -d build.

Note that we could also have used the .babelrc config file and specify this plugin for the Babel process to use.

Executing the above should create a build folder, and in that build folder we should have two JavaScript files with the following content:

// hero.class.js
"use strict";
Object.defineProperty(exports, "__esModule", {
  value: true
});
class Hero {
  constructor(name) {
    this.name = name;
  }
}
exports.Hero = Hero;
// app.js
'use strict';
var _class = require('./hero.class');
const superman = new _class.Hero('Superman');

Babel has automatically transpiled our code to use CommonJS style modules.