why export and import error in node.js 9? - javascript

I am learning the javascript not long. I make two files like bellow.
app.js:
import * as Conf from './conf'
console.log(Conf.a)
conf.js:
export let a = 1
And i just run the command in console:
node app.js
It was err. The err msg:
(function (exports, require, module, __filename, __dirname) { import *
as Conf from './conf'
SyntaxError: Unexpected token import
Can anyone tell me why? And what is about the javascript and babel and so on. I am not so familiar about the concepts. Thanks.

There is a comity that each year promote a new javascript norm that are called ECMA 2015 (ES6), ECMA 2016 (ES7), ECMA 2017 (ES8) ...
Each norm describe the functionality javascript must have.
It exists multiple javascript engines in the market:
V8 from google (and node)
Chakra from microsoft
Rhino from mozilla
and so on
Theses engines try to keep up to the norm, but are not 100% compliant.
here you can see a compatibility table about the engines and ES6.
The problem you can imagine now, is "Why if I want to use the brand new ES8 right away?". There is two answer: Either you wait for node.js to implement it, either you use a transpiler like Babel.
Babel takes the code you do and transpile it into an older norm (ES5) which is fully compatible with node.js.
For example, you want to use import which is an ES6 feature. Babel gonna transform your import into require so node.js can execute it.
It's very usefull and powerfull to use a transpiler so you an use right away the last feature that are improving the productivity of your developper team.
Like #Tuan Anh Tran said, you can use a flag to say to node.js to run it's experimental features, which represent the features it's implementing right now (not particulary safe so for production).
Here is an article about ES6 features.
Here is an article about ES7 features.
Here about ES8 features.

import is ESM keyword and it's in experimental. See nodejs documentation on esm
If you really want to use it, you can either use babel or run your app with --experimental-modules flag and name your file .mjs extension

You need to install Babel or another transpiler to use ES6 import/export in NodeJS.
Babel installation you can find here: https://babeljs.io/docs/setup/#installation
Also you can use NodeJS module loading system.
Docs: https://nodejs.org/api/modules.html
In your case:
app.js
var conf = require('./conf');
console.log(conf);
conf.js
let a = 1;
module.exports = a;
Or
app.js
var conf = require('./conf');
console.log(conf.a);
conf.js
let a = 1;
exports.a = a;

As the other answers already pointed out, the keywords import and export are experimental.
That's why I'd suggest using require():
Your app.js:
let conf = require("./conf");
console.log(conf.a);
Your conf.js:
let a = 1;
exports.a = a;
node app.js will then print 1 to the console.

Related

Use import inside a nodejs usually using require

I have a NodeJS app with a lot of routes, functions, etc. I have a lot of files with const xxx = require('yyy').
I now want to use this: https://www.npmjs.com/package/simple-ldap-search
I thought my journey would be as peaceful as it has been for now, but I can't use it, let me explain: instead of the usual require, I have to use import, as described in the documentation:
import SimpleLDAP from 'simple-ldap-search';
I searched on StackOverflow, and I saw I could put "type": "module" in the top package.json file, but then if I do I can't use require... It seems unsolvable.
Does it mean I have to choose between using ES6 or CommonJS? I read this question: Using Node.js require vs. ES6 import/export
I have the impression the import is more efficient, am I right?
Is it possible to use simple-ldap-search in my current node app without making big changes?
Is it possible to "convert" (I know it's not the precise term but I think you'll understand) the use of require to import and vice-versa?
Thanks for your answers.
As this project issue states, it isn't possible to use require in a project that switched to type: "module" in its package.json. For these use cases one would need to use a loader like Babel, etc.
It is worth considering switching over to ES modules, i.e to add type: "module" to your top-level package.json. It is still possible to import a CommonJS module with import but it does not work the other way around.
Alternatively, you can switch back to a 2.x version of that package, from what I see they made the switch to ES modules from 3.0.0 onwards.
While you can't use import in a commonjs file, you can use import()
This will make it more annoying when having to deal with the async loading, but is probably easier than converting your entire project to ESModules.
const simpleLDAPLoader = import('simple-ldap-search');
// later
async function () {
const {default: SimpleLDAP} = await simpleLDAPLoader;
const simpleLDAP = new SimpleLDAP();
}
Adn this will use the cached version every time you await the exisiting promise
Source: https://nodejs.org/api/esm.html#esm_interoperability_with_commonjs
Using require to load an ES module is not supported because ES modules have asynchronous execution. Instead, use import() to load an ES module from a CommonJS module.
I am not sure if it is going to help you in your case but I have found this solution for myself and I can use ES6 import and "require" at the same time.
In package.json:
"type": "module"
And in your file:
import { createRequire } from "module";
const require = createRequire(import.meta.url);
Works for my projects!

How to correctly configure experimental ECMAScript module so import/export can be used in Node.js

Time is flying and now the Node.js ver.10.0.0 have been out for the public. While I'm working with my MERN stack, frequently I have to switch between ES6 import/export syntax for the front-end (React.JS) and the CommonJS module.exports/require syntax in my Node/Express server-side. And I'm really wish the writing style could be unified in import/export shortly without using Babel and get it from the native support.
A good news is since the last year I read James' post on Medium addressing in the difficulty of implementing the ES6 module system in Node.js, the experimental ECMAScript Modules is now in stability 1 for a while, which means it could be enabled by --experimental-modules flag.
However, when I'm trying to use import/export syntax on Node, it is never working. For example, I have try this:
import fs from 'fs';
console.log(typeof fs.readFile);
The above code will throw me error:
(function (exports, require, module, __filename, __dirname) { import fs from 'fs';
^^
SyntaxError: Unexpected identifier
I'm really sure I have enabled the experimental flag calling as $node --experimental-modules, so what should I really do in order to kick the ES6 import/export experimental module working on my Node local server? What am I missed?
Added:
The reason why I want to try this experimental feature is to have consistent coding style in both front and back. And because it is now available natively, so I want to get ready to it. Once it have been reach in stage 2, I then can adapted to import/export quickly and have less pain.
But obviously, Google (ref) and AirBnb(ref) have different view points upon if we should use import/export syntax or not in their code-style guide. And based on Google, I'm still surprising that the semantics of ES6 import/export is not yet finalized while ECMA2019 is on its way. I'm just wonder when I can really use import/export in my project, or what is really need to be finalized?
Updated:
After pointed out by Jaromanda X, if I changed my file name to .mjs then it works. Originally I thought is the module to be loaded have to be named in .mjs extension, but it seems I was wrong. However, if that is the case, which means I will need to renamed all my project file in .mjs... and that is not appealing. Just wonder if there is a way to use this feature it in the traditional .js file? What should I configure?
Right at this point ECMAScript Module is not yet finalized in node.js v10, so it is not recommended to use it in the production environment. Since the use of import/export is standardized in the ECMAScript specification, so no matter how, it is important for node to provide such supports for the community.
The major differences between require() and ECMAScript Module is how node is going to handle its cache. Unlike require(), so far ECMAScript Module have no such API to manipulate the module cache. Also, it is unknown if it would be directly supported in the normal *.js files without a loader, so stay tuned.
The direction right now is try to introduce a new *.mjs file to explicitly showing it used the standard JS module (in accordance with ES6), but if one read the doc closely you actually could see it is also possible to specify your own extension match, including the use of the more traditional *.js. However, it required more configurations and the use of --loader flag to load the extra configuration.
There are 6 different formats are supported, including the one for modules written in C++ (it can also be loaded by require()), which is very powerful. In short, to use *.js file extension, the key setting in the loader is to have:
const JS_EXTENSIONS = new Set(['.js', '.mjs']);
And the loader function will need to check as if the file to be loaded is in JS_EXTENSIONS data set. Here, the key in the loader function is that it should return an object that have two properties: url and format, i.e.:
return {
url: (...), // e.g. './x?n=1234'
format: 'esm', // there are 5 + 1 dynamic formatting
};
It would be recommended to named the loader as custom-loader.mjs, and use it as $node --experimental-modules --loader ./custom-loader.mjs since it was demonstrated in the official doc. Once you have configured the loader correctly (based on what you need), then you should be able to use import/export as if you may used in a front-end react app in your node project.

Use "import" with Node library, rather than "require"?

Newbie Node question here.
I'm trying to use the Google Cloud Node client with an existing application (not written by me) that bundles its code with rollup.
I've tried importing the library with require, as per its documentation, as follows:
import REGL from "regl/dist/regl";
import Camera from "./lib/camera";
...
var gcloud = require('google-cloud');
But my application complains (CLARIFICATION: it only starts producing this error when I add the require statement, otherwise the imports work fine):
'import' and 'export' may only appear at the top level
So maybe I need to use import gcloud instead of require, but how? I tried looking at the code in node_modules and doing this instead:
import gcloud from "google-cloud/src/index";
But now I get a bunch of other errors
🚨 Unexpected token
node_modules/google-cloud/node_modules/ent/reversed.json (2:7)
1: {
2: "9": "Tab;",
^
How can I use import instead of require, or alternatively, how can I make require play nicely with import?
import is ES6 syntax. You either must use an experimental flag with nodejs or use babel to compile your js to be ES6 compatible.
EDIT:
Since the problem is with require and not import, i'm updating my answer.
I'm not sure what you're setup is but it's because, i'm guessing, google-cloud isn't written in es6. So you'll have to see if there's an es6 version in the src. If there is you could try (I doubt this will work)
Try:
import * as gcloud from 'google-cloud'
if that doesn't work - try a shimming module like riveted. You'll need webpack to compile this. Since you're using rollup.js, which i'm unfamiliar with you'll need a es5 to es6 compiler for this.

Is it possible to use the ES6 keyword `import` in CoderPad?

Background
I'm trying to import the underscore library within coderpad.io (aka CoderPad)
This ES5 syntax works:
const _ = require('underscore')
This ES6 syntax doesn't:
import * as _ from 'underscore'
Question
Is it possible to use the ES6 import keyword in CoderPad? (if so, how? if not, why not?)
From their Supported Languages page:
Running NodeJS v6
We run NodeJS with the --harmony flag on, which gives you access to most of the features in the upcoming JavaScript ES6 spec. For a complete description of which ES6 features are available, check out the Node compatibility table. Your code is also run for you in strict mode by default, which will enable most ES6 features to work without configuration on your part.
It uses Node v6, which implements most of ES6, but not modules.

Using node.js, nodeunit, and ES6/Harmony

Right now I have a unit testing build environment using node.js and nodeunit. Very happy with these but now I need TCO. I know that TCO has been added into the ES6 standard, but I don't know how to allow it for use with my project. Tried the Harmony flag, but couldn't get it to work with nodeunit. Any help?
Got the idea for using Harmony here:
Node.js tail-call optimization: possible or not?
I like the way these guys think, but I can't do the first answer because then other working on the project would also be forced to change their nodeunit.cmd files (which may screw up other projects they are working on) and the second answer doesn't appear to work:
NodeUnit enable harmony features
From what I understand, it looks like you want to write unit tests in ES5 using nodeunit to test your code written in ES6.
If I understood well, then you can check out this post which shows how to achieve that.
This solution requires you to npm install traceur and then you can require() your ES6 module from within your tests like so :
var traceur = require('traceur');
traceur.require.makeDefault(function(filename) {
return filename.indexOf('node_modules') === -1; // Don't parse node modules
});
var myModule = require('./../path/to/my/module.js');
module.exports = {
// ... tests ...
};
Now you should be able to run that with nodeunit.

Categories

Resources