Parcel: jQuery plugins (i.e., venobox) complain that jQuery is not defined

Created on 15 Oct 2019  Β·  4Comments  Β·  Source: parcel-bundler/parcel

πŸ› bug report

I'm just using the Bootstrap + FontAwesome recipe and trying to get jQuery plugins like venobox and easing to work (this is from a legacy project).

I followed the steps, and afterwards I ran npm i venobox and edited main.js to this:

import "bootstrap";
import "bootstrap/dist/css/bootstrap.css"; // Import precompiled Bootstrap css
import "@fortawesome/fontawesome-free/css/all.css";
import $ from "jquery";
import "venobox/venobox/venobox.min";
import "venobox/venobox/venobox.css";

$(document).ready(function() {
  $("#msgid").text("This is Hello World by JQuery");
  $(".venobox").venobox(); // <-- error over here
});

πŸŽ› Configuration (.babelrc, package.json, cli command)

I'm not using a .babelrc.

package.json:

{
  "name": "testing-bootstrap-parcel",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "parcel index.html"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "bootstrap": "^4.3.1",
    "jquery": "^3.4.1",
    "popper.js": "^1.15.0",
    "venobox": "^1.8.6"
  },
  "devDependencies": {
    "@fortawesome/fontawesome-free": "^5.11.2",
    "parcel-bundler": "^1.12.4"
  }
}

CLI command:
npm run start

πŸ€” Expected Behavior

For there not to be an error.

😯 Current Behavior

The console printed an error:

Uncaught ReferenceError: jQuery is not defined
    at Object.parcelRequire.node_modules/venobox/venobox/venobox.min.js (venobox.min.js:12)
    at newRequire (main.1f19ae8e.js:47)
    at localRequire (main.1f19ae8e.js:53)
    at Object.parcelRequire.main.js.bootstrap (main.js:5)
    at newRequire (main.1f19ae8e.js:47)
    at main.1f19ae8e.js:81
    at main.1f19ae8e.js:120

πŸ’ Possible Solution

I'm not sure. I'm really a beginner trying to try to move one of my projects to a bundler, so I can minify the code, reduce the number of HTTP requests, hot reload, etc.

πŸ”¦ Context

I'm trying to move a hackathon landing page I'm making (here is the GitHub repo) onto Parcel. We used a bootstrap template called TheEvent from here, so it had a bunch of legacy libraries that were unwieldy when trying to move to Parcel.

I know using a template might be frowned upon, but we are all beginners and just want to learn more software development (i.e., stuff like Parcel).

πŸ’» Code Sample

All the code in the minimal example is in this GitHub repo.

Nevertheless, here are the main components:

main.js:

import "bootstrap";
import "bootstrap/dist/css/bootstrap.css"; // Import precompiled Bootstrap css
import "@fortawesome/fontawesome-free/css/all.css";
import $ from "jquery";
import "venobox/venobox/venobox.min";
import "venobox/venobox/venobox.css";

$(document).ready(function() {
  $("#msgid").text("This is Hello World by JQuery");
  $(".venobox").venobox();
});

index.html:

<!DOCTYPE html>
<html lang="en">
  <head> </head>
  <body>
    <div>testing</div>
    <i class="fas fa-address-book"></i>
    <div id="msgid">lol</div>
    <script src="./main.js"></script>
  </body>
</html>

🌍 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.12.4
| Node | 10.16.3
| npm/Yarn | 6.12.0
| Operating System | macOS Mojave 10.14.6 (18G103)

Thanks for your help! πŸ˜„

Bug

Most helpful comment

I don't really know why it gave you that error but there's a problem here, it's that ESM modules doesn't allow you to put code in between the imports, so you'd have to put

import $ from "jquery";
globalThis.jQuery = $;

in a separate file before importing venobox,
so e.g
jquery-global.js

import $ from "jquery";
globalThis.jQuery = $;
import "./jquery-global.js";

import $ from "jquery";
import "bootstrap";
import "bootstrap/dist/css/bootstrap.css"; // Import precompiled Bootstrap css
import "@fortawesome/fontawesome-free/css/all.css";
import "venobox/venobox/venobox.min";
import "venobox/venobox/venobox.css";

$(document).ready(function() {
  $("#msgid").text("This is Hello World by JQuery");
  $(".venobox").venobox();
});

All 4 comments

I doubt this is a Parcel bug as venobox use the jQuery global(https://github.com/nicolafranchini/VenoBox/blob/master/venobox/venobox.js#L763)
which makes it uncompatible with the module version of Jquery which exports itself

import $ from 'jquery'
console.log($)
/*
Ζ’ ( selector, context ) {

        // The jQuery object is actually just the init constructor 'enhanced'
        // Need init if jQuery is called (just allow error to be thrown if not included)
        return new jQuery…
*/
console.log(window.jQuery) // undefined

To fix that, you'd simply have to define the jQuery export to the global context.
To do that you can simply do

import $ from 'jquery'
globalThis.jQuery = $

Thank you so much for your help!

To do that you can simply do

import $ from 'jquery'
globalThis.jQuery = $

Hmm... I tried modifying main.js to:

import $ from "jquery";
globalThis.jQuery = $;
import "bootstrap";
import "bootstrap/dist/css/bootstrap.css"; // Import precompiled Bootstrap css
import "@fortawesome/fontawesome-free/css/all.css";
import "venobox/venobox/venobox.min";
import "venobox/venobox/venobox.css";

$(document).ready(function() {
  $("#msgid").text("This is Hello World by JQuery");
  $(".venobox").venobox();
});

but I still get:

Uncaught ReferenceError: jQuery is not defined
    at Object.parcelRequire.node_modules/venobox/venobox/venobox.min.js (venobox.min.js:12)
    at newRequire (main.1f19ae8e.js:47)
    at localRequire (main.1f19ae8e.js:53)
    at Object.parcelRequire.main.js.jquery (main.js:6)
    at newRequire (main.1f19ae8e.js:47)
    at main.1f19ae8e.js:81
    at main.1f19ae8e.js:120

(To view all the code, I put it on the banou26-fix branch of the repo here)

you'd simply have to define the jQuery export to the global context.

I'm not exactly sure what "defining an export to the global context" means. Could you please elaborate?

I don't really know why it gave you that error but there's a problem here, it's that ESM modules doesn't allow you to put code in between the imports, so you'd have to put

import $ from "jquery";
globalThis.jQuery = $;

in a separate file before importing venobox,
so e.g
jquery-global.js

import $ from "jquery";
globalThis.jQuery = $;
import "./jquery-global.js";

import $ from "jquery";
import "bootstrap";
import "bootstrap/dist/css/bootstrap.css"; // Import precompiled Bootstrap css
import "@fortawesome/fontawesome-free/css/all.css";
import "venobox/venobox/venobox.min";
import "venobox/venobox/venobox.css";

$(document).ready(function() {
  $("#msgid").text("This is Hello World by JQuery");
  $(".venobox").venobox();
});

Excellent. It works perfectly! I cannot thank you enough πŸ™‡β€β™‚οΈ

Was this page helpful?
0 / 5 - 0 ratings

Related issues

philipodev picture philipodev  Β·  3Comments

jsftw86 picture jsftw86  Β·  3Comments

donaldallen picture donaldallen  Β·  3Comments

oliger picture oliger  Β·  3Comments

dsky1990 picture dsky1990  Β·  3Comments