Closed mdede closed 2 years ago
(Please ignore the original message before this edit, I wrote it when quite tired. After re-reading now, it makes better sense.)
@mdede Unfortunately, I am not familiar with Meteor. However, I believe the issue may be with your import statement, import 'bootstrap-modbox'
. It is valid JavaScript, but I think that will immediately execute the code in the module (and won't be reachable externally).
Your import statement should define a variable for the class exported from the module:
import modbox from 'bootstrap-modbox';
No problem Eric, Meteor forum helped me. It is resolved now. Hoisting seems to be the culprit. For information: see this post.
Thanks @mdede, after seeing the suggested solution, that makes sense. It looks like I didn't do enough testing - I tested loading modbox as a module, but not with bootstrap also loaded as a module. Apologies for the oversight.
I can do a bit to alleviate this by appending bootstrap.Modal.Default
to the modbox default options inside the constructor instead of when the static #defaultOptions
object is initialized. This will fix the hoisting issue by making sure bootstrap
isn't called until a modbox is actually created as opposed to immediately when loading the library. That said, the globalThis.bootstrap = bootstrap
definition will still be necessary, but you will no longer need the intermediary globalize-bootstrap.js
file. You will be able to simply:
import * as bootstrap from 'bootstrap';
globalThis.bootstrap = bootstrap;
import modbox from 'bootstrap-modbox/dist/bootstrap-modbox.esm';
I'll also make a note of this in the docs.
Unfortunately on my end, as suggested by a user in that thread, it's not as simple as importing bootstrap into the ES module version of modbox. As you can see, while it can work with a bundler, it was not written specifically with that in mind, but rather was written for use as pure vanilla JavaScript.
The ES standard module system requires a relative path to the file to be imported. Meaning if I were to include it, I would have to hardcode the path, and anyone using modbox would either have to use that same path to bootstrap, or modify the code with their own path - which is obviously not desirable. Alternatively, if I imported bootstrap using the specifier syntax as you are, then a bundler would be required and no one could use the ES module version in a vanilla JavaScript environment (it would throw an error).
A JavaScript import map is a potential solution, however, it is currently still an experimental feature and not supported by all browsers. For now, perhaps I could also add a more descriptive error to be thrown if the bootstrap
object is not found.
I'm hardly an expert on this topic, but using globalThis (in general) doesn't seem right. What about (naively):
import * as bootstrapXY from 'bootstrap'; //get bootstrap from whatever module/package
import modbox from 'bootstrap-modbox/dist/bootstrap-modbox.esm'; //no static class initialization here
modbox.init(bootstrapXY.Modal); //I presume this is the only object you need from the whole Bootstrap
modbox.alert("hello");
This would decouple both modules completely. Perhaps modbox.init
could be class method?
Passing a reference to bootstrap into the class might not a bad alternative. I'll have to think about it a bit. Thank you.
Unfortunately on my end, as suggested by a user in that thread, it's not as simple as importing bootstrap into the ES module version of modbox. As you can see, while it can work with a bundler, it was not written specifically with that in mind, but rather was written for use as pure vanilla JavaScript.
Hi, user from that thread here :D
The usual way to deal with this is by preparing it as a UMD bundle with the dependencies specified ther. This bundling method tests for the presence of AMD or CommonJS import styles and falls back to window
globals for direct use in script tags. That means you can still stick bootstrap in a script tag and it will set the global, and where require
is availiable it will use that to fetch bootstrap.
Not sure how that goes with native ESModules, but since most bundlers (eg Meteor, Webpack, etc) end up packaging everything with commonjs/require
it's still a big help
Sorry I don't have time to find an example to show you but hopefully this gives you some search terms to start.
Also, I think passing in bootstrap is a perfectly good solution. I suggest making it look for a global bootstrap if none is passed in to keep it backwards-compatible
I don't think you need to change how it's published, I know that's a lot of effort. Just giving you a potential solution if you feel so inclined
Nevertheless I'm perfectly fine importing it as-is :-).
New v1.5.0 release addresses this.
Hi Eric, i'm trying to use your npm package in a Meteor application.
But the client does not load at all saying
pointing at
#defaultOptions={...bootstrap.Modal.Default
line of your class.Any idea what might be wrong? Adding
console.log(bootstrap.Modal.Default)
after the first import line shows expected output without errors. Cheers, Milos