"Uncaught SyntaxError: Cannot use import statement outside a module" when importing ECMAScript 6
Asked Answered
B

34

1228

I'm using ArcGIS JSAPI 4.12 and wish to use Spatial Illusions to draw military symbols on a map.

When I add milsymbol.js to the script, the console returns error

Uncaught SyntaxError: Cannot use import statement outside a module`

so I add type="module" to the script, and then it returns

Uncaught ReferenceError: ms is not defined

Here's my code:

<link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/css/main.css">
<script src="https://js.arcgis.com/4.12/"></script>
<script type="module" src="milsymbol-2.0.0/src/milsymbol.js"></script>

<script>
    require([
        "esri/Map",
        "esri/views/MapView",
        "esri/layers/MapImageLayer",
        "esri/layers/FeatureLayer"
    ], function (Map, MapView, MapImageLayer, FeatureLayer) {

        var symbol = new ms.Symbol("SFG-UCI----D", { size: 30 }).asCanvas(3);
        var map = new Map({
            basemap: "topo-vector"
        });

        var view = new MapView({
            container: "viewDiv",
            map: map,
            center: [121, 23],
            zoom: 7
        });
    });
</script>

So, whether I add type="module" or not, there are always errors. However, in the official document of Spatial Illusions, there isn't any type="module" in the script. I'm now really confused. How do they manage to get it work without adding the type?

File milsymbol.js

import { ms } from "./ms.js";

import Symbol from "./ms/symbol.js";
ms.Symbol = Symbol;

export { ms };
Bifid answered 3/10, 2019 at 3:20 Comment(2)
This question is in the top 10 of all 21,642,537 questions on Stack Overflow in terms of view rate (presumably from search engine hits). It has got about 1800 views per day over its lifetime.Streamer
@PeterMortensen Probably because the title made it look like much more generic than it actually is.Tremulous
T
764

Update For Node.js / NPM

Add "type": "module" to your package.json file.

{
  // ...
  "type": "module",
  // ...
}

Note: When using modules, if you get ReferenceError: require is not defined, you'll need to use the import syntax instead of require. You can't natively mix and match between them, so you'll need to pick one or use a bundler if you need to use both.

Timber answered 3/11, 2020 at 0:27 Comment(2)
Yes. Basically, don't run TypeScript scripts independently, but put them in an existing Angular project and things will work fine ;-)Disario
@Disario Escape the loopCourtyard
T
622

I got this error because I forgot the type="module" inside the script tag:

<script type="module" src="whatever.js"></script>
Titanic answered 3/11, 2019 at 10:43 Comment(2)
THANKS. do you know why this doesn't work if i add "type": "module" to my package.json?Ricker
@backwardforward this is because package.json is for nodejs, which runs on the server. your problem is happening when the script is loaded in the browser.Paugh
E
227

It looks like the cause of the errors are:

  1. You're currently loading the source file in the src directory instead of the built file in the dist directory (you can see what the intended distributed file is here). This means that you're using the native source code in an unaltered/unbundled state, leading to the following error: Uncaught SyntaxError: Cannot use import statement outside a module. This should be fixed by using the bundled version since the package is using rollup to create a bundle.

  2. The reason you're getting the Uncaught ReferenceError: ms is not defined error is because modules are scoped, and since you're loading the library using native modules, ms is not in the global scope and is therefore not accessible in the following script tag.

It looks like you should be able to load the dist version of this file to have ms defined on the window. Check out this example from the library author to see an example of how this can be done.

Exploration answered 3/10, 2019 at 4:31 Comment(4)
Thank you for your reply, now I know I have the wrong file. I've been looking for the dist version of the file but with no result. Do you know any way to get the dist version? Thanks so much!Bifid
It's available for download on npm (npmjs.com/package/milsymbol). Alternatively, you could build it yourself by cloning the repo and running one of the build scripts. It looks like there's an AMD build script (github.com/spatialillusions/milsymbol/blob/master/…) that should allow you to require the built package directly into your code.Exploration
I've downloaded through npm, now I have script : <script src="node_modules/milsymbol/dist/milsymbol.js"></script>, but the console still returns Uncaught ReferenceError: ms is not defined. The issue is ms is not defined in the dist/milsymbol.js, it's defined in src/milsymbol.js, but it requires type="module" and will cause scope problem. Is there any solution for this. Thanks so much!Bifid
What if thats the actual intention, referencing it from /src. As the author is not planning to expose a property of a class for example..Lott
C
114

I resolved my case by replacing import with require:

// import { parse } from 'node-html-parser';
const parse = require('node-html-parser');
Chorea answered 15/5, 2020 at 0:22 Comment(6)
const {parse} = require('node-html-parser'); worked for meAlidus
What is the explanation? Why does this work? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).Streamer
the question was about browserSibel
This answer is useful in NodeJs if you want to keep it old school. But it's not related to the questionHugo
How are answers like that real? a) This is 100 % NOT A SOLUTION TO A PROBLEM b) Where is the explanation of what is happening?Prognosticate
I believe the reason involves es vs commonjs modulesBechance
G
96

There are several common ways to resolve the conflict associated with the above issue

1. The first: In the script, include type=module

<script type="module" src="milsymbol-2.0.0/src/milsymbol.js"></script>

This is the most recommended way to fix the issue
By adding the type="module" attribute, you are telling the browser that the script should be treated as an ECMAScript module, and it should use the appropriate rules for resolving dependencies and executing the code.


2. The second: In node.js, into your package.json file

{
  "type": "module",
}

Restart the project npm start


3. The third: replace import by require()

Try this

import { parse } from 'node-html-parser';
parse = require('node-html-parser');

Else try this

// import { parse } from 'node-html-parser';
parse = require('node-html-parser');
Griffe answered 9/11, 2021 at 13:33 Comment(4)
What if all 3 of those don't work. I want a simple api.js file with tons of reusable global functions that I don't want to have to import one at a time ever. ie: <script id="apijs" src="%PUBLIC_URL%/api.js"></script>Henke
Are these 3 ways AND or OR. And how to use these in NextJS .Uppish
Adding "type": "module" in package.json works with node v18.Antecede
@Uppish these are the 3 ways which are the most common fix for the conflict with the above issueGriffe
C
62

I was also facing the same issue until I added the type="module" to the script.

Before it was like this

<script src="../src/main.js"></script>

And after changing it to

<script type="module" src="../src/main.js"></script>

It worked perfectly.

Chufa answered 3/4, 2020 at 15:59 Comment(6)
Getting CORS on doing thisUrolith
Meaning you're requesting from another domain. You can fix that by adding Access-Control-Allow-Origin: * in your headers. You can check the MDN docs about CORS at developer.mozilla.org/en-US/docs/Web/HTTP/….Chufa
no i know about cors , the thing is these are my local filesUrolith
You need to serve your script in an http server, browsers use an http request to load es6 modules, the server needs to respond in the header a CORS allowing your origin.Flatworm
the simplest way: you can use http-server: https://mcmap.net/q/45417/-using-node-js-as-a-simple-web-serverFlatworm
This answer was already given: https://mcmap.net/q/45488/-quot-uncaught-syntaxerror-cannot-use-import-statement-outside-a-module-quot-when-importing-ecmascript-6Pharynx
T
61

Applicable for node 12. This answer is no longer maintained for new node versions. Feel free to comment solutions for more recent versions.

I solved this issue by doing the following:

When using ECMAScript 6 modules from the browser, use the .js extension in your files, and in the script tag add type = "module".

When using ECMAScript 6 modules from a Node.js environment, use the extension .mjs in your files and use this command to run the file:

node --experimental-modules filename.mjs

Edit: This was written when node12 was the latest LTS, this does not apply to node 14 LTS.

Teutonize answered 5/2, 2020 at 9:56 Comment(4)
Modules: ECMAScript modules: Enabling https://nodejs.org/api/esm.html#esm_enablingGivens
This is no longer necessary. Simply add "type": "module" to your package.json and everything will work as expected. (Use .js for filename extensions)Firsthand
We can use .cjs files as well.Stpierre
Must add that I was only getting this error when running my jest tests. I had to add file jest.config.mjs (specifically mjs extension) to resolve this issue.Harley
S
33

I don't know whether this has appeared obvious here. I would like to point out that as far as client-side (browser) JavaScript is concerned, you can add type="module" to both external as well as internal js scripts.

Say, you have a file 'module.js':

var a = 10;
export {a};

You can use it in an external script, in which you do the import, eg.:

<!DOCTYPE html><html><body>
<script type="module" src="test.js"></script><!-- Here use type="module" rather than type="text/javascript" -->
</body></html>

test.js:

import {a} from "./module.js";
alert(a);

You can also use it in an internal script, eg.:

<!DOCTYPE html><html><body>
<script type="module">
    import {a} from "./module.js";
    alert(a);
</script>
</body></html>

It is worthwhile mentioning that for relative paths, you must not omit the "./" characters, ie.:

import {a} from "module.js";     // this won't work
Soiree answered 25/7, 2020 at 7:0 Comment(1)
For those arriving here with a Rails 7 problem. I found add the type="module" like so <%= javascript_include_tag 'someScript', type: "module" %>` where app/javascript/someScript.js. I didn't understand that this is something like a script tag. This moved the issue along to Uncaught TypeError: Failed to resolve module specifier "ol/Map". Relative references must start with either "/", "./", or "../".Cateran
A
25

If you want to use import instead of require() for modules, change or add the value of type to module in package.json file

Example:

package.json file

{
  "name": "appsample",
  "version": "1.0.0",
  "type": "module",
  "description": "Learning Node",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Chikeluba Anusionwu",
  "license": "ISC"
}
import http from 'http';

var host = '127.0.0.1',
    port = 1992,
    server = http.createServer();

server.on('request', (req, res) => {
  res.writeHead(200, {"Content-Type": "text/plain"});
  res.end("I am using type module in package.json file in this application.");
});

server.listen(port, () => console.log(
    'Listening to server ${port}. Connection has been established.'));
Arand answered 9/9, 2021 at 16:28 Comment(0)
N
22

For me, it was caused by not referencing a library (specifically typeORM, using the ormconfig.js file, under the entities key) to the src folder, instead of the dist folder...

   "entities": [
      "src/db/entity/**/*.ts", // Pay attention to "src" and "ts" (this is wrong)
   ],

instead of

   "entities": [
      "dist/db/entity/**/*.js", // Pay attention to "dist" and "js" (this is the correct way)
   ],
Nitrite answered 14/9, 2020 at 9:46 Comment(0)
O
16

I got this error in React and fixed it with the following steps:

  1. Go to the project root directory, and open the Package.json file for editing.

  2. Add "type":"module";

  3. Save it and restart the server.

Ordinate answered 4/1, 2021 at 10:24 Comment(0)
E
15

Add "type": "module", to your package.json file.

And restart your application:

npm start

Then your problem is solved.

Extol answered 7/9, 2021 at 4:39 Comment(5)
Is the comma part of it or not?Streamer
@PeterMortensen you are adding an item to a JSON object, items are delimited with commas, so unless you add it at the end you need a comma.Homosporous
But I'm not writing a module?Least
Missing script: "start"Cerotype
The question does not mention node.js at all.Tremulous
P
11

Why this occurs and more possible causes:

A lot of interfaces still do not understand ES6 JavaScript syntax/features. Hence there is need for ES6 to be compiled to ES5 whenever it is used in any file or project.

The possible reasons for the SyntaxError: Cannot use import statement outside a module error is you are trying to run the file independently. You are yet to install and set up an ES6 compiler such as Babel or the path of the file in your runscript is wrong/not the compiled file.

If you will want to continue without a compiler, the best possible solution is to use ES5 syntax, which in your case would be var ms = require(./ms.js);. This can later be updated as appropriate or better still set up your compiler and ensure your file/project is compiled before running and also ensure your run script is running the compiled file usually named dist, build or whatever you named it and the path to the compiled file in your runscript is correct.

Precede answered 5/1, 2021 at 4:44 Comment(2)
Thank you. This is one of only two answers that tries to get at the root cause. I would expect Node.js 15.5 to support this 2016 feature though, and yet I'm finding it doesn't?Trichromatism
This should be the accepted answer, because as @Trichromatism says, it is the only answer that goes to the root of the problem.Tonneson
P
10

I'm coding on vanilla JavaScript. If you're doing same, simply add a type="module" to your script tag.

That is, previous code:

<script src="./index.js"></script>

Updated code:

<script type="module" src="./index.js"></script>`
Pedaias answered 6/4, 2021 at 21:10 Comment(5)
Please do not repeat: https://mcmap.net/q/45488/-quot-uncaught-syntaxerror-cannot-use-import-statement-outside-a-module-quot-when-importing-ecmascript-6Pharynx
@Pharynx it's not duplicate of mentioned answer. As you can notice, this answer suggested to add type="module" for developer's script definition, your linked answer suggests to mark library's script definition. I've encountered the same error and solved it only using this answer.Loftin
The above answer suggests to add type="module", it says: ...because I forgot the type="module" inside the script tag, so does your answer. What is the exact difference?Pharynx
In addition, there is https://mcmap.net/q/45488/-quot-uncaught-syntaxerror-cannot-use-import-statement-outside-a-module-quot-when-importing-ecmascript-6,https://stackoverflow.com/…, https://mcmap.net/q/45488/-quot-uncaught-syntaxerror-cannot-use-import-statement-outside-a-module-quot-when-importing-ecmascript-6, https://mcmap.net/q/45488/-quot-uncaught-syntaxerror-cannot-use-import-statement-outside-a-module-quot-when-importing-ecmascript-6, etcPharynx
Duplicate to https://mcmap.net/q/45488/-quot-uncaught-syntaxerror-cannot-use-import-statement-outside-a-module-quot-when-importing-ecmascript-6Apc
C
9

For me this helped:

  1. In the .ts file I used: import prompts from "prompts";
  2. And used "module": "commonjs" in file tsconfig.json
Claire answered 21/6, 2021 at 19:50 Comment(2)
What .ts file is it?Streamer
It is any typeScript or JavaScript file your code needs some module import added.Claire
T
5

I have faced the same error by EXPO.

Mainly the solution is that to add "type": "module", in the package.json file.

my files, you can find two package.json

Code Image

However, you have to check that which is your correct package.json.

In my case, there are two package.json files, then you should add that to the server file.

To identify which is correct package.json, find "scripts": { "test": "echo \"Error: no test specified\" && exit 1" },

Below ↑ this line, add "type": "module",

Trevar answered 9/11, 2021 at 13:19 Comment(5)
What is "EXPO"?Streamer
expo.devTrevar
may i ask what that theme is : )Laddie
Sorry for the late reply, if my memory is correct, this theme is cyberpunk 2077 (beta). But I am not sure, I changed it sooner from the last comment.Trevar
LOL, I like the picturesTrevor
T
4

None of the provided answers worked for me, but I found a different solution from: How to enable ECMAScript 6 imports in Node.js

Install ESM:

npm install --save esm

Run with ESM:

node -r esm server.js
Thematic answered 11/10, 2021 at 16:27 Comment(0)
B
3

The error is triggered because the file you're linking to in your HTML file is the unbundled version of the file. To get the full bundled version you'll have to install it with npm:

npm install --save milsymbol

This downloads the full package to your node_modules folder.

You can then access the standalone minified JavaScript file at node_modules/milsymbol/dist/milsymbol.js

You can do this in any directory, and then just copy the below file to your /src directory.

Bodywork answered 3/11, 2019 at 21:30 Comment(1)
P
3

I ran into this error while trying to use import Express.js.

Instead of   import express from 'express';

I used   const express = require('express');

Pedaias answered 5/6, 2021 at 12:36 Comment(0)
A
3

Use this code. It worked well for me:

Add this script tag to file index.html:

<script type="module">
    import { ms } from "./ms.js";
    import Symbol from "./ms/symbol.js";
</script>
Addington answered 22/7, 2021 at 10:30 Comment(1)
E
2

In my case, I updated

"lib": [
      "es2020",
      "dom"
    ]

with

"lib": [
  "es2016",
  "dom"
]

in my tsconfig.json file.

Eviaevict answered 18/2, 2021 at 9:56 Comment(1)
Thank you, your comment lead me to install: @babel/preset-env, and with that npm install, I am able to use the import statement.Externalization
L
2

I had to import some data from an external file (JavaScript file), to my script.js file present in my HTML file.

File data.js

const data = {a: 1, b: 2}

By adding type=module I got CORS error.

I found out that I can import file data.js into my script.js file just by including file data.js inside my HTML file.

For example, previously my HTML file consists of

<script src="assets/script.js"></script>

As I required some data from file data.js, I just changed my HTML file to:

<script src="assets/data.js"></script>
<script src="assets/script.js"></script>

I.e., include file data.js before file script.js, giving access to my data variable inside file script.js.

Leatriceleave answered 15/1, 2022 at 11:40 Comment(2)
Could you show how you use data.js inside script.js? The script.js contains no import statements?Petromilli
@parsecer, Yes there are no import statements inside script.js file. For example. data.js can have const data_js_variable = 1 and we can use this variable inside script.js without the need of any import statements. We just have to include the js files in order inside our html file like<script src="assets/data.js"></script> <script src="assets/script.js"></script>Leatriceleave
B
1

Well, in my case, I didn't want to update my package.json file and change the file type to mjs.

So I was looking around and found out that changing the module in file tsconfig.json affected the result. My ts.config file was:

{
  "compilerOptions": {
    "target": "es2020",
    "module": "es2020",
    "lib": [
      "es2020",
    ],
    "skipLibCheck": true,
    "sourceMap": true,
    "outDir": "./dist",
    "moduleResolution": "node",
    "removeComments": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "baseUrl": "."
  },
  "exclude": [
    "node_modules"
  ],
  "include": [
    "./src/**/*.ts"
  ]
}

Like this and changing the module from "module": "es2020" to "module" : "commonjs" solved my issue.

I was using MikroORM and thought maybe it doesn't support any module above CommonJS.

Bacciform answered 25/7, 2021 at 10:53 Comment(0)
K
1

try add .babelrc

{
"presets": [
  [
    "@babel/env",
    {
      "targets": {
        "node": "12"
      },
      "modules": "commonjs"
    }
  ]
] }
Kolb answered 13/6, 2023 at 17:48 Comment(1)
Add the file or add something to the file?Streamer
S
1

If you're using NextJS, maybe your code should be use on the client (brower) side only. Try replace the component in the Page by a dynamic import with "ssr: false" like this in '/pages/my-page':

[...]
const MyClientSideOnlyComponent = dynamic(() => import('../components/Component'), {ssr: false});
    
return   <MyClientSideOnlyComponent/>
[...]

instead of

return <Component/>
Seay answered 12/1 at 13:11 Comment(0)
S
0

I thought I would add this note because it was not apparently obvious to me. You need to add type="module" to all script includes, not just the one you want to use for your utility file.

index.html:

<script type="module" src="js/controllers/utils.js"></script>
<script type="module" src="js/controllers/main.js"></script>`

main.js:

import myFunction from './utils.js

utils.js:

export default myFunction
Spousal answered 17/10, 2022 at 21:24 Comment(0)
E
0

if you want to import functions from module. let's say, main.js has func1 and func2 defined, and you want to import those to function to a new module say, test.js

Below will solve the problem.

main.js:

const func1 = () => {console.log('do sth in func1')};
const func2 = () => {console.log('do sth in func2')};

//at the end of module
//export specific functions here
module.exports = { func1, func2 };

test.js :

// import them here
const{ func1, func2} = require('./main.js');
func1();
func2();
Ewart answered 2/12, 2022 at 0:45 Comment(1)
survey.js -> main.jsTumbledown
S
0

Following worked, inline export gave issue but export at the end of fn following worked. const xxx = async(....)

module.exports = { xxx, };

Spinescent answered 2/5, 2023 at 17:25 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Struma
K
0

If you are facing the same issue in the Cucumber TypeScript framework then the below fix is working.

In the cucumber.json file, mention as below. Install the ts-node.

{
    "default":{
        "requireModule":[
            "ts-node/register"
        ]
    }
}
Kunkle answered 7/6, 2023 at 13:48 Comment(0)
D
-1

It's because you haven't exported. The .ts file requires an export class format, whereas in a .js file we would use the exports function.

So, we have to use var_name = require("<pathfile>") to use those file functions.

Dawkins answered 24/3, 2021 at 18:58 Comment(1)
Hello... Inspect // Watch ... Your answer is poorly elaborated. It is useful to insert an effective response, with codes and references. Concluding a practical and efficient solution. This platform is not just any forum. We are the largest help and support center for other programmers and developers in the world. Review the terms of the community and learn how to post;Shiloh
Y
-1

Use

<script type="module" src="/src/moduleA.js"></script>

instead of

<script>System.import("/src/moduleA.js")</script>
Yong answered 18/8, 2022 at 11:57 Comment(0)
A
-2

I've added this in the tsconfig.json file and it fixed it. I was having this issue when trying to run the mockttp!

"ts-node": {
    "compilerOptions": {
        "module": "commonjs"
    }
}
Aq answered 8/12, 2023 at 0:22 Comment(1)
What is "the mockttp"?Streamer
M
-6

Just add .pack between the name and the extension in the <script> tag in src.

I.e.:

<script src="name.pack.js">
    // Code here
</script>
Mohler answered 1/3, 2020 at 12:46 Comment(0)
B
-8

This error occurs when it fails in Babel transpile.

Brumal answered 10/11, 2021 at 8:57 Comment(2)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewGuenzi
This issue has nothing to do with bable transpileStrunk

© 2022 - 2024 — McMap. All rights reserved.