How Can I Use Named Module Exports in Node 16 App? - javascript

I'm using Node 16.3.0 and Express 4.17.1 (though my Node version is flexible)
I have a session.js file that's like this:
// session.js
exports.fetchUserId = async function(token){
...
}
exports.save = async function(userId){
...
}
Then over in my app.js file, I try to do this:
// app.js
import session from './session.js'
I get the following error:
import session from './session.js'
^^^^^^^
SyntaxError: The requested module './session.js' does not provide an export named 'default'
...and then I want to use session in app.js like this:
let userId = await session.fetchUserId(req.body.token)
I have tried the following without any luck:
Adding "type": "module" to package.json
This answer by doing npm i esm
Using nodemon --experimental-modules app.js
My code works fine when used in a NuxtJS project, but I'm trying a vanilla Node/Express app and the named exports don't work.
Any idea what I'm doing wrong?

Problem in your code is that you are mixing the ES modules with CommonJS modules.
By default, node treats each javascript file as a CommonJS module but with the following in the package.json file
"type": "module"
you are telling node to treat each javascript file as a Ecmascript module but in session.js file, you are using the CommonJS module syntax to export the functions.
Solutions
You could solve your problem using one of the following options:
Change the extension of the session.js file to .cjs. (Don't forget to change the extension in the import statement in app.js file as well).
Changing the extension to .cjs will tell node to treat session.cjs file as a CommonJS module.
Just use ES modules and change the exports in session.js file as shown below:
export const fetchUserId = async function(token){ ... }
export const save = async function(userId) { ... }
and change the import statement in app.js file as:
import * as session from "./session.js";

Related

Why am I getting this UnhandledPromiseRejectionWarning error when running npm build on my serverless project?

I am getting the following error when trying to run npm build on my serverless aws-nodejs-typescript project and do not understand how to fix it. Anyone able to point me in the right direction please?
npm build
(node:44390) UnhandledPromiseRejectionWarning: Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /usr/local/lib/node_modules/npm/node_modules/chalk/source/index.js
require() of ES modules is not supported.
require() of /usr/local/lib/node_modules/npm/node_modules/chalk/source/index.js from /usr/local/lib/node_modules/npm/lib/utils/explain-dep.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /usr/local/lib/node_modules/npm/node_modules/chalk/package.json.
...
Thanks very much!
The latest version of chalk has changed to ES6 import/export syntax instead of CJS (CommonJS with require). So instead of:
const chalk = require('chalk');
You have to do:
import chalk from 'chalk';
You'll (unfortunately) have to change all the other requires into imports as well, then change all your module.exports into export default and all your exports.whatever to export whatever; where whatever is your thing, or as suggested rename your file to index.cjs to force CJS.
Then there are the docs for import and export if you need them.
Then, you need to add type: "module" to package.json. So much for chalk :)
I didn't like that so I used to just use colors intead, but...

Promoting Babelized ES module code to native Node 14+

I have lot of javascript written to be run by nodejs, but which we ran through the Babel loader at runtime, so that we could write ES syntax -- in particular using import rather than require.
We have a layout like:
package.json
node_modules/
...packages...
top/
server.js
fribbity.js
server.js looks like (I've elided the babel import boilerplate) :
import {fribbity} from 'top/fribbity'
const x = fribbity()
console.log(`fribbity = ${x}`)
while fribbity.js might be
export const fribbity = () => 17
I'd like to promote all this code to use native ES modules in Node 14+. I added "type": "module" to package.json. But now I've run into the module resolution rules. By default, Node now expects my import in server.js to be
import {fribbity} from './fribbity.js'
Are there settings I can apply in package.json, or on the node command line, that would enable node to resolve the imports as they were originally written? That is, preserving the deep import path style (import string begins with no slash or dot, and ends without the ".js" extension)? I've tried several false starts.

Node can't find modules without .js extension

I have a file, test.js with these lines of code inside:
import {blabla} from "./bla";
async function dataGenerator() {
..........
}
(async() => {
console.log('1')
await dataGenerator()
console.log('2')
})()
Note: Ignore the import structure. It is just fictive for the question. In my file the imports are auto.
When I'm trying to run from terminal with node test.js it returns error:
Cannot find module 'D:\bla' imported from D:\test.js
I have added into package.json the line: "type": "module". Without this it returns:
Cannot use import statement outside a module
I'm using node v14. How can I run the test.js without adding to all the imports ".js". There are functions in functions in functions and is complicated to add .js extension. Is there any npm to run it?
Node.js by default does not attempt to guess the file extension when using import for ES modules. This is different from CommonJS modules with require.
In the documentation for the ES module loader you can read how files are found on disk.
The heading 'Customizing ESM specifier resolution algorithm' states:
The --experimental-specifier-resolution=[mode] flag can be used to customize the extension resolution algorithm. The default mode is explicit, which requires the full path to a module be provided to the loader. To enable the automatic extension resolution and importing from directories that include an index file use the node mode.

Import ES6 module from http url in Typescript

I am writing an ES6 module which depends on the other ES6 module specified with http url like this:
import { el, mount } from "https://cdnjs.cloudflare.com/ajax/libs/redom/3.26.0/redom.es.js";
const pElem = el("p") // definitely works in Javascript
When I tried to translate my module in Typescript, I got this error:
Cannot find module 'https://cdnjs.cloudflare.com/ajax/libs/redom/3.26.0/redom.es.js' or its corresponding type declarations.
I'm using ts-watch npm module to compile Typescript, and it works fine unless I don't use the import from https://....
I also know that if I tried to import npm module (e.g. import {el} from "redom") it works as well. But what I am writing is a module for web browser, not that of npm. With this reason, using webpack is not an option.
Thanks to #acrazing's comment, I managed to resolve this problem. Here's how:
In a new ts file:
declare module 'https://*'
This mutes the error that Typescript compiler attempts to read type declaration.
If you want to access type declaration as a node dependency, paste this in a new ts file:
declare module 'https://cdnjs.cloudflare.com/ajax/libs/redom/3.26.0/redom.es.js' {
export * from 'redom'
}
and add redom dependency in package.json
"dependencies": {
"redom": "3.26.0",
...
},
Then, type declaration is read from local ./node_modules directory, VSCode recognizes the types as well.
declare module 'https://*' somehow doesn't work for me so I simply ignore it.
// #ts-ignore Import module
import { Foo } from "https://example.com/foo.ts";
// Now you can use Foo (considered any)

How to import nodejs module "module" via es6 import to create "require" function with "createRequire" in order to use node's "require"?

I am writing a JavaScript es6 module which contains "Mocha" test-cases which test a JavaScript es6 module containing the actual functionality of my app.
I am trying to import nodejs module "module" via es6 import like so:
import { createRequire } from 'module';
Next I create a "require" function by calling "createRequire":
const require = createRequire(import.meta.url);
Afterwards I try to use "require" to import nodejs modules:
const chai = require('chai');
const assert = chai.assert;
I put that all together in a HTML file, started a web-server and opened the HTML file in the browser.
Unfortunately, the first line gives me an error in the console of the Browser Firefox:
TypeError: Error resolving module specifier: module
The browser Chromium gives me the following error message:
Uncaught TypeError: Failed to resolve module specifier "module". Relative references must start with either "/", "./", or "../".
Actually, giving relative references is not working either:
I installed the nodejs module "module" (npm install module) and used a relative path to that module. Unfortunately, the browser does not know how to load the module because no concrete entrypoint is given.
I just tried stick to the manual but had no luck:
https://nodejs.org/api/modules.html#modules_module_createrequire_filename
What do you think? How should I change my code so that this works?
Many thanks in advance for your valuable advice.
I hope you've installed the module using 'npm install module' command, try using commonJS pattern and include the module in the following way
const { createRequire } = require('module');
require() is used to load files in node, and module is a node module.
These things don't exist in browsers.
You do these things, and running mocha tests in node. There should be no browser, just a command line.

Categories

Resources