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