Hi,
I want to import the library erobertson42/bootstrap-modbox in my app, which in turn depends on package bootstrap. My package.json:
"bootstrap": "^5.1.3",
"bootstrap-modbox": "^1.4.0"
Imports on client:
import bootstrap from "bootstrap";
import modbox from 'bootstrap-modbox';
And when the page loads on the client I get the exception on the second import line:
Uncaught ReferenceError: bootstrap is not defined
at Function.<static_initializer> (modules.js?hash=:16696:92)
at module (modules.js?hash=:16677:52)
at fileEvaluate (modules-runtime-hot.js?hash=:388:7)
at Module.require (modules-runtime-hot.js?hash=:270:27)
at Module.moduleLink [as link] (modules.js?hash=:331:22)
at hello.js:28:1
Which points to the line with the spread operator (…bootstrap.Modal.Default,) in static private property of the default export class:
export default class modbox {
static version = '1.4.0';
/* private members */
#options;
static #defaultOptions = {
// bootstrap modal default options
...bootstrap.Modal.Default, //THIS IS THROWING THE EXCEPTION
// modbox default options
icon: null,
style: 'white',
All this on the latest Meteor version 2.6.1. Latest Edge Chromium. Bootstrap package alone works fine and bootstrap object is accessible from within the code, i.e. I can do console.log(bootstrap.Modal);
works as expected.
So I’m just wondering how is this possible, that bootstrap is Undefined, when it is imported just before this class? Or anything wrong with the imports? I run out of ideas and stacktrace doesn’t seem to help.
Thanks for your help! Milos
Hmm, no difference with import 'bootstrap'
Looking at the code for bootstrap-modbox
, it doesn’t import
or require
bootstrap in any way and just expects it to be globally defined (source, and built version)
To be clear, this is bad module design by bootstrap-modbox
But that does give us the information required to get it working! We just need to set bootstrap
as a global before loading modbox
Make a new file globalize-bootstrap.js
import bootstrap from "bootstrap";
globalThis.bootstrap = bootstrap;
export bootstrap;
then import globalize-bootstrap.js
before importing bootstrap-modbox
import bootstrap from "/utils/globalize-bootstrap";
import modbox from 'bootstrap-modbox';
Note: the reason we put setting a global var in another file instead of between the two import lines is because import
statements are hoisted to the top of the file, so the global var will be set after modbox is imported. By putting it in the other file, that import runs to completion before the modbox import starts
5 Likes
Thanks to @coagmano it is now working. The solution is as follows.
- The
globalize-bootstrap.js
:
import * as bootstrap from "bootstrap";
globalThis.bootstrap = bootstrap;
export default bootstrap;
- and my .js imports it:
import bootstrap from "../lib/globalize_bootstrap";
import modbox from 'bootstrap-modbox/dist/bootstrap-modbox.esm';
Tricky indeed, but learned a lot about hoisting.
1 Like
Amazing that the hoisting docs you linked don’t even mention ESModule imports!!!
That’s the part that was relevant here
Not even the docs on the import
statement mention that they get hoisted to the top import - JavaScript | MDN
And I’m still wondering what shall the ideal solution be? Can we hint the author of the package?
Regarding the MDN doc: hoisting is only in Glossary, whereas import
is in the Reference part. I’m going to update the part via pull-request. At least my days&nights spent on the issue are of some use for others.