BUG:
An older website that imports jQuery and Bootstrap from locally downloaded files don't have their dependencies properly running; Bootstrap complains that jQuery
and $
are not found. It seems that either the order from the HTML is not respected, or that JS that installs to the root window
are not working correctly.
<script src="LIBS/jquery.min.js"></script>
<script src="LIBS/bootstrap.min.js"></script>
$> parcel index.html
Imported scripts run correctly
Bootstrap complains about not finding jquery. Not sure if import order or window
problem
Can't use Parcel if this doesn't work for older / retrofit websites.
| Software | Version(s)
| ---------------- | ----------
| Parcel | 1.2.0
| Node | v8.9.1
| npm/Yarn | npm v5.5.1
| Operating System | Windows 10
We're seeing a lot of this, too, trying to get some legacy code working with Parcel
This seems like a valid use case for a parcelignore
. They're being included in the correct order, but I'm guessing the closure scope is preventing them from mounting to the window correctly.
some of my problems here seem to go away by using jquery off of CDN instead of bundling in a node package. Probably more performant that way, anyways... Still investigating to see if that fixes everything.
Sometimes corporate policy requires self hosting all dependencies
Hi.
I tried using a CDN, a local link, and node modules, nothing works.
This is a very simple HTML that I used to test.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- JQuery -->
<script src="import/jquery-3.2.1.min.js"></script>
<!-- Bootstrap JS and CSS -->
<link rel="stylesheet" href="import/bootstrap/css/bootstrap.min.css">
<script src="import/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div id="test"></div>
</body>
<script>
$('#test').text('aaa');
</script>
</html>
@DeMoorJasper @brandon93s I'm not sure how .parcelignore
would fix this. I don't want to ignore these files... I want parcel to manage everything and for it to work! If I include jquery separately from CDN, before my parcel bundle, it works. I would rather include it _in_ my parcel bundle.
@benhutton parcelignore could possibly just copy over the files without any processing making this exactly the same as using a cdn for example and hopefully mounting to the window correctly.
Although a better fix would be a more solid way to go, possibly removing the need for parcelignore (which is currently still RFC)
@DeMoorJasper so I would still somehow be able to leverage jquery from npm?
Yes I would be pretty happy if it can just bundle our code without touching the 3rd party libraries.
@benhutton is that not currently possible? If u approach jQuery as a node_module it should work just fine, because it never has the need to mount to the window?
something like
const $ = require('jQuery');
$("#somethin")....
Also another way to fix this would be to detect how many packages are being bundled and just leave sole packages/libraries without imports alone.
All these things i'm proposing sound and kinda are hotfixes/short term solutions.
Like discussed in another issue the proper end-game for bundling would be to remove the need of the prelude entirely, so that code is just bundled in a smaller package and doesn't perform any unexpected behaviour.
unfortunately, const $ = require('jQuery');
doesn't work for me. At least, I can't do that at the top level and have it work everywhere (like I could with webpack, which we're moving from). I think it works if I do that in every single file that uses jquery.
@benhutton Since bootstrap (at least the self downloaded one) seems to require jQuery on the window scope, and fails if not found, I'm not sure how to solve that multi-dependency.
Like @benhutton I have also been stymied by the fact that const $ = require('jquery')
doesn't work, so right now I don't know a way past this.
same problem, how to use jquery with parcel? need help
This is because jQuery disables setting itself on the window global in a CommonJS environment (which Parcel is). See https://github.com/jquery/jquery/blob/master/src/wrapper.js#L29 and https://github.com/jquery/jquery/blob/2d4f53416e5f74fa98e0c1d66b6f3c285a12f0ce/src/exports/global.js#L30-L32.
If you need it to be accessible on window, you could do something like window.$ = require('jquery')
. Does that work?
I'm using TypeScript but this did expose '$' to 'window' for jquery-ui etc to consume it.
import * as $ from 'jquery'
(<any>window).$ = (<any>window).jQuery = $
I have a question, but how can I access any of the classes being declared in the bundled JS without individually exporting them like above?
I found that they're listed in 'window.require.cache[N].exports.default' where N is some number I haven't specified but is there a way to access those by class names?
How am I supposed to access class methods in the bundled JS from within inline HTML such as through 'onclick' properties?
Currently I'm exporting every classes that need exposed the same way as jQuery above which is bit of a work since I can't iterate over a directory in the entry point script but have to manually list them all (which needs updating from time to time).
Hitting this when using EaselJS 1.x versions.
import 'easeljs/lib/easeljs.min.js'
complains createjs
wasn't there.
I'm not sure what we should do about this. The cause of this issue is that jQuery relies on this
being the global object, but in a CommonJS environment (which Parcel emulates) this
refers to the module object.
Perhaps we could make it so that if you imported a script from HTML, it would retain this
in the entry module, but as soon as you require
it would turn into the module object since it is in a common js context. Then you could have <script type="commonjs">
and <script type="module">
for commonjs and ES6 module environments. Obviously this is a breaking change from the current default, but with Parcel 2 on the horizon I'd like to revisit this issue and get some options that make sense. Thoughts?
I solved this by adding this code
```var // Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$;
jQuery.noConflict = function(deep) {
if (window.$ === jQuery) {
window.$ = _$;
}
if (deep && window.jQuery === jQuery) {
window.jQuery = _jQuery;
}
return jQuery;
};
// Expose jQuery and $ identifiers, even in AMD
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if (!noGlobal) {
window.jQuery = window.$ = jQuery;
}```
in the top of the file (linked to above)
2 and a half years and nobody posted at least a workaround?
This worked for me in a project that uses bootstrap and jquery. In my app.js (entry point for parcel):
import jQuery from "jquery";
window.$ = window.jQuery = jQuery; // workaround for https://github.com/parcel-bundler/parcel/issues/333
import 'bootstrap/dist/js/bootstrap.bundle';
Import order matters. Couldn't get it to work with the normal bootstrap js include because it couldn't resolve the dependency for Popper, even though I'm not using tooltips or popper anywhere.
So only workaround? I think gulp doesn't have this issue.
@taducquang gulp isn't a bundler.
The workaround from @sundayz
import jQuery from "jquery";
window.$ = window.jQuery = jQuery;
import "lib-that-depends-on-jQuery";
didn't work for me, since the library that depends on jQuery does so in a sync way, and because parcel ends up generating
"use strict";
var _ = _interopRequireDefault(require("jquery"));
require("lib-that-depends-on-jQuery");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
window.$ = window.jQuery = _.default;
assigning jQuery on window happens too late.
Combining the workaround with the hint from @devongovett does the trick for me:
const jQuery = require("jquery")
window.$ = window.jQuery = jQuery;
require("lib-that-depends-on-jQuery")
since parcel generates in that case
var jQuery = require("jquery");
window.$ = window.jQuery = jQuery;
require("lib-that-depends-on-jQuery");
var jQuery = require("jquery");
window.$ = window.jQuery = jQuery;
require("lib-that-depends-on-jQuery");
This works for me if lib-that-depends-on-jQuery
only uses an instance of jQuery. I tested it with select2 and this condition to test for jQuery absence does not trigger.
However ..
select2 extends jQuery functionality, but the "upgraded" jQuery instance is not available.
That is: the jQuery instance is not mutated (to be upgraded)
And also: the return value from const foo = require('select2/dist/js/select2.js');
is not a jQuery instance but instead something with signature of function exports(root, jQuery)
.
Does someone have this working with a library that extends jQuery ??
My suspicion is that another library can make use of jQuery through 3 methods:
window
(i guess this would be useful when jQuery was loaded in CommonJS but dependent libraries are outside of CommonJS)require('jquery')
, however this can sometimes fail depending on how your paths are loaded (you can try require('jquery')
in your own code to see if it works.As example of 3
const jQuery_tmp = require('cash-dom/dist/cash.min.js'); // using jQuery compatible library
const $ = require('select2/dist/js/select2.js')(jQuery_tmp); // Let the plugin do it's thing
@flip111 That's all fine and good if you are the library owner. If you are just importing something like Bootstrap, however, you as a dev don't really have control over how a dependency like jQuery is looked for.
My suspicion is that another library can make use of jQuery
@mix3d you shouldn't take this too literally. Replace "another library" by "your app".
You see here that if you include bootstrap, including jQuery is a separate step that is not within the code of bootstrap itself. This is the same if you are using import statements.
If you have code that is going "to look for jQuery", you should select the method of making jQuery available in such a way that it corresponds to the ways the code is looking for jQuery.
This worked for me:
import $ from 'jquery'
Most helpful comment
2 and a half years and nobody posted at least a workaround?
This worked for me in a project that uses bootstrap and jquery. In my app.js (entry point for parcel):
Import order matters. Couldn't get it to work with the normal bootstrap js include because it couldn't resolve the dependency for Popper, even though I'm not using tooltips or popper anywhere.