Search code examples
javascriptgulpecmascript-6browserifybabeljs

How to use Gulp and Babelify (Babel + Browserify) to compile singletons and classes


I'm trying to develop an isomorphic game in NodeJS and the web browser. I decided to transfer my codebase to ES6 and ES7 and compile it with BabelJS.

I'm having difficulty compiling the code with Gulp, Babelify, and Gulp-develop-server.

First Issue

First off, the server seems to cache files when I use Gulp watch and call

Application structure
The files in node_modules are there because then I don't need relative import paths. import Event from 'event/event'; instead of import Event from '../event';

src
|
| -- client
|    |
|    | -- main.js (Entrypoint, instantiate game.js class)
|    | -- ...
|
| -- server
|    |
|    | -- main.js (Entrypoint, instantiate game.js class)
|    | -- ...
|
| -- node_modules
|    |
|    | -- event
|    |    |
|    |    | -- event.js (See singleton below)
|    |    | -- package.json ({ "browserify": { "transform": [ [ "babelify", { "stage": "0" } ] ] } })
|    | -- game
|    |    |
|    |    | -- game.js (Class, imports event.js)
|    |    | -- package.json ({ "browserify": { "transform": [ [ "babelify", { "stage": "0" } ] ] } })
|    | -- ...

Second Issue

When I import my singleton, it is missing its functions. Previously, I tried creating a class, and exporting an instance of it, but that didn't work.

Singleton

export default
{
    events: new Map(),
    dispatch: function ( name, value )
    {
        if ( !this.events.has( name ) )
        {
            this.events.set( name, [] );
        }

        for ( var func of this.events.get( name ) )
        {
            func( value );
        }
    },
    listen: function ( name, func )
    {
        if ( !this.evens.has( name ) )
        {
            this.events.set( name, [ func ] );
        }

        this.events.get( name ).push( func );
    }
};

Class (.listen() doesn't work)

import Event from 'event/event';

export default class Game
{
    constructor()
    {
        // listen is undefined
        Event.listen( 'play', function () {} );
    }
}

Gulp Cache

var gulp = require( 'gulp' ),
    babel = require( 'gulp-babel' ),
    babelify = require( 'babelify' ),
    server = require( 'gulp-develop-server' ),
    source = require( 'vinyl-source-stream' ),
    changed = require( 'gulp-changed' ),
    sourcemaps = require( 'gulp-sourcemaps' ),
    browserify = require( 'browserify' ),
    autoprefixer = require( 'gulp-autoprefixer' ),
    watchify = require( 'watchify' );

var paths = {
    client: 'src/client/',
    common: 'src/node_modules/',
    server: 'src/server/',
    html: 'src/client/view/',
    css: 'src/client/view/css/',
    assets: 'src/client/view/assets/',
    node_modules: 'node_modules',
    build_client: 'build/client',
    build_server: 'build'
};

var files = {
    client: paths.build_client + '/client.js',
    server: paths.build_server + '/server_src.js'
}

gulp.task( 'watch', [ 'build', 'server:start' ], function ()
{
    var originalKeys = Object.keys( require.cache );
    gulp.watch( [ paths.common + '**/*.js', paths.client + '**/*.js' ], [ 'client:js' ] );
    gulp.watch( [ paths.common + '**/*.js', paths.server + '**/*.js' ], [ 'server:restart' ] );
} );

gulp.task( 'watch_client:js', function ()
{
    var bundle = browserify(
    {
        debug: true,
        entries: './src/client/main.js',
        cache:
        {},
        packageCache:
        {}
    } );

    bundle = watchify( bundle );
    bundle.transform( babelify.configure(
    {
        sourceMaps: true,
        stage: 0
    } ) );
    bundle.on( 'update', function ()
    {
        executeBundle( bundle );
    } );
    executeBundle( bundle );
} );

function executeBundle( bundle )
{
    var start = Date.now();
    bundle
        .bundle()
        .on( "error", function ( err )
        {
            console.log( "Error : " + err.message );
        } )
        .pipe( source( 'client.js' ) )
        .pipe( gulp.dest( paths.build_client ) )
        .on( 'time', function ( time )
        {
            console.log( 'Bundle finished in ' + time + '.' );
        } );
}

gulp.task( 'build', [ 'client:js', 'client:node_modules', 'server:js' ] );

gulp.task( 'client:js', function ()
{
    browserify(
        {
            debug: true,
            cache:
            {},
            packageCache:
            {}
        } )
        .transform( babelify.configure(
        {
            sourceMaps: true,
            stage: 0
        } ) )
        .require( "./src/client/main.js",
        {
            entry: true
        } )
        .bundle()
        .pipe( source( 'client.js' ) )
        .pipe( gulp.dest( paths.build_client ) );
} );

gulp.task( 'client:node_modules', function ()
{
    return gulp.src( [ paths.node_modules + '/socket.io/node_modules/socket.io-client/socket.io.js' ] )
        .pipe( changed( paths.build_client ) )
        .pipe( gulp.dest( paths.build_client ) );
} );

gulp.task( 'server:js', function ()
{
    browserify(
        {
            debug: true
        } )
        .transform( babelify.configure(
        {
            sourceMaps: true,
            stage: 0
        } ) )
        .require( "./src/server/main.js",
        {
            entry: true
        } )
        .bundle()
        .pipe( source( 'server_src.js' ) )
        .pipe( gulp.dest( './build' ) );

    gulp.src( './src/server/server.js' )
        .pipe( gulp.dest( paths.build_server ) );
} );

gulp.task( 'server:start', [ 'server:js' ], function ()
{
    server.kill();
    server.listen(
    {
        path: paths.build_server + '/server.js'
    } );
} );

gulp.task( 'server:restart', [ 'server:js' ], function ()
{
    server.restart();
} );

Solution

  • I am using RollupJS (http://rollupjs.org) now because it greatly simplifies the process of module loading and running plugins like Babel.

    Stop downvoting and thinking this post is too broad. If you've actually tried to do what I've done, you've realized is quite a specific issue.