user1063287
user1063287

Reputation: 10879

When using the ES Module system in Node.js, can all Node packages be imported using the same import syntax?

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.

Source

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';

Source

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

Answers (1)

Pixievolt No. 1
Pixievolt No. 1

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

Related Questions