I'm trying to follow a tutorial on NodeJS. I don't think I missed anything but whenever I call the process.env.NODE_ENV the only value I get back is undefined. According to my research the default value should be development. How is this value dynamically set and where is it set initially?
process.env is a reference to your environment, so you have to set the variable there.
To set an environment variable in Windows:
SET NODE_ENV=development
on macOS / OS X or Linux:
export NODE_ENV=development
tips
in package.json:
"scripts": {
"start": "set NODE_ENV=dev && node app.js"
}
in app.js:
console.log(process.env.NODE_ENV) // dev
console.log(process.env.NODE_ENV === 'dev') // false
console.log(process.env.NODE_ENV.length) // 4 (including a space at the end)
so, this may better:
"start": "set NODE_ENV=dev&& node app.js"
or
console.log(process.env.NODE_ENV.trim() === 'dev') // true
For people using *nix (Linux, OS X, etc.), there's no reason to do it via a second export command, you can chain it as part of the invoking command:
NODE_ENV=development node server.js
Easier, no? :)
We ran into this problem when working with node on Windows.
Rather than requiring anyone who attempts to run the app to set these variables, we provided a fallback within the application.
var environment = process.env.NODE_ENV || 'development';
In a production environment, we would define it per the usual methods (SET/export).
You can use the cross-env npm package. It will take care of trimming the environment variable, and will also make sure it works across different platforms.
In the project root, run:
npm install cross-env
Then in your package.json, under scripts, add:
"start": "cross-env NODE_ENV=dev node your-app-name.js"
Then in your terminal, at the project root, start your app by running:
npm start
The environment variable will then be available in your app as process.env.NODE_ENV, so you could do something like:
if (process.env.NODE_ENV === 'dev') {
// Your dev-only logic goes here
}
in package.json we have to config like below (works in Linux and Mac OS)
the important thing is "export NODE_ENV=production" after your build commands below is an example:
"scripts": {
"start": "export NODE_ENV=production && npm run build && npm run start-server",
"dev": "export NODE_ENV=dev && npm run build && npm run start-server",
}
for dev environment, we have to hit "npm run dev" command
for a production environment, we have to hit "npm run start" command
In macOS for those who are using the express version 4.x.x and using the DOTENV plugin, need to use like this:
After installing the plugin import like the following in the file where you init the application:
require('dotenv').config({path: path.resolve(__dirname+'/.env')});
In the root directory create a file '.env' and add the varaiable like:
NODE_ENV=development
or
NODE_ENV = development
As early as possible in your application, require and configure dotenv.
require('dotenv').config()
In UBUNTU use:
$ export NODE_ENV=test
install dotenv module ( npm i dotenv --save )
require('dotenv').config() //write inside the file where you will use the variable
console.log(process.env.NODE_ENV) // returns value stored in .env file
Must be the first require in app.js
npm install dotenv
require("dotenv").config();
In my case, I have a node app. The way I have structured it is that I have client folder and server folder. I had my .env file inline with these two folder. My server file needs the .env file. It was returning undefined because it did not live inside the server file. It was an oversight.
App
-client
-server
-.env
Instead I moved .env inside server file like so:
App
-client
-server
|-.env <---here
|-package.json
|-and the rest of the server files...
(before this - ofcourse have the dotenv npm package installed and follow its doc)
It is due to OS
In your package.json, make sure to have your scripts(Where app.js is your main js file to be executed & NODE_ENV is declared in a .env file).Eg:
"scripts": {
"start": "node app.js",
"dev": "nodemon server.js",
"prod": "NODE_ENV=production & nodemon app.js"
}
For windows
Also set up your .env file variable having NODE_ENV=development
If your .env file is in a folder for eg.config folder make sure to specify in app.js(your main js file)
const dotenv = require('dotenv');
dotenv.config({ path: './config/config.env' });
You can use the dotenv package from npm, here is the link: https://www.npmjs.com/package/dotenv
Which allows you to place all your configuration in a .env file
If you faced this probem in React, you need react-scripts#0.2.3 and higher. Also for other environment variables than NODE_ENV to work in React, they need to be prefixed with REACT_APP_.
For me, the issue was that I was using the pkg library to turn my app into an executable binary. In that case, the accepted solutions didn't work. However, using the following code solved my problem:
const NODE_ENV = (<any>process).pkg ? 'production' : process.env.NODE_ENV;
I found this solution here on GitHub.
In Electron Js
"scripts": {
"start": "NODE_ENV=development electron index.js",
},
If you define any function with the name process then that may also cause this issue.
Defining process.env.NODE_ENV in package.json for Windows/Mac/Linux:
Here's what worked for me on my Mac (MacBook Pro 2019, 16 inch, Big Sur):
"scripts": {
"build": "export NODE_ENV=prod || set NODE_ENV=prod&& npx eslint . && node --experimental-json-modules ./backend/app.js && gulp",
},
Using the export NODE_ENV=prod || set NODE_ENV=prod&& string may work in Windows and Linux but I haven't tested that.
If someone could confirm that would be great.
Unfortunately using the cross-env npm package did NOT work for me at all in my package.json file and I spend a long time on my Mac trying to make this work.
I also faced this issue.
I moved .env file to the root folder (not the project folder, a level higher) and it worked out.
Check it. it might help you as well
You can also set it by code, for example:
process.env.NODE_ENV = 'test';
Related
I don't understand what is wrong.
Node v5.6.0
NPM v3.10.6
The code:
function (exports, require, module, __filename, __dirname) {
import express from 'express'
};
The error:
SyntaxError: Unexpected token import
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:387:25)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:447:10)
at startup (node.js:140:18)
at node.js:1001:3
Node 13+ Since Node 13, you can use either the .mjs extension, or set {"type": "module"} in your package.json. You don't need to use the --experimental-modules flag. Modules is now marked as stable in node.js
Node 12 Since Node 12, you can use either the .mjs extension, or set "type": "module" in your package.json. And you need to run node with the --experimental-modules flag.
Node 9 In Node 9, it is enabled behind a flag, and uses the .mjs extension.
node --experimental-modules my-app.mjs
While import is indeed part of ES6, it is unfortunately not yet supported in NodeJS by default, and has only very recently landed support in browsers.
See browser compat table on MDN and this Node issue.
From James M Snell's Update on ES6 Modules in Node.js (February 2017):
Work is in progress but it is going to take some time — We’re currently looking at around a year at least.
Until support shows up natively (now marked stable in Node 13+), you'll have to continue using classic require statements:
const express = require("express");
If you really want to use new ES6/7 features in NodeJS, you can compile it using Babel. Here's an example server.
Unfortunately, Node.js doesn't support ES6's import yet.
To accomplish what you're trying to do (import the Express module), this code should suffice
var express = require("express");
Also, be sure you have Express installed by running
$ npm install express
See the Node.js Docs for more information about learning Node.js.
I'm shocked esm hasn't been mentioned. This small, but mighty package allows you to use either import or require.
Install esm in your project
$ npm install --save esm
Update your Node Start Script to use esm
node -r esm app.js
esm just works. I wasted a TON of time with .mjs and --experimental-modules only to find out a .mjs file cannot import a file that uses require or module.exports. This was a huge problem, whereas esm allows you to mix and match and it just figures it out... esm just works.
As mentioned in other answers Node JS currently doesn't support ES6 imports.
(As of now, read EDIT 2)
Enable ES6 imports in node js provides a solution to this issue. I have tried this and it worked for me.
Run the command:
npm install babel-register babel-preset-env --save-dev
Now you need to create a new file (config.js) and add the following code to it.
require('babel-register')({
presets: [ 'env' ]
})
// Import the rest of our application.
module.exports = require('./your_server_file.js')
Now you can write import statements without getting any errors.
Hope this helps.
EDIT:
You need to run the new file which you created with above code. In my case it was config.js. So I have to run:
node config.js
EDIT 2:
While experimenting, I found one easy solution to this issue.
Create .babelrc file in the root of your project.
Add following (and any other babel presets you need, can be added in this file):
{
"presets": ["env"]
}
Install babel-preset-env using command npm install babel-preset-env --save, and then install babel-cli using command npm install babel-cli -g --save
Now, go to the folder where your server or index file exists and run using:
babel-node fileName.js
Or you can run using npm start by adding following code to your package.json file:
"scripts": {
"start": "babel-node src/index.js"
}
Error: SyntaxError: Unexpected token import or SyntaxError: Unexpected token export
Solution: Change all your imports as example
const express = require('express');
const webpack = require('webpack');
const path = require('path');
const config = require('../webpack.config.dev');
const open = require('open');
And also change your export default = foo; to module.exports = foo;
In case that you still can't use "import" here is how I handled it:
Just translate it to a node friendly require. Example:
import { parse } from 'node-html-parser';
Is the same as:
const parse = require('node-html-parser').parse;
babel 7 proposal
can you add dev dependencies
npm i -D #babel/core #babel/preset-env #babel/register
and add a .babelrc in the root
{
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
and add to the .js file
require("#babel/register")
or if you run it in the cli, you could use the require hook as -r #babel/register, ex.
$node -r #babel/register executeMyFileWithESModules.js
When I was started with express always wanted a solution to use import instead require
const express = require("express");
// to
import express from "express"
Many time go through this line:- Unfortunately, Node.js doesn't support ES6's import yet.
Now to help other I create new two solutions here
1) esm:-
The brilliantly simple, babel-less, bundle-less ECMAScript module loader.
let's make it work
yarn add esm / npm install esm
create start.js or use your namespace
require = require("esm")(module/*, options*/)
// Import the rest of our application.
module.exports = require('./src/server.js')
// where server.js is express server start file
Change in your package.josn pass path of start.js
"scripts": {
"start": "node start.js",
"start:dev": "nodemon start.js",
},
"dependencies": {
+ "esm": "^3.2.25",
},
"devDependencies": {
+ "nodemon": "^1.19.2"
}
2) Babel js:-
This can be divide into 2 part
a) Solution 1 thanks to timonweb.com
b) Solution 2
use Babel 6 (older version of babel-preset-stage-3 ^6.0)
create .babelrc file at your root folder
{
"presets": ["env", "stage-3"]
}
Install babel-preset-stage-3
yarn add babel-cli babel-polyfill babel-preset-env bable-preset-stage-3 nodemon --dev
Change in package.json
"scripts": {
+ "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+ "start": "npm run build && node ./build/index.js",
+ "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+ "clean": "rm -rf build && mkdir build"
},
"devDependencies": {
+ "babel-cli": "^6.26.0",
+ "babel-polyfill": "^6.26.0",
+ "babel-preset-env": "^1.7.0",
+ "babel-preset-stage-3": "^6.24.1",
+ "nodemon": "^1.19.4"
},
Start your server
yarn start / npm start
Oooh no we create new problem
regeneratorRuntime.mark(function _callee(email, password) {
^
ReferenceError: regeneratorRuntime is not defined
This error only come when you use async/await in your code.
Then use polyfill that includes a custom regenerator runtime and core-js.
add on top of index.js
import "babel-polyfill"
This allow you to use async/await
use Babel 7
Need to upto date every thing in your project
let start with babel 7
.babelrc
{
"presets": ["#babel/preset-env"]
}
Some change in package.json
"scripts": {
+ "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+ "start": "npm run build && node ./build/index.js",
+ "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+ "clean": "rm -rf build && mkdir build",
....
}
"devDependencies": {
+ "#babel/cli": "^7.0.0",
+ "#babel/core": "^7.6.4",
+ "#babel/node": "^7.0.0",
+ "#babel/polyfill": "^7.0.0",
+ "#babel/preset-env": "^7.0.0",
+ "nodemon": "^1.19.4"
....
}
and use import "#babel/polyfill" on start point
import "#babel/polyfill"
import express from 'express'
const app = express()
//GET request
app.get('/', async (req, res) {
// await operation
res.send('hello world')
})
app.listen(4000, () => console.log('🚀 Server listening on port 400!'))
Are you thinking why start:dev
Seriously. It is good question if you are new. Every change you are boar with start server every time
then use yarn start:dev as development server every change restart server automatically for more on nodemon
if you can use 'babel', try to add build scripts in package.json(--presets=es2015) as below. it make to precompile import code to es2015
"build": "babel server --out-dir build --presets=es2015 && webpack"
As of Node.js v12 (and this is probably fairly stable now, but still marked "experimental"), you have a couple of options for using ESM (ECMAScript Modules) in Node.js (for files, there's a third way for evaling strings), here's what the documentation says:
The --experimental-modules flag can be used to enable support for
ECMAScript modules (ES modules).
Once enabled, Node.js will treat the following as ES modules when passed to
node as the initial input, or when referenced by import statements within
ES module code:
Files ending in .mjs.
Files ending in .js, or extensionless files, when the nearest parent
package.json file contains a top-level field "type" with a value of
"module".
Strings passed in as an argument to --eval or --print, or piped to
node via STDIN, with the flag --input-type=module.
Node.js will treat as CommonJS all other forms of input, such as .js files
where the nearest parent package.json file contains no top-level "type"
field, or string input without the flag --input-type. This behavior is to
preserve backward compatibility. However, now that Node.js supports both
CommonJS and ES modules, it is best to be explicit whenever possible. Node.js
will treat the following as CommonJS when passed to node as the initial input,
or when referenced by import statements within ES module code:
Files ending in .cjs.
Files ending in .js, or extensionless files, when the nearest parent
package.json file contains a top-level field "type" with a value of
"commonjs".
Strings passed in as an argument to --eval or --print, or piped to
node via STDIN, with the flag --input-type=commonjs.
I'm going to address another problem within the original question that no one else has. After recently converting from CommonJS to ESM in my own NodeJS project, I've seen very little discussion about the fact that you cannot place imports wherever you want, like you could with require. My project is working great with imports now, but when I use the code in the question, I first get an error for not having a named function. After naming the function, I receive the following...
import express from 'express'
^^^^^^^
SyntaxError: Unexpected identifier
at Loader.moduleStrategy (internal/modules/esm/translators.js:88:18)
You cannot place imports inside functions like you could require. They have to be placed at the top of the file, outside code blocks. I wasted quite a bit of time on this issue myself.
So while all of the above answers are great at helping you get imports to work in your project, none address the fact that the code in the original question cannot work as written.
import statements are supported in the stable release of Node since version 14.x LTS.
All you need to do is specify "type": "module" in package.json.
In my case it was looking after .babelrc file, and it should contain something like this:
{
"presets": ["es2015-node5", "stage-3"],
"plugins": []
}
My project uses node v10.21.0, which still does not support ES6 import keyword. There are multiple ways to make node recognize import, one of them is to start node with node --experimental-modules index.mjs (The mjs extension is already covered in one of the answers here). But, this way, you will not be able to use node specific keyword like require in your code. If there is need to use both nodejs's require keyword along with ES6's import, then the way out is to use the esm npm package. After adding esm package as a dependency, node needs to be started with a special configuration like: node -r esm index.js
I've been trying to get this working. Here's what works:
Use a recent node version. I'm using v14.15.5. Verify your version by running: node --version
Name the files so that they all end with .mjs rather than .js
Example:
mod.mjs
export const STR = 'Hello World'
test.mjs
import {STR} from './mod.mjs'
console.log(STR)
Run: node test.mjs
You should see "Hello World".
Simply install a higher version of Node. As till Node v10 es6 is not supported. You need to disable a few flags or use
I don't understand what is wrong.
Node v5.6.0
NPM v3.10.6
The code:
function (exports, require, module, __filename, __dirname) {
import express from 'express'
};
The error:
SyntaxError: Unexpected token import
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:387:25)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:447:10)
at startup (node.js:140:18)
at node.js:1001:3
Node 13+ Since Node 13, you can use either the .mjs extension, or set {"type": "module"} in your package.json. You don't need to use the --experimental-modules flag. Modules is now marked as stable in node.js
Node 12 Since Node 12, you can use either the .mjs extension, or set "type": "module" in your package.json. And you need to run node with the --experimental-modules flag.
Node 9 In Node 9, it is enabled behind a flag, and uses the .mjs extension.
node --experimental-modules my-app.mjs
While import is indeed part of ES6, it is unfortunately not yet supported in NodeJS by default, and has only very recently landed support in browsers.
See browser compat table on MDN and this Node issue.
From James M Snell's Update on ES6 Modules in Node.js (February 2017):
Work is in progress but it is going to take some time — We’re currently looking at around a year at least.
Until support shows up natively (now marked stable in Node 13+), you'll have to continue using classic require statements:
const express = require("express");
If you really want to use new ES6/7 features in NodeJS, you can compile it using Babel. Here's an example server.
Unfortunately, Node.js doesn't support ES6's import yet.
To accomplish what you're trying to do (import the Express module), this code should suffice
var express = require("express");
Also, be sure you have Express installed by running
$ npm install express
See the Node.js Docs for more information about learning Node.js.
I'm shocked esm hasn't been mentioned. This small, but mighty package allows you to use either import or require.
Install esm in your project
$ npm install --save esm
Update your Node Start Script to use esm
node -r esm app.js
esm just works. I wasted a TON of time with .mjs and --experimental-modules only to find out a .mjs file cannot import a file that uses require or module.exports. This was a huge problem, whereas esm allows you to mix and match and it just figures it out... esm just works.
As mentioned in other answers Node JS currently doesn't support ES6 imports.
(As of now, read EDIT 2)
Enable ES6 imports in node js provides a solution to this issue. I have tried this and it worked for me.
Run the command:
npm install babel-register babel-preset-env --save-dev
Now you need to create a new file (config.js) and add the following code to it.
require('babel-register')({
presets: [ 'env' ]
})
// Import the rest of our application.
module.exports = require('./your_server_file.js')
Now you can write import statements without getting any errors.
Hope this helps.
EDIT:
You need to run the new file which you created with above code. In my case it was config.js. So I have to run:
node config.js
EDIT 2:
While experimenting, I found one easy solution to this issue.
Create .babelrc file in the root of your project.
Add following (and any other babel presets you need, can be added in this file):
{
"presets": ["env"]
}
Install babel-preset-env using command npm install babel-preset-env --save, and then install babel-cli using command npm install babel-cli -g --save
Now, go to the folder where your server or index file exists and run using:
babel-node fileName.js
Or you can run using npm start by adding following code to your package.json file:
"scripts": {
"start": "babel-node src/index.js"
}
Error: SyntaxError: Unexpected token import or SyntaxError: Unexpected token export
Solution: Change all your imports as example
const express = require('express');
const webpack = require('webpack');
const path = require('path');
const config = require('../webpack.config.dev');
const open = require('open');
And also change your export default = foo; to module.exports = foo;
In case that you still can't use "import" here is how I handled it:
Just translate it to a node friendly require. Example:
import { parse } from 'node-html-parser';
Is the same as:
const parse = require('node-html-parser').parse;
babel 7 proposal
can you add dev dependencies
npm i -D #babel/core #babel/preset-env #babel/register
and add a .babelrc in the root
{
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
and add to the .js file
require("#babel/register")
or if you run it in the cli, you could use the require hook as -r #babel/register, ex.
$node -r #babel/register executeMyFileWithESModules.js
When I was started with express always wanted a solution to use import instead require
const express = require("express");
// to
import express from "express"
Many time go through this line:- Unfortunately, Node.js doesn't support ES6's import yet.
Now to help other I create new two solutions here
1) esm:-
The brilliantly simple, babel-less, bundle-less ECMAScript module loader.
let's make it work
yarn add esm / npm install esm
create start.js or use your namespace
require = require("esm")(module/*, options*/)
// Import the rest of our application.
module.exports = require('./src/server.js')
// where server.js is express server start file
Change in your package.josn pass path of start.js
"scripts": {
"start": "node start.js",
"start:dev": "nodemon start.js",
},
"dependencies": {
+ "esm": "^3.2.25",
},
"devDependencies": {
+ "nodemon": "^1.19.2"
}
2) Babel js:-
This can be divide into 2 part
a) Solution 1 thanks to timonweb.com
b) Solution 2
use Babel 6 (older version of babel-preset-stage-3 ^6.0)
create .babelrc file at your root folder
{
"presets": ["env", "stage-3"]
}
Install babel-preset-stage-3
yarn add babel-cli babel-polyfill babel-preset-env bable-preset-stage-3 nodemon --dev
Change in package.json
"scripts": {
+ "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+ "start": "npm run build && node ./build/index.js",
+ "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+ "clean": "rm -rf build && mkdir build"
},
"devDependencies": {
+ "babel-cli": "^6.26.0",
+ "babel-polyfill": "^6.26.0",
+ "babel-preset-env": "^1.7.0",
+ "babel-preset-stage-3": "^6.24.1",
+ "nodemon": "^1.19.4"
},
Start your server
yarn start / npm start
Oooh no we create new problem
regeneratorRuntime.mark(function _callee(email, password) {
^
ReferenceError: regeneratorRuntime is not defined
This error only come when you use async/await in your code.
Then use polyfill that includes a custom regenerator runtime and core-js.
add on top of index.js
import "babel-polyfill"
This allow you to use async/await
use Babel 7
Need to upto date every thing in your project
let start with babel 7
.babelrc
{
"presets": ["#babel/preset-env"]
}
Some change in package.json
"scripts": {
+ "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+ "start": "npm run build && node ./build/index.js",
+ "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+ "clean": "rm -rf build && mkdir build",
....
}
"devDependencies": {
+ "#babel/cli": "^7.0.0",
+ "#babel/core": "^7.6.4",
+ "#babel/node": "^7.0.0",
+ "#babel/polyfill": "^7.0.0",
+ "#babel/preset-env": "^7.0.0",
+ "nodemon": "^1.19.4"
....
}
and use import "#babel/polyfill" on start point
import "#babel/polyfill"
import express from 'express'
const app = express()
//GET request
app.get('/', async (req, res) {
// await operation
res.send('hello world')
})
app.listen(4000, () => console.log('🚀 Server listening on port 400!'))
Are you thinking why start:dev
Seriously. It is good question if you are new. Every change you are boar with start server every time
then use yarn start:dev as development server every change restart server automatically for more on nodemon
if you can use 'babel', try to add build scripts in package.json(--presets=es2015) as below. it make to precompile import code to es2015
"build": "babel server --out-dir build --presets=es2015 && webpack"
As of Node.js v12 (and this is probably fairly stable now, but still marked "experimental"), you have a couple of options for using ESM (ECMAScript Modules) in Node.js (for files, there's a third way for evaling strings), here's what the documentation says:
The --experimental-modules flag can be used to enable support for
ECMAScript modules (ES modules).
Once enabled, Node.js will treat the following as ES modules when passed to
node as the initial input, or when referenced by import statements within
ES module code:
Files ending in .mjs.
Files ending in .js, or extensionless files, when the nearest parent
package.json file contains a top-level field "type" with a value of
"module".
Strings passed in as an argument to --eval or --print, or piped to
node via STDIN, with the flag --input-type=module.
Node.js will treat as CommonJS all other forms of input, such as .js files
where the nearest parent package.json file contains no top-level "type"
field, or string input without the flag --input-type. This behavior is to
preserve backward compatibility. However, now that Node.js supports both
CommonJS and ES modules, it is best to be explicit whenever possible. Node.js
will treat the following as CommonJS when passed to node as the initial input,
or when referenced by import statements within ES module code:
Files ending in .cjs.
Files ending in .js, or extensionless files, when the nearest parent
package.json file contains a top-level field "type" with a value of
"commonjs".
Strings passed in as an argument to --eval or --print, or piped to
node via STDIN, with the flag --input-type=commonjs.
I'm going to address another problem within the original question that no one else has. After recently converting from CommonJS to ESM in my own NodeJS project, I've seen very little discussion about the fact that you cannot place imports wherever you want, like you could with require. My project is working great with imports now, but when I use the code in the question, I first get an error for not having a named function. After naming the function, I receive the following...
import express from 'express'
^^^^^^^
SyntaxError: Unexpected identifier
at Loader.moduleStrategy (internal/modules/esm/translators.js:88:18)
You cannot place imports inside functions like you could require. They have to be placed at the top of the file, outside code blocks. I wasted quite a bit of time on this issue myself.
So while all of the above answers are great at helping you get imports to work in your project, none address the fact that the code in the original question cannot work as written.
import statements are supported in the stable release of Node since version 14.x LTS.
All you need to do is specify "type": "module" in package.json.
In my case it was looking after .babelrc file, and it should contain something like this:
{
"presets": ["es2015-node5", "stage-3"],
"plugins": []
}
My project uses node v10.21.0, which still does not support ES6 import keyword. There are multiple ways to make node recognize import, one of them is to start node with node --experimental-modules index.mjs (The mjs extension is already covered in one of the answers here). But, this way, you will not be able to use node specific keyword like require in your code. If there is need to use both nodejs's require keyword along with ES6's import, then the way out is to use the esm npm package. After adding esm package as a dependency, node needs to be started with a special configuration like: node -r esm index.js
I've been trying to get this working. Here's what works:
Use a recent node version. I'm using v14.15.5. Verify your version by running: node --version
Name the files so that they all end with .mjs rather than .js
Example:
mod.mjs
export const STR = 'Hello World'
test.mjs
import {STR} from './mod.mjs'
console.log(STR)
Run: node test.mjs
You should see "Hello World".
Simply install a higher version of Node. As till Node v10 es6 is not supported. You need to disable a few flags or use
I am trying to set my environment variable within package.json so that I can use it within my server.js file. I have set it as NODE_ENV=development, set NODE_ENV=development,
cross-env NODE_ENV=development, export NODE_ENV=development but it is still returning undefined. I am not sure what is going wrong but I would love any insight into this problem!
package.json
"scripts": {
"dev": "NODE_ENV=development npm run client & npm run start & npm run json-server & redis-server"
}
server.js
//returns undefined
console.log(process.env.NODE_ENV)
I am not entirely sure how your file is structure but it seems you got
some of the command wrong.
You should use set NODE_ENV=development and you should double
ampersand
Honestly it much easier to define it in your main server file like
this:
const env = process.env.NODE_ENV || "development"
Did you install and require the dotenv package and did you call the .config() function of it in your index.js ? This will probably help.
I don't understand what is wrong.
Node v5.6.0
NPM v3.10.6
The code:
function (exports, require, module, __filename, __dirname) {
import express from 'express'
};
The error:
SyntaxError: Unexpected token import
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:387:25)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:447:10)
at startup (node.js:140:18)
at node.js:1001:3
Node 13+ Since Node 13, you can use either the .mjs extension, or set {"type": "module"} in your package.json. You don't need to use the --experimental-modules flag. Modules is now marked as stable in node.js
Node 12 Since Node 12, you can use either the .mjs extension, or set "type": "module" in your package.json. And you need to run node with the --experimental-modules flag.
Node 9 In Node 9, it is enabled behind a flag, and uses the .mjs extension.
node --experimental-modules my-app.mjs
While import is indeed part of ES6, it is unfortunately not yet supported in NodeJS by default, and has only very recently landed support in browsers.
See browser compat table on MDN and this Node issue.
From James M Snell's Update on ES6 Modules in Node.js (February 2017):
Work is in progress but it is going to take some time — We’re currently looking at around a year at least.
Until support shows up natively (now marked stable in Node 13+), you'll have to continue using classic require statements:
const express = require("express");
If you really want to use new ES6/7 features in NodeJS, you can compile it using Babel. Here's an example server.
Unfortunately, Node.js doesn't support ES6's import yet.
To accomplish what you're trying to do (import the Express module), this code should suffice
var express = require("express");
Also, be sure you have Express installed by running
$ npm install express
See the Node.js Docs for more information about learning Node.js.
I'm shocked esm hasn't been mentioned. This small, but mighty package allows you to use either import or require.
Install esm in your project
$ npm install --save esm
Update your Node Start Script to use esm
node -r esm app.js
esm just works. I wasted a TON of time with .mjs and --experimental-modules only to find out a .mjs file cannot import a file that uses require or module.exports. This was a huge problem, whereas esm allows you to mix and match and it just figures it out... esm just works.
As mentioned in other answers Node JS currently doesn't support ES6 imports.
(As of now, read EDIT 2)
Enable ES6 imports in node js provides a solution to this issue. I have tried this and it worked for me.
Run the command:
npm install babel-register babel-preset-env --save-dev
Now you need to create a new file (config.js) and add the following code to it.
require('babel-register')({
presets: [ 'env' ]
})
// Import the rest of our application.
module.exports = require('./your_server_file.js')
Now you can write import statements without getting any errors.
Hope this helps.
EDIT:
You need to run the new file which you created with above code. In my case it was config.js. So I have to run:
node config.js
EDIT 2:
While experimenting, I found one easy solution to this issue.
Create .babelrc file in the root of your project.
Add following (and any other babel presets you need, can be added in this file):
{
"presets": ["env"]
}
Install babel-preset-env using command npm install babel-preset-env --save, and then install babel-cli using command npm install babel-cli -g --save
Now, go to the folder where your server or index file exists and run using:
babel-node fileName.js
Or you can run using npm start by adding following code to your package.json file:
"scripts": {
"start": "babel-node src/index.js"
}
Error: SyntaxError: Unexpected token import or SyntaxError: Unexpected token export
Solution: Change all your imports as example
const express = require('express');
const webpack = require('webpack');
const path = require('path');
const config = require('../webpack.config.dev');
const open = require('open');
And also change your export default = foo; to module.exports = foo;
In case that you still can't use "import" here is how I handled it:
Just translate it to a node friendly require. Example:
import { parse } from 'node-html-parser';
Is the same as:
const parse = require('node-html-parser').parse;
babel 7 proposal
can you add dev dependencies
npm i -D #babel/core #babel/preset-env #babel/register
and add a .babelrc in the root
{
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
and add to the .js file
require("#babel/register")
or if you run it in the cli, you could use the require hook as -r #babel/register, ex.
$node -r #babel/register executeMyFileWithESModules.js
When I was started with express always wanted a solution to use import instead require
const express = require("express");
// to
import express from "express"
Many time go through this line:- Unfortunately, Node.js doesn't support ES6's import yet.
Now to help other I create new two solutions here
1) esm:-
The brilliantly simple, babel-less, bundle-less ECMAScript module loader.
let's make it work
yarn add esm / npm install esm
create start.js or use your namespace
require = require("esm")(module/*, options*/)
// Import the rest of our application.
module.exports = require('./src/server.js')
// where server.js is express server start file
Change in your package.josn pass path of start.js
"scripts": {
"start": "node start.js",
"start:dev": "nodemon start.js",
},
"dependencies": {
+ "esm": "^3.2.25",
},
"devDependencies": {
+ "nodemon": "^1.19.2"
}
2) Babel js:-
This can be divide into 2 part
a) Solution 1 thanks to timonweb.com
b) Solution 2
use Babel 6 (older version of babel-preset-stage-3 ^6.0)
create .babelrc file at your root folder
{
"presets": ["env", "stage-3"]
}
Install babel-preset-stage-3
yarn add babel-cli babel-polyfill babel-preset-env bable-preset-stage-3 nodemon --dev
Change in package.json
"scripts": {
+ "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+ "start": "npm run build && node ./build/index.js",
+ "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+ "clean": "rm -rf build && mkdir build"
},
"devDependencies": {
+ "babel-cli": "^6.26.0",
+ "babel-polyfill": "^6.26.0",
+ "babel-preset-env": "^1.7.0",
+ "babel-preset-stage-3": "^6.24.1",
+ "nodemon": "^1.19.4"
},
Start your server
yarn start / npm start
Oooh no we create new problem
regeneratorRuntime.mark(function _callee(email, password) {
^
ReferenceError: regeneratorRuntime is not defined
This error only come when you use async/await in your code.
Then use polyfill that includes a custom regenerator runtime and core-js.
add on top of index.js
import "babel-polyfill"
This allow you to use async/await
use Babel 7
Need to upto date every thing in your project
let start with babel 7
.babelrc
{
"presets": ["#babel/preset-env"]
}
Some change in package.json
"scripts": {
+ "start:dev": "nodemon --exec babel-node -- ./src/index.js",
+ "start": "npm run build && node ./build/index.js",
+ "build": "npm run clean && babel src -d build -s --source-maps --copy-files",
+ "clean": "rm -rf build && mkdir build",
....
}
"devDependencies": {
+ "#babel/cli": "^7.0.0",
+ "#babel/core": "^7.6.4",
+ "#babel/node": "^7.0.0",
+ "#babel/polyfill": "^7.0.0",
+ "#babel/preset-env": "^7.0.0",
+ "nodemon": "^1.19.4"
....
}
and use import "#babel/polyfill" on start point
import "#babel/polyfill"
import express from 'express'
const app = express()
//GET request
app.get('/', async (req, res) {
// await operation
res.send('hello world')
})
app.listen(4000, () => console.log('🚀 Server listening on port 400!'))
Are you thinking why start:dev
Seriously. It is good question if you are new. Every change you are boar with start server every time
then use yarn start:dev as development server every change restart server automatically for more on nodemon
if you can use 'babel', try to add build scripts in package.json(--presets=es2015) as below. it make to precompile import code to es2015
"build": "babel server --out-dir build --presets=es2015 && webpack"
As of Node.js v12 (and this is probably fairly stable now, but still marked "experimental"), you have a couple of options for using ESM (ECMAScript Modules) in Node.js (for files, there's a third way for evaling strings), here's what the documentation says:
The --experimental-modules flag can be used to enable support for
ECMAScript modules (ES modules).
Once enabled, Node.js will treat the following as ES modules when passed to
node as the initial input, or when referenced by import statements within
ES module code:
Files ending in .mjs.
Files ending in .js, or extensionless files, when the nearest parent
package.json file contains a top-level field "type" with a value of
"module".
Strings passed in as an argument to --eval or --print, or piped to
node via STDIN, with the flag --input-type=module.
Node.js will treat as CommonJS all other forms of input, such as .js files
where the nearest parent package.json file contains no top-level "type"
field, or string input without the flag --input-type. This behavior is to
preserve backward compatibility. However, now that Node.js supports both
CommonJS and ES modules, it is best to be explicit whenever possible. Node.js
will treat the following as CommonJS when passed to node as the initial input,
or when referenced by import statements within ES module code:
Files ending in .cjs.
Files ending in .js, or extensionless files, when the nearest parent
package.json file contains a top-level field "type" with a value of
"commonjs".
Strings passed in as an argument to --eval or --print, or piped to
node via STDIN, with the flag --input-type=commonjs.
I'm going to address another problem within the original question that no one else has. After recently converting from CommonJS to ESM in my own NodeJS project, I've seen very little discussion about the fact that you cannot place imports wherever you want, like you could with require. My project is working great with imports now, but when I use the code in the question, I first get an error for not having a named function. After naming the function, I receive the following...
import express from 'express'
^^^^^^^
SyntaxError: Unexpected identifier
at Loader.moduleStrategy (internal/modules/esm/translators.js:88:18)
You cannot place imports inside functions like you could require. They have to be placed at the top of the file, outside code blocks. I wasted quite a bit of time on this issue myself.
So while all of the above answers are great at helping you get imports to work in your project, none address the fact that the code in the original question cannot work as written.
import statements are supported in the stable release of Node since version 14.x LTS.
All you need to do is specify "type": "module" in package.json.
In my case it was looking after .babelrc file, and it should contain something like this:
{
"presets": ["es2015-node5", "stage-3"],
"plugins": []
}
My project uses node v10.21.0, which still does not support ES6 import keyword. There are multiple ways to make node recognize import, one of them is to start node with node --experimental-modules index.mjs (The mjs extension is already covered in one of the answers here). But, this way, you will not be able to use node specific keyword like require in your code. If there is need to use both nodejs's require keyword along with ES6's import, then the way out is to use the esm npm package. After adding esm package as a dependency, node needs to be started with a special configuration like: node -r esm index.js
I've been trying to get this working. Here's what works:
Use a recent node version. I'm using v14.15.5. Verify your version by running: node --version
Name the files so that they all end with .mjs rather than .js
Example:
mod.mjs
export const STR = 'Hello World'
test.mjs
import {STR} from './mod.mjs'
console.log(STR)
Run: node test.mjs
You should see "Hello World".
Simply install a higher version of Node. As till Node v10 es6 is not supported. You need to disable a few flags or use
I'm writing some mocha tests that load code that have paths like this:
import MyStore from "stores/MyStore"
This works fine in the web browser because we are using the webpack-dev-server which in turn reads this entry from webpack.config.js: config.resolve.root: [path.resolve(__dirname, "./app")] so it knows to find ./app/stores/MyStore.
This path does not work when running it from mocha --compilers js:babel/register. I'm trying to locate a package or configuration that I may use for this. It would save us from having to change may code references and of course keep our imports more portable.
Not sure if it matters, we use iojs. If this really can't be done it would be fine just to update the paths. Thank you...
How about including your app directory in $NODE_PATH:
env NODE_PATH=$NODE_PATH:$PWD/app mocha ...
Here's a cross-platform method. First install cross-env:
npm install cross-env --save-dev
then in your package.json:
"scripts": {
...
"test": "cross-env NODE_PATH=./app mocha ..."
}
In windows, I had to do this:
set NODE_PATH=%CD%/app&& mocha...
for some reason, adding a space after 'app' would cause it not to work