532

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
3
  • 4
    Use transpiler like Babel to use import in Nodejs as it is not natively supported in nodejs.There is best alternative of import is require so go with that. Commented Sep 8, 2017 at 14:40
  • Checkout support for import () the nodejs v16 - nodejs.org/api/packages.html
    – human
    Commented Apr 26, 2021 at 4:13
  • 1
    @BHUVNESHKUMAR: Is your statement still correct in 2022? Commented Mar 23, 2022 at 20:14

18 Answers 18

597

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.

12
  • 2
    does anyone know if node 10 will ship with support enabled by default? (due for debut next month)
    – Hartmut
    Commented Mar 30, 2018 at 14:26
  • 2
    @Scimonster......node --experimental-modules my-app.mjs (node:12176) ExperimentalWarning: The ESM module loader is experimental. { Error: Cannot find module /C:/Users/WittyParrot/Documents/card-test-project/src/my-app.mjs at search (internal/modules/esm/DefaultResolve.js:23:12)test-project/src/my-app.mjs at search (internal/modules/esm/DefaultResolve.js:23:12)....throwing a warning could not find my-app.js....please suggest....i installed node version 9.11.1
    – Leo
    Commented Apr 24, 2018 at 10:22
  • 5
    Still requires a flag in v12 nodejs.org/api/esm.html#esm_ecmascript_modules
    – ABabin
    Commented May 1, 2019 at 19:19
  • 1
    Seems Node v13.2.0 can't import or import() ES modules as '.js' except when there's a package.json with type: module somewhere above it. esm still has utility in those cases.
    – jiku
    Commented Dec 4, 2019 at 4:16
  • 2
    Off topic, but I can't install node 14, because it no longer supports windows 7. It's sad, that if I want full support for import/export without any flags, then I have to upgrade my operating system. Commented May 27, 2020 at 22:52
68

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.

2
  • 9
    import is not necessarily a feature of TypeScript. TypeScript is ES6 with typings. So stuff like import is ES6 native.
    – borislemke
    Commented Nov 16, 2016 at 6:11
  • 2
    Node now supports this natively so this answer is out of date
    – Liam
    Commented Mar 2, 2021 at 8:54
59

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.

4
  • How do I use esm to debug with the Visual Studio Code debugger? I want to press F5 and start debugging js in VSCode directly.
    – pashute
    Commented Sep 6, 2020 at 18:29
  • 1
    If you're using nodemon, update your npm script to nodemon -r esm app.js to get automatic reloads with this solution.
    – Jesse Q
    Commented Sep 10, 2020 at 5:26
  • 1
    Wow. I did not believe this was true, but it is. Commented Mar 8, 2021 at 18:44
  • 1
    I just tried it on a complex project after losing a significant time trying other options, and wow, this works just fine ! Thanks Commented Nov 11, 2022 at 16:40
39

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"
    }
2
36

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;

2
  • 1
    I wish you would have explained the export default part a little more. I am having trouble with that part. The import works great with your answer.
    – JoeGalind
    Commented Feb 24, 2018 at 23:26
  • There is an answer before my answer which has an explanation. But for clarification Node does not support ES6 syntax. When you say Import ... you're using ES6 syntax Commented Feb 26, 2018 at 0:40
21

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;
3
  • 5
    not true if you are (as is likely the case) using the export keyword Commented Jan 28, 2019 at 8:39
  • @DanielThompson Sorry if this can be missunderstanding, I'm just giving a workaround for this case, if you work without the export keyword, anyways thanks for your helpful note!
    – Alberto
    Commented Oct 10, 2019 at 10:27
  • 1
    Working for me. Thanks
    – Ali Azhar
    Commented Mar 18, 2020 at 5:48
15

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
1
  • 2
    Installing @babel/preset-env and adding it to .babelrc made the trick. No need for @babel/register plugin in my case.
    – Marcos R
    Commented Jun 14, 2019 at 19:28
10

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

9

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"
2
  • but will my call to npm start first do the "build", or first do the "start"? (The start is currently defined: "nodemon src/app.js --exec \"npm run lint && node\"",
    – pashute
    Commented Sep 4, 2018 at 9:52
  • if i run this cmd, it shows server doen't exist error Commented Dec 10, 2018 at 6:22
9

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.

7

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.

1
  • thanks, that was the issue, though very annoying. my import list at the top is going to be 100 lines long. makes it easier to manage when everything that has to do with a particular API call is all in one spot
    – Zackattack
    Commented Apr 20, 2022 at 0:01
4

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.

2
  • I use node 14.17.5 but canot use import.
    – e-info128
    Commented Aug 14, 2021 at 0:54
  • It's supported. But not without extra config. You still either need to specify "type": "module" as I mentioned or use .mjs extension for your file. Commented Aug 16, 2021 at 16:58
3

In my case it was looking after .babelrc file, and it should contain something like this:

{
  "presets": ["es2015-node5", "stage-3"],
  "plugins": []
}
1

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

1

I've been trying to get this working. Here's what works:

  1. Use a recent node version. I'm using v14.15.5. Verify your version by running: node --version
  2. 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".

0

The best option so far I found after all experiment is Babel which is a production-ready solution and very easy to implement

First install npm i @babel/core @babel/preset-env @babel/register

Create a .babelrc file in the root of your project

{ "presets": [ "@babel/preset-env" ] }

Create a main.js file and provide an entry point

require('@babel/register')({}) module.exports = require('./app.js')

Package.json

"scripts": { "start": "node app.js", "dev": "nodemon app.js" }

and now you are good to use import syntax without changing the file extension

Reffernce link > https://github.com/Aakashdeveloper/May_Node_Mrng_23/tree/master/weatherapp

0

using nodejs v20

save the files with extension .mjs rather than .js

to import use statement

import {source_func} from './source_file.mjs'
-2

Simply install a higher version of Node. As till Node v10 es6 is not supported. You need to disable a few flags or use

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.