twbs / bootstrap

The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.
https://getbootstrap.com
MIT License
169.86k stars 78.72k forks source link

Bootstrap 5 not working with Vite and jQuery #38914

Open liamkeily opened 1 year ago

liamkeily commented 1 year ago

Prerequisites

Describe the issue

Bootstrap 5 provides instructions for getting started with Vite, and separate instructions for optionally using jQuery.

The documentation states

If Bootstrap detects jQuery in the window object it’ll add all of our components in jQuery’s plugin system;

Based on that I am setting window.jQuery in my main.js file, before including a bootstrap plugin.

// Import jQuery
import jQuery from 'jquery';

// Add jQuery to the Window (see https://getbootstrap.com/docs/5.2/getting-started/javascript/#optionally-using-jquery)
window.jQuery = jQuery;

// Import only the Bootstrap components we need
import { Popover } from 'bootstrap';

// Initialise the popover onload
jQuery(function() {
    jQuery('[data-bs-toggle="popover"]').popover();
});

However it does not appear to be correctly registering the plugin.

image

Reduced test cases

This is a fork of the bootstrap example repo, a copy has been made of the vite example and the following commit attempts to make it work with jQuery instead of the Vanilla JS.

https://github.com/liamkeily/bootstrap-examples/pull/1/commits/09fe7f2bbb9d11e68d43ab3c273b7fbc039e3043

What operating system(s) are you seeing the problem on?

macOS

What browser(s) are you seeing the problem on?

Chrome

What version of Bootstrap are you using?

5.3.0

liamkeily commented 1 year ago

I have dug further into this and it looks like bootstraps defineJQueryPlugin(Popover) and its containing onDOMContentLoaded is getting called before the window.jQuery = jQuery line in main.js. So window.jQuery is not defined at the time it is trying to register the plugin.

I guess this is something to do with the way Vite loads dependencies

liamkeily commented 1 year ago

This also worked fine for Bootstrap 4, which we are upgrading from.

Created a separate branch on that repo to prove that Bootstrap 4 works https://github.com/liamkeily/bootstrap-examples/compare/vite-and-jquery...liamkeily:bootstrap-examples:vite-and-jquery-bootstrap4

XhmikosR commented 1 year ago

Any PRs that fix the issue are welcome. But please try to add a test case.

jamesRUS52 commented 11 months ago

Any news?

AllanJard commented 7 months ago

I encountered this as well while listening for a Bootstrap modal event - jQuery event wasn't triggered but listening with addEventListener was.

Could Bootstrap expose a function (use() for example, or setJquery()) which would let us set the jQuery library for Bootstrap to use, falling back to the window.jQuery if not present?

Then the usage would be:

import $ from 'jquery';
import bootstrap from 'bootstrap';

bootstrap.use($);

instead of doing window.jQuery = $;?

I can create a PR if this might be of interest?

skeets23 commented 3 months ago

This is actually really easy to fix, it's just not documented anywhere.

Create a "wrapper" for jquery like this:

jquery_import.js

import $ from 'jquery';
window.$ = window.jQuery = $;

In your main js file, import this wrapper before importing the JS for bootstrap 5.

If you don't use a wrapper file, Vite moves the global declaration to the very end of the built JS file, and it won't work.

liamkeily commented 2 months ago

Thanks @skeets23 that did actually work

XhmikosR commented 2 months ago

Let's reopen the issue and wait for someone to submit a PR. I'm pretty sure it's a common issue worth documenting.