Using p5.js via npm

Hey there!
I downloaded p5 via npm locally in one of my projects. Now how do I import it to the index.html file?

Is doing this worth it? Or should I rather abandon this idea and use the CDN instead?

  • Let’s say you have a folder named “MySketch”.
  • And inside that folder a file called “sketch.js”:
'use strict';

function setup() {
  createCanvas(800, 600).mousePressed(redraw);
  noLoop();
}

function draw() {
  background('#' + hex(~~random(0x1000), 3));
}
  • Then you open the command shell while inside that folder and type in: npm i -D p5
  • You’ll get a subfolder “node_modules” and 2 files: “package.json” & “package-lock.json”.
  • In order to load both “sketch.js” and the acquired “p5.js” file inside “node_modules/p5/lib/” you’d create an “index.html” template like this:
<script defer src=node_modules/p5/lib/p5.js></script>
<script defer src=sketch.js></script>
  • However you could simply scrap all that and just get it remotely from a CDN:
<script defer src=https://cdn.JsDelivr.net/npm/p5></script>
<script defer src=sketch.js></script>
1 Like

Thank you @GoToLoop.
I have another question: I have my project inside a long path of sub-folders. So is there a way I can lead the path variable staright to the root repository and then into the node modules?

You can use ../ in order to go up to the parent folder of the current folder.

You can also begin from the base folder by starting the path w/ /:

<script defer src=/node_modules/p5/lib/p5.js></script>
1 Like

@GoToLoop thanks for sharing info how to use p5.js with npm.

i have managed to use it via import p5 from ‘p5’ in main.js
and import main.js in index.html

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

// inside main.js
import p5 from "p5";

/* method 1 */
function sketch1() {
  setup = () => {
    createCanvas(400, 400);
  }

  draw = () => {
    background(220);
    stroke(0);
    fill(255);
    ellipse(200, 200, 100, 100);
  }
}

new p5(sketch1);

/* method 2 */
const sketch2 = (p5) => {
  p5.setup = () => {
    p5.createCanvas(400, 400);

  };

  p5.draw = () => {
    p5.background(220);
    p5.stroke(0);
    p5.fill(255);
    p5.ellipse(200, 200, 100, 100);
  };
}


new p5(sketch2);

in JSDoc for p5 I read:

This is the p5 instance constructor. A p5 instance holds all the properties and methods related to a p5 sketch. It expects an incoming sketch closure and it can also take an optional node parameter for attaching the generated p5 canvas to a node. The sketch closure takes the newly created p5 instance as its sole argument and may optionally set preload(), setup(), and/or draw() properties on it for running a sketch.
A p5 sketch can run in “global” or “instance” mode: “global” - all properties and methods are attached to the window “instance” - all properties and methods are bound to this p5 object

My question: how do i change modes ?

ideally it would be great to use sketch only declaring setup and draw functions and calling them with p5, instead inside of a sketch function. Is it possible? It seems minor thing but I find it much cleaner than method 1, and since global context is already used perhaps this could work too somehow?

function setup() {
    createCanvas(400, 400);
 }

 function draw () {
    background(220);
    stroke(0);
    fill(255);
    ellipse(200, 200, 100, 100);
 }

new p5({ setup, draw });

AFAIK, library p5.js isn’t available as an ES6 module:

So we can’t use keyword import for it; it needs to be downloaded as a regular JS file from within an HTML file.

Constructor p5’s 1st parameter is a callback function, not a regular object.

When constructor p5 calls back our function, it passes the newly created instance.

If you wanna use instance mode, but prefer to have callbacks such as setup() & draw() as top-functions rather than inside a single callback, you can follow this model:

ES6 imports work with no problem once you import your script in index.html with type="module" attribute.

The only thing weird is that P5 methods are available only via global scoped variables (you define own setup and draw as variables inside the sketch function that is passed to P5 constructor.

Thanks to this trick you don’t need to call p5.createCanvas etc but simply createCanvas.

This way though is exploiting what would normally be a javascript anti-pattern (setup and draw are being hoisted implicitly and ‘caught’ by p5 context, making p5 methods available). I think it would be good to mention this in the docs as it is not standard use of JS and modules.

Library p5.js isn’t officially available as a ES6 module, so we can’t use keyword import to acquire it.

We can only use import for actual ES6 module files, like “vehicle.mjs” in the example below:

Any plans to make it available officially for ES6 modules? it is pretty standard these days.

Library p5.js got modularized using CommonJS syntax, even though ES6 module syntax was already available back then:

1 Like