Reputation: 6615
I've just started working on a small node project that will interface with a MongoDB. However, I cannot seem to get the relevant node modules to import correctly, even though I have installed them correctly via npm
.
For example, the following code throws an error, telling me that "express has no default export":
import express from "express";
However, this code works:
const express = require("express");
So my question is, what is the difference in how the import and variable/require methods function? I'd like to fix whatever is plaguing my imports on the project, as it seems likely to cause additional problems down the road.
Upvotes: 624
Views: 414717
Reputation: 2212
The major difference between require
and import
, is that import
is native to JS, but require
is only available in Node.js.
For reference, below is an example of how Babel can convert ES6's import
syntax to CommonJS's require
syntax. Do note that since Node.js v12, doing so is unnecessary.
Say the fileapp_es6.js
contains this import:
import format from 'date-fns/format';
This is a directive to import the format function from the node package date-fns.
The related package.json
file could contain something like this:
"scripts": {
"start": "node app.js",
"build-server-file": "babel app_es6.js --out-file app.js",
"webpack": "webpack"
}
The related .babelrc
file could be something like this:
{
"presets": [
[
"env",
{
"targets":
{
"node": "current"
}
}
]
]
}
This build-server-file
script defined in the package.json
file is a directive for babel to parse the app_es6.js
file and output the file app.js
.
After running the build-server-file
script, if you open app.js
and look for the date-fns
import, you will see it has been converted into this:
var _format = require("date-fns/format");
var _format2 = _interopRequireDefault(_format);
Most of that file is gobbledygook to most humans, however computers understand it.
Also for reference, as an example of how a module can be created and imported into your project, if you install date-fns
and then open node_modules/date-fns/get_year/index.js
you can see it contains:
var parse = require('../parse/index.js')
function getYear (dirtyDate) {
var date = parse(dirtyDate)
var year = date.getFullYear()
return year
}
module.exports = getYear
Using the babel process above, your app_es6.js
file could then contain:
import getYear from 'date-fns/get_year';
// Which year is 2 July 2014?
var result = getYear(new Date(2014, 6, 2))
//=> 2014
And babel would convert the imports to:
var _get_year = require("date-fns/get_year");
var _get_year2 = _interopRequireDefault(_get_year);
And handle all references to the function accordingly.
Upvotes: 171
Reputation: 3701
import (ES Modules syntax) |
require (CommonJS Modules syntax) |
|
---|---|---|
Summary | It is the latest standard for working with modules in JavaScript and is supported in modern browsers and environments that transpile or support ES6, like TypeScript or Babel. |
It was not originally part of JavaScript, but was adopted as the standard for Node.js, which has been routinely used in JavaScript server-side development. |
Exports | Static (pre-defined). The structure of the module's exports is determined when the code is parsed, not while running. This static nature allows tooling such as bundlers and linters to analyze the code without executing it, enabling features like better tree-shaking and faster load times in browsers. For example:
|
Computed during runtime. The exports in a module are determined during the execution of the code. For example:
|
Loading Modules |
Can be asynchronous, allowing efficient, selective loading of module parts. This can result in faster load times and better performance. For example:
|
Synchronous (loads modules one by one). Always loads entire module, which could affect performance if the module is large. For example:
|
Full Example |
Make sure to export the function first. Then import it
|
Make sure to add the function to module.exports . Then import it
|
Scope |
If an exported value changes in the module it was defined in, that change is visible in all modules that import this value. For example: Now use it somewhere
|
The exports are copied at the time of requiring the module. Now use it somewhere
|
If it's hard to read here, read a copy of this table in GitHub.
Upvotes: 10
Reputation: 438
new ES6:
'import' should be used with 'export' key words to share variables/arrays/objects between js files:
export default myObject;
//....in another file
import myObject from './otherFile.js';
old school:
'require' should be used with 'module.exports'
module.exports = myObject;
//....in another file
var myObject = require('./otherFile.js');
Upvotes: 26
Reputation: 470
These tools belong to different generations.
require
exists only in CommonJS (the way Node.js created to import and export modules within an application), and import
is ES6, ie, a new tool that both browser JavaScript and server JavaScript (Node.js ) can use.
In addition to this historical difference, there are differences in usage, where import
is more flexible, modern and powerful than require
.
It is important however to take into account that some browsers still do not support ES6, so it may be necessary to compile before using it.
require
uses module.exports
, which is the "old" (but still valid) syntax for exporting a module, which can be anything we want, an object, a string, etc.
import
uses both, ie, you can use module.exports
and export
, and it allows you to export various pieces of code more or less like module.export
did. One of the advantages of import
is that it can only import parts of what was exported:
File that exports:
// A.js file
// CommonJS syntax
module.exports = {
foo: function(){ return 'bar';},
baz: 123
}
// ES6 syntax
export function foo(){ return 'bar';}
export const baz = 123;
// or
function foo(){ return 'bar';}
const baz = 123;
export default {foo, baz};
File that imports:
// B.js file
// CommonJS syntax
const A = require('./A.js');
const foo = A.foo;
const baz = A.baz;
// ES6 syntax
import * as A from './A.js';
const foo = A.foo;
const baz = A.baz;
// or only
import {foo, baz} from './A.js';
When you use export default
(ES6 syntax) it implies that you only export one thing per file. If it's an object, import
can only import pieces. But if it's a function, for example, then you can just use import foo from './A.js';
without needing {}
or * as foo
.
Source: https://pt.stackoverflow.com/a/213938/317251
Upvotes: 6
Reputation: 550
import
coming from ES6
is an update to the old CommonJs
module where require
came from. Down the line, I will differential the syntax difference but for now, let's understand why they updated this.
require
is the function that is executed on runtime, which means it behaves like the other JavaScript functions if you define it in the middle of the script the above part of the script won't recognise it or if you put it inside the if statement it will only execute if the if expression will be true, or if you put it inside another function it will only execute when the function gets executed, etc.
On the other hand, import
executes on a static level and it has some rules that it should always be on a root level and should not be inside any conditional statements or functions. Due to JavaScript static analysis for imports, it will throw compile time errors if you do so.
These were the advantages due to that the team changed the way of importing packages to ES6
.
Then Why node is still using the CommonJs module when ES6 is better?
There is a huge code base that uses the CommonJs module in the node that is very difficult to convert to ES6 due to its support for years. But there are many tools that allow us to write ES6 code in node but down the line, these tools transpile it to CommonJs.
Syntax Differences:
Import totally depends on the way things are exported from the package.
If the default way of export is used while exporting a function or variable. like module.export = functionName
in CommondJs
or export default functionName
in ES6
then imports will be like this.
Import in CommonJs vs ES6
const functionName = require("package/exampleFile"); // CommonJs
import functionName from "package/expampleFile.js"; // ES6.
// here you can see that we need to add .js at the end of the file
If multiple functions are exported like module.exports = {functionName1, functionName2}
in CommonJs
or export functionName1 export functionName2
in ES6
then the import will be like this.
const {functionName1, functionName2} = require("package/exampleFile"); // CommonJs
import {functionName1, functionName2} from "package/expampleFile.js"; // ES6.
Upvotes: 1
Reputation: 38542
This simple image will help to you understand the differences between require
and import
.
Apart from that,
You can't selectively load only the pieces you need with require
but with import
, you can selectively load only the pieces you need, which can save memory.
Loading is synchronous(step by step) for require
on the other hand import
can be asynchronous(without waiting for previous import) so it can perform a little better than require
.
Upvotes: 721
Reputation: 591
There's a big difference between this:
import express from "express";
and this:
import * as express from "express";
the correct translation from CommonJS to ES6 of
const express = require("express");
is the second import.
Basically, that's because in the first import you are looking for an export in module express
named express
. The second one you are importing the whole express module with name express
.
Upvotes: 15
Reputation: 1650
I will make it simple,
Major difference is in require, entire JS file is called or included. Even if you don't need some part of it.
var myObject = require('./otherFile.js'); //This JS file will be included fully.
Whereas in import you can extract only objects/functions/variables which are required.
import { getDate }from './utils.js';
//Here I am only pulling getDate method from the file instead of importing full file
Another major difference is you can use require
anywhere in the program where as import
should always be at the top of file
Edit: In Latest node versions you can use destructuring. It will look like this
const { getDate } = require('./date.js');
Upvotes: 42
Reputation: 854
Let me give an example for Including express module with require & import
-require
var express = require('express');
-import
import * as express from 'express';
So after using any of the above statement we will have a variable called as 'express' with us. Now we can define 'app' variable as,
var app = express();
So we use 'require' with 'CommonJS' and 'import' with 'ES6'.
For more info on 'require' & 'import', read through below links.
require - Requiring modules in Node.js: Everything you need to know
import - An Update on ES6 Modules in Node.js
Upvotes: 72