Javascript modules - Cannot use import statement outside a module - javascript

I am new to Javascript and I am trying to learn modules from a tutorial. In have a folder in visual studio code/VScode which has two files, script.js & external.js.
Script.js imports content from external.js and prints text to console. I get the below error when I run script.js from vs code, with node.js run configuration. Can someone please tell me why this happens and how to fix it ? In comparison, imports in Java are simple.
import {keyValue} from './external.js';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1070:16)
at Module._compile (internal/modules/cjs/loader.js:1120:27)
external.js :
export let keyValue = 1000;
script.js :
import {keyValue} from './external.js';
console.log(keyValue);
UPDATES :
Node version - v12.16.2, upgraded to v14.4.0.

What's the version of node.js?
If node.js is version 13 or above, you can do either:
add { type: "module" } to package.json.
{
...
scripts: "...",
type: "module"
}
rename .js to .mjs
If it's under 13, rename .js to .mjs, and run with additional params --experimental-modules.
node --experimental-modules script.js
Or
You can also fix the import statement outside a module issue
by not using the import statement and using the dynamic import function instead.
script.js
import("./external.js").then((module) => {
console.log(module.keyValue);
});
This form also supports the await keyword.
let module = await import('./external.js');
console.log(module.keyValue)

it's because you are using es6 modules instead of the default module system for node which is common js. you could either use babel to transpile it or to use the .mjs extension

Related

How to use TypeScript w/ a library with no definition file?

So I’m trying to use the pino-clf library in my koa TS project.
I keep getting this when I try to compile:
TSError: ⨯ Unable to compile TypeScript:
src/modules/logger/index.ts:5:21 - error TS7016: Could not find a declaration file for module 'pino-clf'. '/dev/webservices/node_modules/pino-clf/index.js' implicitly has an 'any' type.
Try `npm i --save-dev #types/pino-clf` if it exists or add a new declaration (.d.ts) file containing `declare module 'pino-clf';`
5 import pinoClf from 'pino-clf'
~~~~~~~~~~
pino-clf doesn’t have a def file and there’s no #types/pino-clf available.
I tried adding a pino-clf.d.ts file in the folder of the file that I’m importing the lib into w/ declare module 'pino-clf' in it. While that got the red squigglies in my IDE to go away, TS still refuses to compile.
How in the world do we use use a lib that’s just plain JS w/ TS and w/o adding a ts-ignore?
So there are two ways this can be accomplished.
Solution One: Probably the easiest
You can just use require ex: const pinoClf = require("pinoClf") - the down-side is that dot reference or intellisense isn't available but if you know the methods you want to use its no biggie.
Solution Two:
Create you own typeDef file in the root of you project. For example,
pino-clf.custom.d.ts
declare module "pino-clf.custom" {
const pinoClfJs = require("pinoClf");
export default class pinoClf {
commonLog (type: string, dest: NodeJS.WriteStream, ancillary: any): void {
pinoClfJs.commonLog(type, dest, ancillary);
}
}
}
then in you tsconfig.json file include the new typeDef file:
{
... // assuming src is already there
"include": [
"src", "pino-clf.custom.d.ts"
]
}
after that you can simply import it import pinoClf from "pino-clf.custom";
This is a very basic implementation, and recommend researching if you desire something more complex. Of course there is more than one way to solve a problem but, I hope this helped. Cheers.

CLI for todo App - help debugging current solution using Commander or change approach to Readline and Event Emitter?

I am trying to build a CLI for a node js only todo app using commander and conf modules in node js, with chalk to colour the output . I am not sure how to resolve the errors being returned:
ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension
contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
I'm getting the above error for both conf and commander
Any suggestions on how I could go about debugging this, or changing approach to using readline and events/EventEmitter would be better, will be appreciated, Thanks
Below is a REDACTED version of code:
list.js
const conf = new (require('conf'))();
const chalk = require('chalk');
function list() {
const todoList = conf.get('todo-list');
if (todoList && todoList.length) {
console.log(
chalk.blue.bold(
'Tasks in green are done. Tasks in yellow are still not done.'
)
}
}
module.exports = list;
index.js file
const { program } = require('commander');
const list = require('./list');
program.command('list').description('List all the TODO tasks').action(list);
program.command('add <task>').description('Add a new TODO task').action(add);
program.parse();
package.json file
{
"main": "index.js",
"type": "module",
"keywords": [],
"dependencies": {
"chalk": "^5.0.0",
"chalk-cli": "^5.0.0",
"commander": "^8.3.0",
"conf": "^10.1.1"
},
"bin": {
"todos": "index.js"
}
}
In your package.json you have:
"type": "module",
This means files with the .js suffix are assumed to be ECMAScript rather than CommonJS. If you want to use CommonJS you can change the file suffix or change the "type" property.
Or you can use the new syntax. In ECMAScript you use import, in CommonJS you use require.
To read more about "type" see: https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#determining-module-system
After some more research I found out I was 'muddying the waters' between CJS or ESM modules.
CJS modules use require and that is the old way of doing things prior to ES6 modules
ESM modules use import
My package.json says type: module telling NodeJS that I am using ESM. But the code is saying CJS.
These are the steps I take to fix this:
rename index.js to index.mjs
update package.json accordingly
replace all require calls with import statements
replace module.exports = list with default export = list (or used a named export)

TypeScript "import { myVar }" syntax seems to be incorrectly compiling in a Node/CommonJS/ES5 app

In my Node application, I have a settings file that exports some settings as an object like this:
// settings.ts
export var settings = {
port: 1234
}
In another file, I import these settings and attempt to reference the port property:
// another-file.ts
import { settings } from './settings';
console.log(settings.port);
This code compiles correctly, but at runtime I get the following error:
Cannot read property 'port' of undefined
When I inspect the compiled code, I can see that this is happening because my second file above is compiling to this:
var settings_1 = require("./settings");
console.log(settings_1.settings.port);
If I walk through the compiled code with my debugger, I can see that the settings_1 variable points to the exported value from settings.ts. In other words, my port property lives at settings_1.port, not at settings_1.settings.port. It seems the TypeScript compiler should instead generated this JavaScript code:
var settings = require("./settings");
console.log(settings.port);
Am I doing something wrong? Or is the TypeScript compiler incorrectly compiling my import?
I know that the TypeScript compiler is correctly type-checking my import; if I do something like this:
import { settings } from './settings';
console.log(settings.propertyThatDoesNotExist);
I get compiler errors that propertyThatDoesNotExist doesn't exist.
I'm using TypeScript 2.3.2, targeting "es5" and outputting "commonjs" modules, running on Node 6.9.2.
Figured it out. It was a silly mistake on my part (isn't it always?). I was working on converting an application from JavaScript to TypeScript, and I copied and renamed settings.js to settings.ts... but I didn't delete settings.js. As a result, I was actually importing my old settings.js file which had its exports set up differently.
Once I deleted settings.js, my application started correctly using the .ts file instead, and my imports worked as expected.

Integrating React components with Pux - where does require() come from?

The Pux documentation tells me to use require() in the browser. Where does that function come from and how do I use it?
Background:
I'm trying to integrate the Quill editor with my web application that uses purescript-pux.
Following the Pux documentation I created a file MyEditor.js like this:
// module MyEditor
var React = require("react");
var Pux = require("purescript-pux");
var MyEditor = React.createClass({
displayName: "MyEditor",
onTextChange: function onTextChange(value) {
this.setState({ text: value });
},
render: function render() {
return React.createElement(ReactQuill, { value: this.state.text,
onChange: this.onTextChange });
}
});
exports.fromReact = Pux.fromReact(MyEditor);
and a file MyEditor.purs as follows:
module MyEditor where
import Pux.Html (Html, Attribute)
foreign import fromReact :: forall a. Array (Attribute a) -> Array (Html a) -> Html a
I then use MyEditor.fromReact [value p.description] in my Html Action and the code compiles, but the browser complains about ReferenceError: require is not defined.
I'm not very familiar with the javascript ecosystem. I'm aware that several libraries providing a require() function exist, but which one do I use with Pux and how?
require is the NodeJS way of importing modules, it's not supported in the browser so you'll need to run your project through a bundler like browserify or webpack to produce a bundle that the browser can understand.
If you are using the pulp build tool it's as simple as running
pulp browserify --to app.js
and then loading app.js in your html through a script tag.
pulp browserify documentation: https://github.com/bodil/pulp#commonjs-aware-builds
In addition to Christophs answer (but can't comment since comments don't allow code blocks):
Using Thermite 4.1.1 this worked for me:
add a package.json file with:
{
"dependencies": {
"react": "^0.14",
"react-dom": "^0.14"
}
}
run npm install
from then on pulp browserify --optimise gets the whole shebang packaged.
This is really badly documented and I opened an issue about that on purescript-react.

Rollup via CLI: Treating as external dependency

I'm trying to bundle everything into one single file with rollupjs.
main.js file:
import * as ex from 'example-export';
ex.alertMe();
example-export.js file:
export function alertMe() {
alert('alert!');
};
The command below and it's response:
karl#karl-ux303ln:~/dev/sketch/experiment/socketio$ rollup ./public/js/main.js --output ./public/js/bundle.js --format iife --sourcemap inline
Treating 'example-export' as external dependency
No name was provided for external module 'example-export' in options.globals – guessing 'ex'
The bundle.js file produced:
(function (ex) {
'use strict';
ex.alertMe();
}(ex));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlLmpzIiwic291cmNlcyI6WyJtYWluLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGV4IGZyb20gJ2V4YW1wbGUtZXhwb3J0JztcblxuZXguYWxlcnRNZSgpOyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxFQUFFLENBQUMsT0FBTyxFQUFFLDs7In0=
I was expecting the example-export module to be included in the bundle.js file. Since this is really new stuff the internet lacks proper examples of this.
I expect the issue has something to do with the --name argument https://github.com/rollup/rollup/wiki/Command-Line-Interface#usage. I cannot however figure out how it's supposed to be used. And let's say if I have multiple exports and imports, how will that look?
Relative path
If the file is in the same directory:
import * as ex from './example-export';
Via NODE_PATH
If the NODE_PATH env variable is set, then you may add a path from that.
If the NODE_PATH is equal to /home/karl/myprojects/mynodeproject/
The library your trying to access is located at /home/karl/myprojects/mynodeproject/src/lib/my_library.js
And the file you are writing which is currently trying to import my_library is at /home/karl/myprojects/mynodeproject/src/index.js
Then you can use the following in index.js:
import * as ex from 'src/lib/example-export';
I have tried the example through the Rollup playground page, only thing I needed to change to get it working was change the
import * as ex from 'example-export';
to
import * as ex from './example-export';
Take a look here

Categories

Resources