Exporting a class with ES6 (Babel)

David Gomes picture David Gomes · Mar 30, 2015 · Viewed 84.3k times · Source

I'm writing some frontend code with ECMAScript 6 (transpiled with BabelJS, and then browserified with Browserify) so that I can have a class in one file, export it and import it in another file.

The way I'm doing this is:

export class Game {
    constructor(settings) {

    ...

    }
}

And then on the file that imports the class I do:

import {Game} from "../../lib/pentagine_browserified.js";
var myGame = new Game(settings);

I then compile it with grunt, this is my Gruntfile:

module.exports = function(grunt) {
  "use strict";

  grunt.loadNpmTasks('grunt-babel');
  grunt.loadNpmTasks('grunt-browserify');

  grunt.initConfig({
    "babel": {
      options: {

        sourceMap: false
      },
      dist: {
        files: {
          "lib/pentagine_babel.js": "lib/pentagine.js",
          "demos/helicopter_game/PlayState_babel.js": "demos/helicopter_game/PlayState.js"
        }
      }
    },

    "browserify": {
      dist: {
        files: {
          "lib/pentagine_browserified.js": "lib/pentagine_babel.js",
          "demos/helicopter_game/PlayState_browserified.js": "demos/helicopter_game/PlayState_babel.js"
        }
      }
    }
  });

  grunt.registerTask("default", ["babel", "browserify"]);
};

However, on the new Game( call, I get the following error:

Uncaught TypeError: undefined is not a function

As so, what I did was analyse the generated code by Babel and Browserify and I found this line on PlayState_browserified.js:

var Game = require("../../lib/pentagine_browserified.js").Game;

I decided to print the require output:

console.log(require("../../lib/pentagine_browserified.js"));

And it is nothing but an empty object. I decided to check out the pentagine_browserified.js file:

var Game = exports.Game = (function () {

It seems like it is correctly exporting the class, but for some other reason it is not being required on the other file.

Also, I'm sure the file is being required properly because changing the string "../../lib/pentagine_browserified.js" spits out a Not Found error, so it is going for the right file, that I'm sure about.

Answer

XåpplI'-I0llwlg'I  - picture XåpplI'-I0llwlg'I - · Apr 2, 2015

Browserify is meant to be fed a single "entry point" file, through which it recursively traverses all of your require statements, importing the code from other modules. So you should be require'ing the _babel.js versions of modules, not _browserified.js ones.

From the looks of it, you intend for your app's "entry point" to be demos/helicopter_game/PlayState_browserified.js, yeah? If that's the case:

  • In PlayState.js, change it to import {Game} from "../../lib/pentagine_babel.js";.
  • In Gruntfile.js, remove "lib/pentagine_browserified.js": "lib/pentagine_babel.js".

Works for me. Let me know if that suffices or I am misunderstanding your requirements here.

P.S. You can use babelify to avoid having separate Grunt tasks for Babel and Browserify. See my answer here for an example.