In a project I\'m collaborating on, we have two choices on which module system we can use:
require
, and exporting using The main advantages are syntactic:
You are unlikely to see any performance benefits with ES6 modules. You will still need an extra library to bundle the modules, even when there is full support for ES6 features in the browser.
Are there any performance benefits to using one over the other?
The current answer is no, because none of the current browser engines implements import/export
from the ES6 standard.
Some comparison charts http://kangax.github.io/compat-table/es6/ don't take this into account, so when you see almost all greens for Chrome, just be careful. import
keyword from ES6 hasn't been taken into account.
In other words, current browser engines including V8 cannot import new JavaScript file from the main JavaScript file via any JavaScript directive.
( We may be still just a few bugs away or years away until V8 implements that according to the ES6 specification. )
This document is what we need, and this document is what we must obey.
And the ES6 standard said that the module dependencies should be there before we read the module like in the programming language C, where we had (headers) .h
files.
This is a good and well-tested structure, and I am sure the experts that created the ES6 standard had that in mind.
This is what enables Webpack or other package bundlers to optimize the bundle in some special cases, and reduce some dependencies from the bundle that are not needed. But in cases we have perfect dependencies this will never happen.
It will need some time until import/export
native support goes live, and the require
keyword will not go anywhere for a long time.
What is require
?
This is node.js
way to load modules. ( https://github.com/nodejs/node )
Node uses system-level methods to read files. You basically rely on that when using require
. require
will end in some system call like uv_fs_open
(depends on the end system, Linux, Mac, Windows) to load JavaScript file/module.
To check that this is true, try to use Babel.js, and you will see that the import
keyword will be converted into require
.
As of right now ES6 import, export is always compiled to CommonJS, so there is no benefit using one or other. Although usage of ES6 is recommended since it should be advantageous when native support from browsers released. The reason being, you can import partials from one file while with CommonJS you have to require all of the file.
ES6 → import, export default, export
CommonJS → require, module.exports, exports.foo
Below is common usage of those.
ES6 export default
// hello.js
function hello() {
return 'hello'
}
export default hello
// app.js
import hello from './hello'
hello() // returns hello
ES6 export multiple and import multiple
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
export { hello1, hello2 }
// app.js
import { hello1, hello2 } from './hello'
hello1() // returns hello1
hello2() // returns hello2
CommonJS module.exports
// hello.js
function hello() {
return 'hello'
}
module.exports = hello
// app.js
const hello = require('./hello')
hello() // returns hello
CommonJS module.exports multiple
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
module.exports = {
hello1,
hello2
}
// app.js
const hello = require('./hello')
hello.hello1() // returns hello1
hello.hello2() // returns hello2
I personally use import because, we can import the required methods, members by using import.
import {foo, bar} from "dep";
FileName: dep.js
export foo function(){};
export const bar = 22
Credit goes to Paul Shan. More info.
The most important thing to know is that ES6 modules are, indeed, an official standard, while CommonJS (Node.js) modules are not.
In 2019, ES6 modules are supported by 84% of browsers. While Node.js puts them behind an --experimental-modules flag, there is also a convenient node package called esm, which makes the integration smooth.
Another issue you're likely to run into between these module systems is code location. Node.js assumes source is kept in a node_modules
directory, while most ES6 modules are deployed in a flat directory structure. These are not easy to reconcile, but it can be done by hacking your package.json
file with pre and post installation scripts. Here is an example isomorphic module and an article explaining how it works.
Using ES6 modules can be useful for 'tree shaking'; i.e. enabling Webpack 2, Rollup (or other bundlers) to identify code paths that are not used/imported, and therefore don't make it into the resulting bundle. This can significantly reduce its file size by eliminating code you'll never need, but with CommonJS is bundled by default because Webpack et al have no way of knowing whether it's needed.
This is done using static analysis of the code path.
For example, using:
import { somePart } 'of/a/package';
... gives the bundler a hint that package.anotherPart
isn't required (if it's not imported, it can't be used- right?), so it won't bother bundling it.
To enable this for Webpack 2, you need to ensure that your transpiler isn't spitting out CommonJS modules. If you're using the es2015
plug-in with babel, you can disable it in your .babelrc
like so:
{
"presets": [
["es2015", { modules: false }],
]
}
Rollup and others may work differently - view the docs if you're interested.