This question already has answers here:
SyntaxError: Cannot use import statement outside a module
(34 answers)
Closed last year.
So I am currently practicing with a trading bot on hardhat. My problem is, when I want to run my script this error shows up:
import './ABIConstants.js';
^^^^^^
SyntaxError: Cannot use import statement outside a module
with this suggestion:
(node:1284) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
However, when I do as it tells me and set "type":"module" I get this error:
hardhat.config.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename hardhat.config.js to end in .cjs, change the requiring code to use dynamic import() which is avakage.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).
And the errors continue as I do the above....etc....
How do I fix this?
Heres the command I am using to run the script if it helps
npx hardhat run scripts/ArbitrageBot.js
There are two kinds of modules in nodejs - the older CommonJS which uses require() to load other CommonJS modules and the newer ESM which uses import to load other ESM modules? There are a few ways to mix and match module types, but that requires some additional knowledge and it is always easier if all the modules in your project are of the same type. So, for us to offer specific advice on your project, we need to know everything that you're trying to use in your project and what module type they all are.
The specific error you first report in your question is because you are trying to use import to load other modules from a file that nodejs is assuming is a CommonJS module and it will not allow that. If everything you are programming with is CommonJS modules, then switch to use require() to load your module instead of import. But, if everything isn't CommonJS modules, then it may be a bit more complicated.
The file extension (.mjs or .cjs) can force a module type or the "type": xxx in package.json can force a type. By default, with neither of those in place nodejs assumes your top level module with a .js extension is a CommonJS module where you would use require() to load other CommonJS modules.
The second error you get when you tried to force your top level module to be an ESM module makes it sounds like the module you are trying to import is a CommonJS module.
So, if I had to guess, I'd say the file you are trying to import is a CommonJS file and therefore, life would be easiest if you made your top level file CommonJS. To do that, remove the "type": "module" from package.json and change your import someModule to require(someModule) instead. This will attempt to just let everything be CommonJS modules.
Related
I created a fresh Next.js project and followed the Uniswap Widget guideline.
// create next app
npx create-next-app#latest
// add Uniswap widget dependency
yarn add #uniswap/widgets
// add Uniswap widget code
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint} />
</div>
However, I get this error suggesting I should change React or Uniswap code to make it compatible with Next.js setup.
Is there anyway I can make this work without changing React or Uniswap libraries, as suggested by the error message?
error - Error [ERR_REQUIRE_ESM]: require() of ES Module /home/pomatti/pjs/uniswap/uniswap-widget/node_modules/#uniswap/widgets/node_modules/#web3-react/core/dist/cjs/index.js from /home/pomatti/pjs/uniswap/uniswap-widget/node_modules/#uniswap/widgets/dist/widgets.js not supported.
index.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /home/pomatti/pjs/uniswap/uniswap-widget/node_modules/#uniswap/widgets/node_modules/#web3-react/core/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).
I have a file, test.js with these lines of code inside:
import {blabla} from "./bla";
async function dataGenerator() {
..........
}
(async() => {
console.log('1')
await dataGenerator()
console.log('2')
})()
Note: Ignore the import structure. It is just fictive for the question. In my file the imports are auto.
When I'm trying to run from terminal with node test.js it returns error:
Cannot find module 'D:\bla' imported from D:\test.js
I have added into package.json the line: "type": "module". Without this it returns:
Cannot use import statement outside a module
I'm using node v14. How can I run the test.js without adding to all the imports ".js". There are functions in functions in functions and is complicated to add .js extension. Is there any npm to run it?
Node.js by default does not attempt to guess the file extension when using import for ES modules. This is different from CommonJS modules with require.
In the documentation for the ES module loader you can read how files are found on disk.
The heading 'Customizing ESM specifier resolution algorithm' states:
The --experimental-specifier-resolution=[mode] flag can be used to customize the extension resolution algorithm. The default mode is explicit, which requires the full path to a module be provided to the loader. To enable the automatic extension resolution and importing from directories that include an index file use the node mode.
I have created some npm modules and compile them to:
commonJS (using exports.default =) and
esm (using export default)
I set up my package.json like so:
main: "index.cjs.js",
module: "index.esm.js"
When I npm install the package and I simple import it like:
import myPackage from 'my-package'
It will automatically choose the main file, not the module.
My question:
Is there a way to import the module file instead when doing import myPackage from 'my-package' in a JavaScript file?
Why I choose the commonJS file for "main":
I noticed that using Node, importing an esm file is not possible because of export default, it has to be commonJS. I have some simple helper JS functions like this and this, and I would want them to be usable to the widest audience. That's why I chose cjs for the "main" path in package.json.
Why I define a separate "module" in package.json:
Lots of famous libraries like Vue.js are already doing this. See further information on this Stackoverflow thread:
What is the "module" package.json field for?
Why do I want to be able to import the "module" file instead of the "main" file:
There is currently a bug in Rollup where it will not properly show JSDoc comments when coding after having imported a cjs file, but it does work when importing a es file.
The workaround I want to avoid:
Just set "main" to the esm file in package.json, right? But then all users who are using my packages in Node apps will not be able to use it anymore...
→ I'm really confused about all this as well, but I think I did enough research to make sense of all it. That being said, if anyone knows a better approach or any other advice, please do tell me in the comments down below!!
Just don't use extension for main file and have es6 and CommonJS version as two separate files with the same name and in the same directory, but with different extension, so:
index.js // transpiled CommonJS code for old nodejs
index.mjs // es6 module syntax
and in package.json:
{
"main": "index"
}
If node is launched with --experimental-modules flag, it would use *.mjs file, otherwise *.js.
Nodejs does not support "module" but does support the newer "exports" spec.
https://nodejs.org/api/packages.html#exports
https://github.com/nodejs/node/blob/v16.14.0/lib/internal/modules/esm/resolve.js#L910
"exports": {
"import": "./main-module.js",
"require": "./main-require.cjs"
},
I'm trying to build a react application using rollup instead of browserify and babel. I realize I need to use the rollup-plugin-babel to transpile jsx, but when I tell rollup the format is iife, the final page loads with an error:
Uncaught ReferenceError: React is not defined
What do I need to add to the rollup.config.js to include the node modules I've installed in package.json in my final build?
Two options:
Include React as a separate <script> tag before your app bundle
Include rollup-plugin-node-resolve in your config file, to pull in dependencies from your node_modules folder.
If you take the second route you'll also need rollup-plugin-commonjs (to convert the CommonJS module into an ES module). I think you would also need to add import * as React from 'react' to each module that contained JSX, otherwise you'll continue to get the ReferenceError.
Note: you might be able to use rollup-plugin-buble to transpile JSX. It's similar to the Babel plugin but much faster (though it doesn't transpile every ES2015 feature)
So I know how to require and export modules in ES6. But for frameworks like Aurelia, the docs say that you require aurelia like so:
import {LogManager} from 'aurelia-framework';
Do I have to place a JS file named aurelia-framework in the folder where the JS file I'm executing it from resides, or does the import function work similiar to the require function in NodeJS/CommonJS?
According to this article ES6 modules spec only deals with loading modules that are present in the file path. Downloading these files (via NPM or by other means) is outside of scope of ECMAScript 6 modules spec. Nothing is said in the spec about supporting npm package includes (traversing the directory structure down to the /, one directory at a time, looking for a package.json file and then searching within the node_modules directory where package.json file is found). So while the import syntax is similar to commonJS style, the whole magic of looking for modules in the node_modules directory is not included.
So for your example to work, aurelia-framework must be a javascript file somewhere in your file system and it should contain an exports statement.
import {LogManager} from 'aurelia-framework'; // ./aurelia-framework.js
import {LogManager} from '../libs/aurelia-framework'; // ../libs/aurelia-framework.js
with Aurelia, you can install dependent libraries using jspm. you can see an example of that here. jspm will get the packages for you and bring them into subfolders in your project. jspm uses an index (stored in config.js) to know where to locate the files (similar to how requirejs, but works for amd, commonjs, and es6 modules).
there is also an example of using the aurelia libraries with requirejs amd loader. this example uses a bundle of aurelia libraries generated by r.js as shown here