Reputation: 10879
This question is not whether Node.js supports the ES Module system.
That question has been answered previously, eg:
How can I use an ES6 import in Node.js?
Node.js - SyntaxError: Unexpected token import
And these answers are supported by the official Node.js docs:
ECMAScript modules are the official standard format to package JavaScript code for reuse...Node.js fully supports ECMAScript modules as they are currently specified and provides interoperability between them and its original module format, CommonJS. Node.js has two module systems: CommonJS modules and ECMAScript modules. Authors can tell Node.js to use the ECMAScript modules loader via the
.mjs
file extension, the package.json "type" field, or the --input-type flag.
So it is clear that Node.js supports the ES Module system.
This question is:
When using the ES Module system in Node.js, can all Node packages be imported using the same import syntax?
The reason I ask is that a lot of packages' documentation does not specify how to import them using ES Module style, eg:
https://expressjs.com/en/starter/hello-world.html
https://github.com/expressjs/session
I want to avoid the situation where I am trying to figure out the correct syntax to use each time I want to import a library.
This answer seems to suggest this syntax:
import * as [ whatever_was_previously_used_as_the_variable_name ] from [ whatever_was_previously_between_the_quotes_in_the_parenthesis ]
So, using the examples above, this:
const express = require('express');
const app = express();
const session = require('express-session');
could safely be converted to:
import * as express from 'express';
const app = express();
import * as session from 'express-session';
Is that the 'universal' syntax that should be used to import all Node packages?
(Update: that session
import above doesn't work, at app.use(session(sessionConfig));
it caused the error TypeError: session is not a function
- I needed to define the import like this: import session from 'express-session'
. I also had to import axios like this: import axios from 'axios'
, or i got a similar error. However, to use msal-node i had to use import * as msal from '@azure/msal-node'
).
Just to confuse things, I have come across other syntax examples, such as these in the Node docs (which includes node:
):
import * as fs from 'node:fs/promises';
// OR:
import * as fs from 'node:fs';
I am hoping a definitive answer can be provided that covers the different scenarios that may exist, eg: Node packages that live in the node_modules
directory as well as one's own custom JavaScript modules that live outside of node_modules
.
In this way, if I ever come across a package that does not specify installation instructions using the ES Modules style, I will still know the correct way to import it.
Upvotes: 2
Views: 1206
Reputation: 815
The import
statement is indeed universal and can be used to import a module of either system, whether inside node_modules or out, or built-in to Node. When importing a CommonJS module this way, the value it would normally expose to require
becomes its default export, so import name from 'url';
, or any other form of import
statement that retrieves the default export, will get you what you need.
The import * as name from 'url';
form you mentioned is for retrieving all of a module's named exports. This creates a module namespace object, never a function, though the function or other value that a CommonJS module exposes to require
is available on the default
property. There's generally no need to use import *
with a CommonJS module, since everything that Node detects as a named export will be properties on the default export anyways.
You can also create a require
from inside an ES module; this will work exactly the same way as require
in CommonJS, but that includes the limitation of importing only CommonJS and built-in modules, not ES modules.
Upvotes: 2