Import class other file syntax error

Im facing this error:

SyntaxError: import declarations may only appear at top level of a module
in Webstorm.

When i have:

sketch.js
import Animal from "path to animal.js";

function setup() {
const dog = new Animal("dog");
dog.sayName();
  createCanvas(400, 400);
}

function draw() {
  background(220);
}

And Animal.js

class Animal {
   name;
 constructor(name) {
    this.name = name;
  }
  //Print Animal
  sayName() {
    console.log(this.name);
  }
}

export default Animal;

Any ideas please ?
Can someone explain how to import/export modules if its somekind different as JS ?

Thanks

I must admit I don’t fully understand how to use modules from the Processing IDE but I managed to get this to work

AnimalDemo.js

import Animal from "./animal.js";

function setup() {
    createCanvas(200, 200);
    const dog = new Animal("dog");
    // console.log(dog)
    dog.sayName();
}

function draw() {
    background(220);
}

window.setup = setup;
window.draw = draw;

animal.js

class Animal {
    constructor(name) {
        this.name = name;
    }
    //Print Animal
    sayName() {
        console.log(this.name);
    }
}

export default Animal;

Both these need to be loaded as modules so in the html file change the ā€˜type’ to ā€˜module’

  <!-- PLEASE NO CHANGES BELOW THIS LINE (UNTIL I SAY SO) -->
  <script language="javascript" type="text/javascript" src="libraries/p5.min.js"></script>
  <script language="javascript" type="module" src="animal.js"></script>
  <script language="javascript" type="module" src="AnimalDemo.js"></script>
  <!-- OK, YOU CAN MAKE CHANGES BELOW THIS LINE AGAIN -->

This was based on a reply by @GoToLoop in this discussion

2 Likes

Only the ā€œmainā€ module file requires to be loaded as <script type=module>.
The other modules are loaded via the import keyword.

In this case, ā€œAnimalDemo.jsā€ is the main module JS file, which loads ā€œanimal.jsā€ via:
import Animal from "./animal.js";

P.S.: It’s advisable to use the extension ā€œ.mjsā€ in order to let others know it’s not a regular JS file, but a Module JS file (MJS).

2 Likes

@GoToLoop thanks for that answer it worked perfectly in VSC. :+1:

The Processing IDE doesn’t seem to able to handle user files with the extension .mjs files but your solution still works if you leave the extensions as .js :grin:

2 Likes

I’ve tried p5js’s mode for the PDE twice or thrice and gave up!

Either i use a simple text editor (like Notepad3 or Kate) for small stuff or VSCode/VSCodium for larger stuff.

1 Like

But if its a class…whats the correcte name of file ???

In Webstorm it doesnt work for me… now appears: Se bloqueó la carga de un módulo de ā€œhttp://localhost:63342/libraries/classes/Animal.jsā€ debido a un tipo MIME no permitido (ā€œtext/htmlā€)

In index.html i have only:

If theres any dev here, should fix this in a near future…is bad to have this problems to import and export, so common thing, and so standarized…Its weird that p.js works different and lack of documetnation about it…( at least i didnt found any)

Thank for your job and help

In your original question, your class Animal is defined inside file " Animal.js".

B/c that class is exported as export default Animal;, you can import it inside your file ā€œsketch.jsā€ as:
import Animal from "./Animal.js";
Assuming both are located in the same folder.

Also, b/c it’s a ā€œdefault exportā€, you can use any other name in place of Animal:
import Pet from "./Animal.js";

As I’ve mentioned before, it’s advisable to use the extension ā€œ.mjsā€ for files that should be loaded as a module.

So, I’d rename ā€œAnimal.jsā€ to ā€œAnimal.mjsā€ and ā€œsketch.jsā€ to ā€œsketch.mjsā€.

This way, it’s clearer they require special loading strategy:
import Animal from "./Animal.mjs";

1 Like

Can you post your ā€œindex.htmlā€ file?

p5.js itself is a regular .js library file, not a module 1.

Indeed they’ve never yet cared about using ECMA module (.mjs) files in the browser!

But weirdly, they do care about Node.JS’ Common module (.cjs) files, even though p5.js isn’t a backend library, but a frontend 1!

1 Like

sure you can download the project ( dont be afraid is where im doing some tests…its almost empty)…Im teacher of vocational education in Computer Science…and im teaching JS…another thing as Animal is a class…should i use export class Animal ???

Error: Se bloqueó la carga de un módulo de ā€œhttp://localhost:63342/libraries/classes/PointCoord.jsā€ debido a un tipo MIME no permitido (ā€œtext/htmlā€).

In english: Page blocked because of a disallowed MIME type (ā€œtext/htmlā€)

Seems very strange: in the head of the index.html i write:

    <script src="/src/scriptindex.js"></script>
    <script src="/libraries/p5.min.js"></script>

Note the / at the beginning of the path…in this case.working fine…

But in the div of the canvas:

<div id="sketch-holder">
        <script src="src/sketch.js" type="module"></script>
    </div>

Works but

<div id="sketch-holder">
        <script src="/src/sketch.js" type="module"></script>
    </div>

With the / doesn’t work, also i have to write type=ā€œmoduleā€ in other tutorials don’t appear this type only:

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

Also i still think that window.setup = setup and window.draw=draw at the end of sketch.js should no be there…if you export and import a js file, just it, don’t know why window is doing here…

Any dev could fix this ?

Also seem that it has gone the tutorial were you setup your environment, linking html file with sketch.js…by now only appear the p5js web editor…but not any explanation about what to write in html file, and how to link to a sketch.js

Your ā€œCalculadora.zipā€ file had to many things in it.
I’ve removed most of it and edited the rest.
Also, I’ve created a GitHub repo for it here:

You can also check it running online on this link:

1 Like

1 - Your ā€œCalculadora.zipā€ file had to many things in it.
I’ve removed most of it and edited the rest.
Thanks for your effort, i told you, dont be afraid, most things were from HTML Boilerplate project template in Webstorm.

2 - Why async ? Ive never seen this, if i delete async is working fine in my computer

script async src="src/scriptindex.js"></script>

I prefer to use

 <script defer src="src/libraries/p5.min.js"></script>

instead of

<script defer src="//cdn.JsDelivr.net/npm/p5"></script>

I prefer to have it downloaded in the project,also Webstorm pop up a warning if library is not downloaded.
The defer also is not necessary no ?

4 - You renamed all to .mjs but according to @quark

The Processing IDE doesn’t seem to able to handle user files with the extension .mjs files but your solution still works if you leave the extensions as .js

5 - @GoToLoop are you a dev of processing ??

Ive to simplify as much as i can the code to my students (…and me)

Thanks

async
It makes a <script> tag to load in parallel while the page is still being processed & immediately run it as soon as its loading is finished.

The reason I’ve used the attribute async for ā€œscriptindex.jsā€ is b/c it doesn’t depend on any other file and no other file depends on it.

Actually, I could’ve used async for the p5.js loading as well in this particular case, given no p5.js library addon is present which would depend on it.

Both async & defer attributes are optional.
They’re used to lower the total loading time of the page.

I use a CDN link so I don’t need to have a copy of ā€œp5.min.jsā€ library on every single folder locally.

Well, never used that. I had no complaints from my text editor. :wink:

defer

  • Like async attribute, defer also loads a <script> in parallel w/ other async & defer scripts.
  • However, it defers its execution until the whole page is parsed & ready.
  • That’s the same default behavior as a ā€œtype=moduleā€ <script> btW.
  • But as you know by now, it’s totally optional. It’s merely for decreasing page loading time.

Not all: I’ve kept ā€œscriptindex.jsā€ as ā€œ.jsā€, b/c it’s the only non-module classic script type, besides the p5.js library.

The files ā€œsketch.mjsā€, ā€œAnimal.mjsā€ and ā€œpoint_coord.mjsā€ can’t be loaded w/ a regular <script> w/o adding the attribute ā€œtype=moduleā€.

The reason is b/c they contain the keywords import and/or export; thus turning them into an ECMA Script Module (ESM) instead:

Although renaming them to ā€œ.mjsā€ is optional, it’s a good practice of letting others know they aren’t classical non-module JS files, that they have different running behaviors.

Also, runtime servers like NodeJS, Deno, Bun, etc., recognize the ā€œ.mjsā€ extension name and change their import/export behavior accordingly.

The original, and now deprecated, NodeJS module is called CommonJS, and its official extension is ā€œ.cjsā€:

Nope! Actually it’s very rare to see any Processing devs here in this forum!

1 Like

You are helping me a lot

@GoToLoop

This weekend i had to make some kind of document with your teaching… :wink:

1 - p5.js could use defer or async which is better ? as far as i know we dont have here any promise to use await/async…

2 - Do you know any way to contact any dev ?

3 - Seems mjs is more node.js, as you can see im developing in browser environmen…still need or better said is recommended to use .mjs in modules( i understand modules as any .js with import or export in their code)

4 - Do you have any explanation about the / … why in most cases workd fine in p5 but in the loading of sketch.js you have to delete it ? perhaps a bug ?

Thanks… for now :wink:

  • Both attributes async & defer load a <script> w/o waiting for the page to be parsed.
  • The diff. is that async runs the script right after it’s finished loading.
  • While defer postpones its execution until the page is fully parsed.
  • If you don’t have other addons which can’t be run before p5.js has run, use defer for all of them; otherwise you’re free to use async for p5.js instead.

Those <script> tag attributes async & defer are used inside an HTML file. They’ve got nothing to do w/ JS files and its syntax.

All I know is their p5.js repo:

Although it’s true it’s more useful for Node.JS as a way to differentiate a CommonJS module from an ESM 1, ā€œ.mjsā€ is ECMA’s official extension name for a JS script that acts as a ESM module.

Indeed those 2 keywords make a JS script become an ESM module file.

I dunno all the rules regarding the requirement or not to place a "/" for a filename path.
But for HTML files, I don’t start the path w/ "/" for local files:

    <link rel="icon" href="img/p5-sq-reverse32.png">
    <link rel="stylesheet" href="styles/styles.css">

    <script async src="src/scriptindex.js"></script>
    <script type="module" src="src/sketch.mjs"></script>

But for remote files, I start w/ a double "//":
<script async src="//cdn.JsDelivr.net/npm/p5"></script>

For the import keyword in a JS file, I generally don’t start a path w/ "/", but either "./" or "../":

import Animal from './classes/Animal.mjs';
import { pointCoord } from './functions/point_coord.mjs';
1 Like

Another thing:

<div id="sketch-holder">
        <script src="/src/sketch.js" type="module"></script>
    </div>

Which is preferred or any good practices…put the inside the div or html tag in which the sketch is gonna be… or as you do at the head of the HTML file ? pros and cons ?

  • Placing a <script> tag inside another tag doesn’t do anything visually!
  • For a p5.js sketch, what we actually want is its <canvas> element.
  • In my ā€œsketch.mjsā€ version, I call method parent() over the p5.Renderer object returned by createCanvas(), passing the <div id="sketch-holder">'s id attribute as its string argument:

This way, the p5.js’s <canvas> becomes a child tag of that <div>.

2 Likes

I knew it…:wink:
I was asking which way is better…as your comment is more smart and ā€œbest practicesā€ put it in the head of the HTML file

1 Like