ECMAScript Modules On Node.js v11.9.0 - node.js

I'm trying to use exports and import on Node.js application, So I used the Node.js documentation ECMAScript Modules. But I am getting error
I am using,
v11.9.0
Run command node --experimental-modules app.js
How can I use ES6 export and import in Node.JS ? Preferred me the way that not using any additional package !
Code :
// test.js
module.exports = { one: 1 };
// app.js
import foo from './test.js';
console.log(foo);
Error :
(node:9352) ExperimentalWarning: The ESM module loader is experimental.
/home/Workspace/test/app.js:1
(function (exports, require, module, __filename, __dirname) { import foo from './test.js';
^^^
SyntaxError: Unexpected identifier
at new Script (vm.js:84:7)
at createScript (vm.js:264:10)
at Proxy.runInThisContext (vm.js:312:10)
at Module._compile (internal/modules/cjs/loader.js:694:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:745:10)
at Module.load (internal/modules/cjs/loader.js:626:32)
at tryModuleLoad (internal/modules/cjs/loader.js:566:12)
at Function.Module._load (internal/modules/cjs/loader.js:558:3)
at createDynamicModule (internal/modules/esm/translators.js:73:15)
at Object.meta.done (internal/modules/esm/create_dynamic_module.js:40:9)

As the doc says your files need a .mjs extension:
The --experimental-modules flag can be used to enable features for
loading ESM modules.
Once this has been set, files ending with .mjs will be able to be
loaded as ES Modules.
You have to currently use the flag and there is no "seamless" way to use them at the moment other than using a transpiler like babel.
As Quentin says CommonJS files can still use .js extension (you can mix and match).

Related

DotEnv comments are crashing

I'm using dotenv version 16.0.0 in my NodeJS project but the comment feature that was recently added causes a crash. Without the comments the .env file works perfectly, loading values from it.
The .env file content:
# Print out information during runtime, useful for debugging problems not caught.
(true/false)
VERBOSE=false
# Database settings, update for actual deployment environment
DB_USERNAME=postgres
DB_PASSWORD=TINY_DUCK
DB_NAME=user_database
DB_HOST=localhost
DB_PORT=5432
The command to run the NodeJS project is:
mocha -r .env ./tests/testManager.js --exit
And the error message I get when running the NodeJS project:
× ERROR: C:\Users\thega\Source\Repos\network\.env:1
# Print out information during runtime, useful for debugging problems not caught. (true/false)
^
SyntaxError: Invalid or unexpected token
at Object.compileFunction (node:vm:352:18)
at wrapSafe (node:internal/modules/cjs/loader:1031:15)
at Module._compile (node:internal/modules/cjs/loader:1065:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at exports.requireOrImport (C:\Users\thega\source\repos\network\node_modules\mocha\lib\nodejs\esm-utils.js:60:20)
at async exports.handleRequires (C:\Users\thega\source\repos\network\node_modules\mocha\lib\cli\run-helpers.js:94:28)
at async C:\Users\thega\source\repos\network\node_modules\mocha\lib\cli\run.js:353:25
It looks to me as if you are trying to import the .env file as JS module instead of loading it with the dotenv package.
The -r flag to mocha means "require":
This will require a module before loading the user interface or test files.
It is useful for:
Test harnesses
Assertion libraries that has augment built-ins or global scope (such as should.js)
Instant ECMAScript modules using esm
Compilers like Babel via #babel/register or TypeScript using ts-node (using --require ts-node/register).
So it will try to load the file as JavaScript and of course that can't work.
Instead, you can require dotenv/config so it will parse the file for you and update process.env accordingly:
mocha -r dotenv/config ./tests/testManager.js --exit
Or, if you already do require('dotenv').config() in your code, you don't need any -r switch here at all.

Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported

I'm making a discord bot in TypeScript using discord.js. When I tried to compile code this morning I got this error:
C:\SECRET\Kostegator\dist\Util\getMeme.js:17
const node_fetch_1 = __importDefault(require("node-fetch"));
^
Error [ERR_REQUIRE_ESM]: require() of ES Module C:\SECRET\Kostegator\node_modules\node-fetch\src\index.js from C:\SECRET\Kostegator\dist\Util\getMeme.js not supported.
Instead change the require of index.js in C:\SECRET\Kostegator\dist\Util\getMeme.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (C:\SECRET\Kostegator\dist\Util\getMeme.js:17:38)
at Object.<anonymous> (C:\SECRET\Kostegator\dist\Util\index.js:15:14)
at Object.<anonymous> (C:\SECRET\Kostegator\dist\Commands\BotOwner\startAutoUpdate.js:4:16)
at C:\SECRET\Kostegator\dist\Client\index.js:61:41
at Array.forEach (<anonymous>)
at ExtendedClient.<anonymous> (C:\SECRET\Kostegator\dist\Client\index.js:58:48)
at Generator.next (<anonymous>)
at C:\SECRET\Kostegator\dist\Client\index.js:27:71
at new Promise (<anonymous>)
at __awaiter (C:\SECRET\Kostegator\dist\Client\index.js:23:12)
at ExtendedClient.init (C:\SECRET\Kostegator\dist\Client\index.js:51:16)
at Object.<anonymous> (C:\SECRET\Kostegator\dist\index.js:19:4) {
code: 'ERR_REQUIRE_ESM'
}
Here's the GitHub repo: Kostegator
The current version of node-fetch is ONLY compatible with an ESM import (using import), not from CommonJS modules using require().
You have these choices to fix:
Switch your project to an ESM module and load it with import fetch from 'node-fetch';.
In a very recent version of nodejs, you can dynamically import an ESM module into a CommonJS module using let fetch = await import('node-fetch').
Use the v2 version of node-fetch that still supports being loaded with require() as explained here in the doc.
With the latest update, node-fetch only works by using import
You could just install the older version of it by
npm i node-fetch#2.6.1
For those coming here trying to deploy a NodeJS App using the cPanel feature, remember that under the hood it uses Phusion Passenger. This tool needs to have a non-module entry point like:
// entry.cjs DONT FORGET TO USE .cjs and not .js
async function loadApp() {
const { app } = await import("./app.js"); // this is your normal entry file - (index.js, main.js, app.mjs etc.)
}
loadApp()
The original answer is here (it deserves your vote): https://stackoverflow.com/a/71901828/14515077

What is the current simplest way to use ES6 / Import statements etc in Node v 10

I'm fairly new to nodejs. With the evolution of nodejs ( I have just installed v.10 ) what is the current simplest way to use ES6 features ( import statements etc ) in a new nodejs project - that "just works" . I want the least dependencies and the method with the fastest path to "just works".
I am finding the posts on the web a bit confusing.
Babel was installed previously for this sort of thing I understand
Node 10 Says ( Here ) enable using node --experimental-modules my-app.mjs
This post seems quite authoritative , but I think it's about creating packages more than using the syntax.
Please help! I seem to get the following errors for;
import {MagentoAccountApi} from 'js-magento-client';
Error 1:
SyntaxError: Unexpected token {
at new Script (vm.js:74:7)
at createScript (vm.js:246:10)
at Object.runInThisContext (vm.js:298:10)
at Module._compile (internal/modules/cjs/loader.js:646:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
at Module.load (internal/modules/cjs/loader.js:589:32)
at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
at Function.Module._load (internal/modules/cjs/loader.js:520:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
at startup (internal/bootstrap/node.js:228:19)
If I try renaming the file to have an extension .mjs and load using: node --experimental-modules .\mtest.mjs , then I get this error:
(node:20224) ExperimentalWarning: The ESM module loader is experimental.
file:///F:/node/magento-test/mtest.mjs:1
import {MagentoAccountApi} from 'js-magento-client';
^^^^^^^^^^^^^^^^^
SyntaxError: The requested module 'js-magento-client' does not provide an export named 'MagentoAccountApi'
at ModuleJob._instantiate (internal/modules/esm/module_job.js:89:21)
I don't know if that is a packagage error , or a setup error.
Maybe Babel is still the right / easiest way to make this work..? I guess I don't want to start using something the is going to be deprecated soon.
At present, with the experimental loader, CommonJS interoperability only allows for a single default export. You can't use named exports with existing CommonJS modules, so currently you have to do this:
import Magneto from "js-magento-client";
const { MagentoAccountApi } = Magneto;
Which is not correct, but is in the process of being fixed apparently.
From the NodeJS v10 docs:
When loaded via import these modules will provide a single default
export representing the value of module.exports at the time they
finished evaluating.
import fs from 'fs';
fs.readFile('./foo.txt', (err, body) => {
if (err) {
console.error(err);
} else {
console.log(body);
}
});
All the comments above telling you that it's a bad idea to start out with an experimental feature are 100% on-point. The above is a good example. At some point this is going to change and you'll have to change your code. If you used Babel instead, you wouldn't have this issue.

Version compatibility issue Azure functions' Node and DirectlineJS es6 exports

End Goal:
To create Azure Function running Botframework-DirectlineJS with binding to Bot (Framework) using DirectLine secret.
Issue:
The above mentioned Botframework-DirectlineJS uses ES6 export and Azure Functions support Node 6.5.0 max doc. Hence the question how to import successfully the DirectlineJS in the index.js file of Azure function?
Error
```
2017-05-23T07:17:45.939 Exception while executing function: Functions.adapter. mscorlib: D:\home\site\wwwroot\adapter\importexportwrapper.js:1
(function (exports, require, module, __filename, __dirname) { import { DirectLine } from 'botframework-directlinejs';
^^^^^^
SyntaxError: Unexpected token import
at Object.exports.runInThisContext (vm.js:76:16)
at Module._compile (module.js:528:28)
at Object.Module._extensions.(anonymous function) [as .js] (D:\home\site\wwwroot\node_modules\node-hook\index.js:73:14)
at Module.load (module.js:473:32)
at tryModuleLoad (module.js:432:12)
at Function.Module._load (module.js:424:3)
at Module.require (module.js:483:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (D:\home\site\wwwroot\adapter\index.js:4:2)
at Module._compile (module.js:556:32).
```
Currently the error was while trying to use npm import-export
Files
index.js
require('import-export');
require ('./importexportwrapper');
let directLine = new DirectLine({
secret: 'DirectlineSecretValue-here'
}
);```
importexportwrapper.js
import { DirectLine } from 'botframework-directlinejs';
Unfortunately it seems like import-export or node-hook doesn't play well with functions / edgejs (the environment we use to run node).
A couple options to try:
use babel to transpile es6 to es5 as a part of your deployment process.
write your function in typescript (index.ts) which will do import transpilation automatically - though this may fail for module dependencies, I haven't tried it out
You have three options: 1) Write your code using ES5, 2) setup a task runner (gulp/grunt/npm scripts) to convert your ES6+ code to ES5 using Babel, or 3) write your code in Typescript and compile it to ES5 via task runner/npm scripts.
The most straight-forward method would be: in your file importexportwrapper.js use require instead of import.
Example:
var directline = require('botframework-directlinejs');
Babel + Gulp Option
Install: npm install --save-dev gulp gulp-babel
Run:
var gulp = require("gulp");
var babel = require("gulp-babel");
gulp.task("default", function () {
return gulp.src("src/app.js") // your source files
.pipe(babel())
.pipe(gulp.dest("dist")); // your compiled output directory
});
Read more about Azure Functions Node.js versions here.

Typescript AMD Modules for Node.js

I have the following Typescript File which i compile with AMD Modules:
import tsmx = module("../TSMX/tsmx");
tsmx.createServer(1337);
which produces the following js:
define(["require", "exports", "../TSMX/tsmx"], function(require, exports, __tsmx__) {
var tsmx = __tsmx__;
tsmx.createServer(1337);
})
When i try to load it in Node.js i get the following error:
(function (exports, require, module, __filename, __dirname) { define(["require
^
ReferenceError: define is not defined
at Object. (C:\DB\Repo\TSMX\TSMX\TSMXTest\app.js:1:63)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:901:3
How to make this work and get "define" defined? I need AMD Modules because i will load some code in the browser.
I come from C# and AS3 where Imports/Namespaces are a lot easier so sorry if this is a amateur question.
EDIT:
As recommended by http://requirejs.org/docs/node.html#nodeModules i added to the top of the file:
if (typeof define !== 'function')
{
var define = require('amdefine')(module );
}
define(function (require)
{
var dep = require('dependency');
return function () { };
});
but this gets placed inside the define call by typescript which makes it useless.
Then i manually placed it outside of the define call which just resulted in an "Cannot find module 'amdefine'" error.
Just an option: You don't need to use AMD on node. Compile your node files separately from your browser files. Use AMD for browser.
If you still want to use AMD on node code this might help: http://nodejs.org/docs/v0.5.0/api/modules.html
I haven't used node yet, but in the browser define / require are defined in a third party library e.g. requirejs : http://requirejs.org/ demo : http://www.youtube.com/watch?v=4AGQpv0MKsA

Resources