7

In CJS modules I would use export and var plugin = require('plugin');     to export/import
In ES6 modules I would use export and import * as plugin from 'plugin'; to export/import.

Are there more syntax differences? are these ^ differences correct?

What does export default and export *?

Rikard
  • 7,485
  • 11
  • 55
  • 92
  • 1
    In CJS, `export` (and `module.export`) is just a variable. In ES6, `export` is a keyword and has it's own grammar in the language! – Bergi Jun 30 '15 at 15:51
  • @Bergi thank you, interesting. Go a intersting answer also that will take some minutes learn. – Rikard Jun 30 '15 at 19:51

1 Answers1

32

CommonJS modules and ES6 modules are pretty similar, but they have some very important differences to be aware of. To answer your question directly first:

var plugin = require('plugin');

in ES6 would be equivalent to both

// Import all named exports of 'plugin'.
import * as plugin from 'plugin';

and/or

// Import default export of 'plugin'.
import plugin from 'plugin';

// an alias of
import {default as plugin} from 'plugin';

but it depends on how 'plugin' has been written and whether it was written with ES6 export or CommonJS module.exports.

CommonJS modules

CommonJS imports only have a single exported object. That object may be a function, or an object, or anything. Generally CommonJS modules do

exports.foo = ...;
exports.bar = ...;

to export named properties. They may also export a 'default' object as

module.exports = function(){};

The core thing here is that if you want both a default export AND named exports, your only option is to actually put the properties directly onto the default export.

ES6 modules

For ES6 modules, the concepts of named exports, and default exports are 100% separated. e.g.

export var foo = ...;
export var bar = ...;
export default function fn(){};

The main difference being that

fn.foo !== foo;

With this example then, there are two cases

Plugin used ES6 export

import * as plugin from 'plugin';

plugin.foo === ...;
plugin.bar === ...;
typeof plugin === 'object';

import plugin from 'plugin';

plugin.foo === undefined;
plugin.bar === undefined;
typeof plugin === 'function';

Plugin used CommonJS module.exports

import * as plugin from 'plugin';

plugin.foo === ...;
plugin.bar === ...;
typeof plugin === 'object';

import plugin from 'plugin';

plugin.foo === ...;
plugin.bar === ...;
typeof plugin === 'function';

Live Binding import/export

The other primary difference in your example is that plugin is a live binding. That means that if it is updated inside the module later, it will update itself in your import, e.g.

// plugin.js

export var foo = 'foo';

export function update(){
    foo = 'bar';
}

// other.js

import {foo, update} from 'plugin';

foo === 'foo';

update();

foo === 'bar'

and that would not be the case if you did

var foo = require('plugin').foo;
var update = require('plugin').update;
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • 1
    This was a very nice answer! `+1`. Can I use commonjs & ES6 syntax in same project in Node.js or io.js (I supose so, but wonder if there are issues to it I am not aware)? Will commonsjs modules disapear with time (maybe a subjective question...)? – Rikard Jun 30 '15 at 20:48
  • Found also a interesting gist/article about this: https://gist.github.com/domenic/4748675 – Rikard Jun 30 '15 at 21:08
  • You definitely can use ES5 modules in ES6. I can't say for Traceur, but there is a standard interoperability layer included by Babel when you use `import` syntax that checks whether you are importing an ES6 module or ES5. – loganfsmyth Jun 30 '15 at 21:54
  • This is a repo for demonstration of the above theory: https://github.com/upupming/cjs-vs-esm – upupming Oct 03 '21 at 17:47