Asked  6 Months ago    Answers:  5   Viewed   41 times

In a project I'm collaborating on, we have two choices on which module system we can use:

  1. Importing modules using require, and exporting using module.exports and exports.foo.
  2. Importing modules using ES6 import, and exporting using ES6 export

Are there any performance benefits to using one over the other? Is there anything else that we should know if we were to use ES6 modules over Node ones?

 Answers

67

Are there any performance benefits to using one over the other?

Keep in mind that there is no JavaScript engine yet that natively supports ES6 modules. You said yourself that you are using Babel. Babel converts import and export declaration to CommonJS (require/module.exports) by default anyway. So even if you use ES6 module syntax, you will be using CommonJS under the hood if you run the code in Node.

There are technical differences between CommonJS and ES6 modules, e.g. CommonJS allows you to load modules dynamically. ES6 doesn't allow this, but there is an API in development for that.

Since ES6 modules are part of the standard, I would use them.


Update 2020

Since Node v12, support for ES modules is enabled by default, but it's still experimental at the time of writing this. Files including node modules must either end in .mjs or the nearest package.json file must contain "type": "module". The Node documentation has a ton more information, also about interop between CommonJS and ES modules.

Performance-wise there is always the chance that newer features are not as well optimized as existing features. However, since module files are only evaluated once, the performance aspect can probably be ignored. In the end you have to run benchmarks to get a definite answer anyway.

ES modules can be loaded dynamically via the import() function. Unlike require, this returns a promise.

Tuesday, June 1, 2021
 
Arman
answered 6 Months ago
14

I'm answering my own question if anybody else has this problem.

It turns out in experimental mode you need to define the full path with extension. So I am trying to import index.js thinking it will know.

To fix it:

import express from 'express'
import next from 'next'
import api from './src/server/api/index.js'
Sunday, August 8, 2021
 
DaveRandom
answered 4 Months ago
71

EDIT 2

How do I export export default new Sync(); without doing new?

Just remove the new keyword from module/lib/index.js:

import Sync from './sync';

export default Sync;

Or directly import from module/lib/sync.js


EDIT 1

Based on the what you are saying is logged,

Sync { dbConnection: undefined }

it seems like your import is returning an instance of the class (which is an object), rather than the class definition itself.

So console.log(new Sync()) would return what you are saying,

class Sync {

  constructor(dbConnection) {
    this.dbConnection = dbConnection;
  }

  test() {
    return "This is a test " + this.dbConnection;
  }
}

console.log(new Sync());

not console.log(Sync)

class Sync {

  constructor(dbConnection) {
    this.dbConnection = dbConnection;
  }

  test() {
    return "This is a test " + this.dbConnection;
  }
}

console.log(Sync);

Are you sure you aren't calling new Sync anywhere prior to exporting?


Initial answer

The code in question works fine:

'use strict';

class Sync {

  constructor(dbConnection) {
    this.dbConnection = dbConnection;
  }

  test() {
    return "This is a test " + this.dbConnection;
  }
}

const sync = new Sync('CONNECTION!');

console.log(sync.test());

Based on your error:

TypeError: object is not a constructor

Your import is not returning what you think it's returning and you are trying to new something that cannot be instantiated.

Most likely your import path is wrong.

Saturday, August 14, 2021
 
Blundell
answered 4 Months ago
66

Change a.js to export the variable:

exports.test = "Hello World";

and assign the return value of require('./a.js') to a variable:

var a = require('./a.js');
console.log(a.test);

Another pattern you will often see and probably use is to assign something (an object, function) to the module.exports object in a.js, like so:

module.exports = { big: "string" };
Thursday, September 9, 2021
 
muaddhib
answered 3 Months ago
12
--alias, -a    Register an alias with a colon separator: "to:from"
             Example: --alias 'jquery:jquery-browserify'   

You can register aliases with browserify, so that covers your renaming.

As for your rooted absolute paths, that can't really be done. As mentioned modul8 has a namespacing mechanism to solve this.

I would recommend you pong SubStack in #stackvm on freenode and ask him directly.

Sunday, September 12, 2021
 
Don Stanislas
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share