p5.js-sound icon indicating copy to clipboard operation
p5.js-sound copied to clipboard

p5 is not defined in /node_modules/p5/lib/addons/p5.sound.js:4323

Open suprim12 opened this issue 5 years ago • 29 comments

Error Remake on Using npm in React App

import * as p5 from "p5"; import "p5/lib/addons/p5.sound";

suprim12 avatar Aug 10 '20 17:08 suprim12

Welcome! 👋 Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, be sure to follow the issue template if you haven't already.

welcome[bot] avatar Aug 10 '20 17:08 welcome[bot]

@suprim12 please mention the versions and some more detail.. It would be more helpful! Thanks

endurance21 avatar Aug 17 '20 21:08 endurance21

Same problem here, i use p5 in react (typescript). In my case, when i import p5/lib/addons/p5.sound the error show up

import p5 from 'p5';
import 'p5/lib/addons/p5.sound';

let bloopOne: p5.SoundFile;

export function preBloop(p: p5): void {
    const loadSound = (path: string) => ((p as any) as p5.SoundFile).loadSound(path);
    bloopOne = loadSound('../audio/bloop1.mp3');
}

export function playBloop(): void {
    bloopOne.play();
}

i use the latest version of p5 "p5": "^1.1.9", "react": "^16.13.1"

ylahssini avatar Aug 23 '20 23:08 ylahssini

@ylahssini it would be great to see actuall error output ! thanks !

endurance21 avatar Aug 24 '20 00:08 endurance21

@endurance21 This is error output, i think it's related to webpack, and i use CRA:

Uncaught ReferenceError: p5 is not defined
    at Object.<anonymous> (p5.sound.js:3112)
    at Object.push../node_modules/p5/lib/addons/p5.sound.js (p5.sound.js:3160)
    at __webpack_require__ (p5.sound.js:84)
    at Object.<anonymous> (p5.sound.js:2885)
    at Object.push../node_modules/p5/lib/addons/p5.sound.js (p5.sound.js:2956)
    at __webpack_require__ (p5.sound.js:84)
    at p5.sound.js:120
    at Object../node_modules/p5/lib/addons/p5.sound.js (p5.sound.js:121)
    at __webpack_require__ (bootstrap:784)
    at fn (bootstrap:150)
    at Module../src/Rain/Bloops.ts (Bloops.ts:2)
    at __webpack_require__ (bootstrap:784)
    at fn (bootstrap:150)
    at Module../src/Rain/index.tsx (index.tsx:1)
    at __webpack_require__ (bootstrap:784)
    at fn (bootstrap:150)
    at Module../src/App.tsx (index.css:7)
    at __webpack_require__ (bootstrap:784)
    at fn (bootstrap:150)
    at Module../src/index.tsx (index.css?f3f6:45)
    at __webpack_require__ (bootstrap:784)
    at fn (bootstrap:150)
    at Object.1 (serviceWorker.ts:149)
    at __webpack_require__ (bootstrap:784)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1

ylahssini avatar Aug 24 '20 21:08 ylahssini

Has anyone been able to solve this? Have tried all discussed solutions in other threads with no luck.

matt-scientist avatar Oct 23 '20 22:10 matt-scientist

@angerboy I solved like this:

import React, { useEffect } from "react"; import './globals'; import "p5/lib/addons/p5.sound"; import p5 from "p5";

and then in globals.js:

import p5 from "p5"; window.p5 = p5;

The problem is that p5 is available as global dependency when using webpack/create-react-app. I'm not sure if this is the best way to approach but it works, I got the idea from here: https://github.com/facebook/create-react-app/issues/4281

LABCAT avatar Nov 08 '20 05:11 LABCAT

@LABCAT Thanks, I wonder if you could share your code? Having the same issue as well ): and can't figure this out.

vennsoh avatar Nov 18 '20 04:11 vennsoh

@vennsoh I'm doing it in this repo: https://github.com/LABCAT/donuts-no-1/

see this file: https://github.com/LABCAT/donuts-no-1/blob/master/src/js/globals.js

and this file: https://github.com/LABCAT/donuts-no-1/blob/master/src/js/P5Sketch.js

LABCAT avatar Nov 18 '20 05:11 LABCAT

@LABCAT

Your workaround seems to be working for only function calls? I added window.p5 = p5 after calling import * as p5 from "p5"

import * as ml5 from "ml5"
window.p5 = p5
import "p5/lib/addons/p5.sound"

Then I'll be able to use the p5.loadSound() function. However if I try to use new p5.Envelope() constructor it'll still throw me an error.

export default function sketch(p5) {
    p5.setup = () => {
        p5.createCanvas(400, 400)
        song = p5.loadSound(url("./assets/hurry.mp3")) // Will work
        env = new p5.Envelope() // Will error
...

It'll say "ndex.js:296 Uncaught (in promise) TypeError: p5.Envelope is not a constructor" Do you know why?

According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_a_constructor It says p5.Envelope() is not a constructor...

vennsoh avatar Nov 18 '20 06:11 vennsoh

@vennsoh @LABCAT
I have been working on this repo in this summer of code , I would like to help it out , but I am busy with my college schedule right now . I would ask to use this current repo code of p5.sound instead what is present in "p5/lib/addons/p5.sound" ,

So how would you use current p5.sound file , it's simple just go to current repo , go to lib folder , and copy p5.sound.js from there and place it somewhere in your repo you might find appropriate to work with , and then import it using like you do and then TELL US THE RESULT .

It will help us figuring out if the same problem is with aall versions or what !!

endurance21 avatar Nov 18 '20 07:11 endurance21

@endurance21 Thanks. I've copied and replaced p5.sound files from https://github.com/processing/p5.js-sound/tree/master/lib

It's still the same problem so I doubt it's the version. The version that I'm using: /** [p5.sound] Version: 0.3.12 - 2020-01-06 */

vennsoh avatar Nov 18 '20 13:11 vennsoh

Thanks a ton for this experiment @vennsoh . Let me tell you one more thing , we have some APIs that's uses audioworklet processors . I am.having doubt that if this is the problem with those audioworklet processors or what !

For this I would ask you to initiatize P5.oscillator() Instead of p5.Envelope()

And see if same happens or what ! Also forgive me if I am counting too much on you for carrying out experiments and all. Hope you understand that..

endurance21 avatar Nov 18 '20 15:11 endurance21

All good. It's still the same problem @endurance21 image

vennsoh avatar Nov 19 '20 01:11 vennsoh

Ah just changing p5.Envelope() --> p5.constructor.Envelope() fixes the problem!

vennsoh avatar Nov 19 '20 22:11 vennsoh

@vennsoh good to hear that . But is the reason it's working .I am clueless right now .

endurance21 avatar Nov 20 '20 04:11 endurance21

Sorry I think I should be a little bit more specified. I used react-p5-js library to fix this problem. The comment thread is here.

https://github.com/and-who/react-p5-wrapper/issues/61

vennsoh avatar Nov 20 '20 07:11 vennsoh

I was able to get everything working using the CDN script links in my index.html:

    <script defer src=https://cdn.JsDelivr.net/npm/p5></script>
    <script defer src=https://cdn.JsDelivr.net/npm/p5/lib/addons/p5.dom.min.js></script>
    <script defer src=https://cdn.JsDelivr.net/npm/p5/lib/addons/p5.sound.min.js></script>

I then waited for window.p5 to be defined:

  useEffect(() => {
    // Wait until p5 is loaded
    p5Interval = window.setInterval(() => {
      if(window.p5) {
        p5 = window.p5;
        myp5 = new p5(Sketch, myRef.current);
        window.clearInterval(p5Interval);
      }
    }, 100);
  }, []);

matt-scientist avatar Dec 08 '20 21:12 matt-scientist

No idea how we could propose this change, but, it seems like p5.sound.js is missing the p5 dependency, so, my fix was to do the following,

In node_modules/p5/lib/addons/p5.sound.js

FIND

/** [p5.sound]  Version: 0.3.12 - 2020-01-06 */

REPLACE WITH

import p5 from "p5"  // import the missing dependency, obviously not a permanent fix, but, simple

/** [p5.sound]  Version: 0.3.12 - 2020-01-06 */

I'm sure there's a solid motivation for structuring the code this way, but, it's doesn't seem very npm friendly. Does @anyone know why it is assumed that p5 is global and/or why node_modules/p5/lib/addons/p5.sound.js is already packed with webpack?

multimonos avatar Jan 11 '21 23:01 multimonos

@vennsoh I'm doing it in this repo: https://github.com/LABCAT/donuts-no-1/

see this file: https://github.com/LABCAT/donuts-no-1/blob/master/src/js/globals.js

and this file: https://github.com/LABCAT/donuts-no-1/blob/master/src/js/P5Sketch.js

Oh my god, this ^ - absolute life saver, I've been trawling every thread over this issue and this fixed it perfectly. The primary difference for me was including import * as p5 from "p5"; and window.p5 = p5; in a seperate file before importing into the sketch.

Thank you! 🤘

dnirns avatar Mar 04 '21 11:03 dnirns

This looks like a duplicate of https://github.com/processing/p5.js-sound/issues/453 and https://github.com/processing/p5.js/issues/4479

I can confirm it is not a problem with Webpack alone - the problem exists in all modern module loaders/compilers including RollUp, TypeScript and Parcel.

Having tested more thoroughly, I can confirm P5 add-ons won't load in the following configurations:

  • CommonJS
  • ES6 > ES5 using Babel or esm
  • ES Modules

Given the enournous populariity of npm and yarn, this issue means that anyone using those package managers will not be able to use p5 with add-ons.

What was it that changed between v0.9 and v1 that broke it?

rjbultitude avatar Mar 04 '21 12:03 rjbultitude

@rjbultitude The basic thing this library is assuming that , p5 is a global variable. so users first need to make available p5 as global or in the scope of p5.sound apis .

does it sounds good ?

endurance21 avatar Mar 04 '21 14:03 endurance21

Thanks for the quick reply @endurance21 I think there are a few fundamental problems:

  1. There are no instructions in the Get Started page that explain how to install and configure p5 and add-ons via NPM or Yarn
  2. Most developers expect frameworks and libraries to manage their own namespacing
  3. This wasn't a problem in earlier versions, so it seems a breaking change was introduced at v1.0 that needs to be clearly communicated.

Are you saying the current solution is to import p5 then assign it to the window object? e.g. window.p5 = p5;

rjbultitude avatar Mar 04 '21 15:03 rjbultitude

@rjbultitude i havenot tried btw , but my intuitions says it well !

endurance21 avatar Mar 04 '21 15:03 endurance21

How shall we proceed then? As per point 2 above, p5 should handle its own namespacing, which would fix this issue and 4479.

Also, do you know the answer to point 3? Why were p5 add-ons able to access the p5 object in v9.0?

I'll make a new issue for the missing instructions, if there's not one already.

rjbultitude avatar Mar 04 '21 17:03 rjbultitude

I've tested the assignment of p5 to the global namespace and can confirm it does not work using ES2015 syntax e.g. import p5 from 'p5'; window.p5 = p5; import 'p5/lib/addons/p5.sound';

As far as I can tell, any compiler will fail to load the add-ons hence the other issues about TypeScript, p5-dom and so on

it only works if you use CommonJS (Node) syntax: const p5 = require('p5'); window.p5 = p5; require('p5/lib/addons/p5.sound');

Does anyone know what changed between v0.9 and v1.0? @therewasaguy @lmccart

Is there a discussion or plan to modernise p5 so that it works with the primary three module patterns and all common loaders/compilers?

Happy to help but am missing context.

rjbultitude avatar Mar 05 '21 11:03 rjbultitude

Another relatively clean workaround until this gets properly fixed (so that others don't waste hours):

  1. Include the libraries directly in your index.html as script tags:
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/addons/p5.sound.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ml5.min.js"></script>
  1. Declare the globals and use p5 in instance mode:
declare const p5: any;
declare const ml5: any;
...

  new p5((sketch: any) => {
    let mic: any;
  
    sketch.setup = () => {
      mic = new p5.AudioIn();
      mic.start(() => {
        const audioContext = new AudioContext();
        pitch = ml5.pitchDetection(MODEL, audioContext, mic.stream, ...);
      });
    };
    ...
  }

terek avatar Apr 03 '21 05:04 terek

If you run into this problem and so happen to be using webpack - there is the imports-loader that can be used https://webpack.js.org/loaders/imports-loader/

I have a config like this:

module: {
        rules: [
            {
              test: path.resolve(__dirname, 'js/libs/easycam/p5.easycam.js'),
              use: "imports-loader?p5=>require('p5')"
            },
            {
              test: path.resolve(__dirname, 'node_modules/p5/lib/addons/p5.sound.js'),
              use: "imports-loader?p5=>require('p5')"
            },
            {
              test: path.resolve(__dirname, 'node_modules/p5/lib/addons/p5.sound.min.js'),
              use: "imports-loader?p5=>require('p5')"
            },

It'd be nice to have p5 sound work without relying on p5 as a global :-|

unjust avatar Apr 08 '22 02:04 unjust

For anyone looking at this solution, the docs for imports-loader have been updated:

module: {
    rules: [
        {
            test: path.resolve(
                __dirname,
                "node_modules/p5/lib/addons/p5.sound.js"
            ),
            loader: "imports-loader",
            options: {
                type: "module",
                imports: "p5",
            },
        },
        {
            test: path.resolve(
                __dirname,
                "node_modules/p5/lib/addons/p5.sound.min.js"
            ),
            loader: "imports-loader",
            options: {
                type: "module",
                imports: "p5",
            },
        },
    ]
}

anuzk13 avatar Sep 08 '22 21:09 anuzk13

Using require fix the compatibility

import p5 from "p5"
window.p5 = p5
require('p5/lib/addons/p5.sound')

Vamoss avatar Nov 21 '22 21:11 Vamoss