newguy newguy - 2 months ago 18
Javascript Question

Making export default work with Babel, webpack and Node.js

I can't figure out why my code doesn't work.

I am building a ES6 style class and want to export it to be able to use it somewhere else in the server side. I put the code into a file called

PlayerManager.js
in the
server
folder.

I put my client code in the
src
folder. And my server code in my
server
folder and
server.js
outside of
server
folder.

Here is the directory structure:

Root
- dist
- node_modules
- public
- server
- src
server.js
webpack.base.js
webpack.dist.js
package.json
.babelrc


PlayerManager.js
file:

class PlayerManager {

constructor() {
if (! PlayerManager.instance) {
this.playerList = {};
this.bulletList = {};
this.initPack = {player: [], bullet: []};
this.removePack = {player: [], bullet: []};

PlayerManager.instance = this;
}

return PlayerManager.instance;
}

resetData() {
this.initPack.player = [];
this.initPack.bullet = [];
this.removePack.player = [];
this.removePack.bullet = [];
}

}

const instance = new PlayerManager();
Object.freeze(instance);

export default instance;


However, when I use
npm run dev
which runs
node server.js
it throws an error saying

export default instance;
^^^^^^
SyntaxError: Unexpected token export
at Object.exports.runInThisContext (vm.js:53:16)


Here is the configuration for babel in webpack:

const path = require('path');
var CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
entry: {
main: './src/main'
},

output: {
path: path.join(__dirname, 'dist'),
filename: '[name].bundle.js'
},

plugins: [
new CopyWebpackPlugin([
{ from: 'public/img',
to: 'static' },
{ from: 'public' }
])
],

module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
//include: path.join(__dirname, 'src')
exclude: [
path.resolve(__dirname, "node_modules"),
],
},
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=90000' }
]
},

resolve: {
extensions: ['', '.js']
}
};


In
.babelrc
:

{
"presets": [
"es2015"
],

"sourceRoot": "./src"
}


In my
package.json
file:

"scripts": {
"build": "npm run lint && npm run release",
"lint": "./node_modules/.bin/eslint ./src/**/*.js",
"dev": "node server.js",
"release": "NODE_ENV=production webpack --config ./webpack.dist.js --progress",
"test": "./test/*.test.js --compilers js:babel-core/register --recursive --reporter spec"
},

Answer

Webpack is a bundler for producing packages that run on the client (in the browser), it is not aware of or concerned with code on the server. (Unless you are doing universal application stuff.)

You will notice too that your npm dev script is simply asking node to load the server.js file, which is (correctly) not mentioned anywhere in your Webpack config.

You are looking for babel-register:

One of the ways you can use Babel is through the require hook. The require hook will bind itself to node’s require and automatically compile files on the fly.

Create an "entry" file that first requires babel-register and then requires your server.js file:

// server-entry.js
require('babel-register')
require('./server.js')

Now change your npm dev script to be node server-entry.js.

______

Aside: it is necessary to create an entry file as babel-register cannot transpile the file in which it is invoked. For example, this would fail:

// server.js
require('babel-register')

export default function () {}