edtrade's avatar
Level 13

Laravel Vite & JQuery

I am having a hard time including jQuery to new Laravel 9 and Vite project i tried "npm install jquery" and adding to bootstrap.js import jQuery from 'jquery'; window.$ = window.jQuery = jQuery; Can someone please help

0 likes
35 replies
drehimself's avatar

You almost got it, I tried:

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

and it worked.

Don't forget to use the vite directive in your blade layout and then run npm run dev

@vite(['resources/css/app.css', 'resources/js/app.js'])
4 likes
warmwhisky's avatar

@drehimself Doesn't work for me either. I've also tried the old way I was using last week with Mix

global.$ = global.jQuery = require('jquery');

This used to work

edtrade's avatar
Level 13

i can't make it work, i keep getting "Uncaught ReferenceError: $ is not defined"

Steps to reproduce

  1. in terminal "npm install jquery"

  2. In "bootstrap.js" i added "import jQuery from 'jquery';" "window.$ = jQuery;"

  3. Added to my "layout.blade.php" @vite(['resources/css/app.css', 'resources/js/app.js'])

  4. Add some jquery code to blade file which extends my layout.blade.php

  5. In terminal "npm run dev"

Looks like my javascript/jquery code wihtin my blade file is running before vite files are even loaded. Within my browser console i have access to window.$

I get "Uncaught ReferenceError: $ is not defined" before [vite] connecting, [vite] connected

Only works if i wrap my jquery code within a setTimeout

2 likes
warmwhisky's avatar

@edtrade Same here. I've tried many ways to import $ so far and it always says $ is not defined

drehimself's avatar

@edtrade If I'm understanding correctly, you are correctly importing jQuery within Vite but you are trying to use it in a script tag within your blade files. I don't think that is going to work.

If you try writing your jQuery code directly within the bootstrap.js file after importing jQuery, that should work.

Is there any reason you need to use a build tool for jQuery? I personally only use build tools when the JavaScript/CSS I write needs to be compiled into something the browser can understand (i.e. Vue, React, SCSS, Tailwind, etc). For things like jQuery or vanilla JS libraries, I would much rather use a simple CDN link (or download locally and put in the public folder). It's much simpler in my opinion and avoids problems like this.

1 like
warmwhisky's avatar

@drehimself

If I'm understanding correctly, you are correctly importing jQuery within Vite but you are trying to use it in a script tag within your blade files. I don't think that is going to work.

Yes that's what I was doing

I was importing jQuery in resources/js/app.js file before Laravel upgraded to Vite in 9.19? But since trying Vite on a new project is no longer works or I am missing something?

If you try writing your jQuery code directly within the bootstrap.js file after importing jQuery, that should work.

Some of my pages require jQuery and a fair amount of it too, but other don't need it. I cannot have that amount of page specific redundant jQuery on every page.

Is there any reason you need to use a build tool for jQuery?

I use jQuery with a build tools as I want as much as I can in one app.js.

MamoonaShuja's avatar

@edtrade i have found a solution create your new file named it custom.js and import it in app.js or bootstrap.js make sure to import jquery at top of the file and your code will executed perfectly I also have same issue and resolved now

papi83dm's avatar

@edtrade @warmwhisky Did you get it to work ? I'm having the same issue as well. I would like to have all my JavaScript compiled under one file. As a work around I'm loading jQuery from the cdn in the blade template.

MamoonaShuja's avatar

@papi83dm it's not different. it's just a way if you dont want to mix-up imports and you custom js files like if you had done js for admin and user panel different then it's better to create there different files that's what i suggest for better and clean approach

YungProf's avatar

@edtrade I've been visiting Laracast to get help for years but I've only just created an account now to type this.

Rather than use SetTimeout, wrap your jQuery code in:

document.addEventListener('DOMContentLoaded', function () {
	// jquery code here
}, false);

It worked for me. PS: I was trying to import PerfectScrollbar, not jQuery ... but it's the same principle, "my code was running before vite files are loaded".

8 likes
johan.vdbroek's avatar

@drehimself while I like keeping things simple. And while this thread got a bit old. I'll add my +1 for adding jQuery, and any frontend dependency really, into the asset bundling process. Why? Because it will allow you to utilize package.json and make application maintenance a lot easier:

  • Your package.json will contain all dependencies, which is a win
  • You can use npm audit to scan for known security issues, which is another win
  • You can run the powerful npm audit fix which applies the needed patches, win-win-win :)
bhojkamal's avatar

@drehimself How to include this ?

window.Popper = require('popper.js').default;

in new vite. please help.

1 like
randit's avatar

@bhojkamal you should change it to ES6 way

import * as Popper from 'popper.js';
window.Popper = Popper.defaults;
1 like
hassam's avatar
How to fix Uncaught ReferenceError: $ is not defined issue with vitejs

100% Working method. I consumed around 4 hours to find a solution and now you can config any node_modules package in Laravel with vitejs.

this method will help you to configure any npm package. just import package in /resources/js/app.js and add <script type="module"></script> where you want to use that npm package.

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

First understand why this error occurred.
- First your route URL request load
- then app.css
- then app.js
- then all other imports (like fonts, svg, css, js)
- (means jquery, select2, dropzone etc will load after app.js)
-- and due to this you got the Uncaught ReferenceError: $ is not defined


Goto: (check the sequence of your project)
-- Inspect element
-- Network
-- and you can see the request sequence

Suppose you import jQuery, select2, dropzonejs, and other packages in  resources/js/app.js like
-------------------------------
import $ from 'jquery'
import select2 from "select2"
import Dropzone from "dropzone"

window.jQuery = window.$ = $
window.Dropzone = Dropzone
-------------------------------

/**
then above all imports didn't work properly reason you need to add module in <script> attribute.
Using module on your inline <script> tag solves this issue by loading the JavaScript in the correct order, making app.js load in before your inline <script> tags and populating the window object with jQuery.
**/


Example:
<script type="module">
    $("button").click(function() {
        $("p").hide();
    });

    $(".select2").select2();
</script>


and maybe you use @stack, @push then the code will be

@push('js_after')
<script type="module">
    $("button").click(function() {
        $("p").hide();
    });

    $(".select2").select2();
</script>
@endpush

Below is the complete details step by step.

1st: install jquery using

npm i jquery
npm i select2  // maybe
npm install --save dropzone // maybe

2nd: add Jquery alias in vite.config.js [you can skip this step, if you don't want alias and jump to 3rd-step]

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.js',
            ],
            refresh: true,
        }),
    ],
    resolve: {
        alias: {
            '$':  'jQuery',
        },
    },
});

3rd: add the below code at end of the resources/js/app.js

import $ from 'jquery'
import select2 from "select2"
import dropzone from "dropzone"

window.jQuery = window.$ = $
window.Dropzone = Dropzone

4th: make sure you added @vite(['resources/css/app.css', 'resources/js/app.js']) in <head>

<head>
    <meta charset="utf-8">
    <title>Dashboard</title>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>

    @yield('content')

    @stack('js_after')
</body>

5th: try to add type="module" in <script>

<script type="module">
    $("button").click(function() {
        $("p").hide();
    });

    $(".select2").select2();
</script>

with child blade

@extends('layouts.dashboard')
@section('content')
    <!-- your blade code -->

    @push('js_after')
        <script type="module">
                $("button").click(function() {
                $("p").hide();
                });

                $(".select2").select2();
        </script>
    @endpush

@endsection

this method will help you to configure any npm package. just import package in /resources/js/app.js and add <script type="module"></script> where you want to use that npm package.

12 likes
thinkverse's avatar

@hassam I think you're misunderstanding what resolve.alias does. It's used to alias imports.

Say you have the following relative import you wanna alias to another easier string.

import './bootstrap';

You can then add an alias for that resolve to let's say boot.

resolve: {
    alias: {
        boot: './bootstrap'
    }
}

Now you can use that alias in your JavaScript files, as long as those are running through Vite.

import 'boot';

So with the aliases you've defined, you can now import jQuery using the following.

import $ from "$";
1 like
Botv0091's avatar

@hassam I don`t understand where place that code ... i try in app.blade.php after @vite(['resources/css/app.css', 'resources/js/app.js']) i try it at bottom ... and a steel got error

(index):667 Uncaught TypeError: $(...).select2 is not a function

I don`t get how it works - please help ))

hassam's avatar

@Botv0091

Add below code in resources\js\app.js. You might skipped import select2 in resources\js\app.js.

I have "select2": "^4.1.0-rc.0", in package.json in dependencies.

import $ from 'jquery'
import select2 from "select2"

window.jQuery = window.$ = $

window.select2 = select2 //(add this if select2 not work. But I hope select2 will work without this line)

And then add below code in .blade.php file where you need

<script type="module">
    $("button").click(function() {
        $("p").hide();
    });

    $(".select2").select2();
</script>
1 like
bagusk99's avatar

@hassam this is the best solution for me, i'm just adding type="module" to my script tag and my node package work perfectly, thank you so much

Mahdipourlotfi's avatar

@hassam آقا دمت گرم بعد از دوسال بازهم کد شما کارگشاست👍👍👍👍

thinkverse's avatar

I've seen a lot of threads with users having this issue, the fix is actually simple. It differs from where you're accessing jQuery. If you only write your jQuery inside your app.js file then you only need to import it.

import $ from "jquery";

If you need to write jQuery inline in a <script> tag, then you also need to add it to the window object.

window.$ = $;

Then if you need to write inline, use a <script> tag that has the type of module.

<script type="module">
// $
</script>

The Uncaught ReferenceError: $ is not defined issue is due to the fact that Laravel's generated <script> tag uses a type of module. So using a regular <script> tag won't work since that's loaded in before app.js by the browser and jQuery won't be available on the window object by that time.

Using module on your inline <script> tag solves this issue by loading the JavaScript in the correct order, making app.js load in before your inline <script> tags and populating the window object with jQuery.

12 likes
graphicmarines's avatar

Hi guys, I have been using laravel 9 with vite and vue 3, at first i was having a challenge for having to import $ in app.js and even in bootstrap but nothing worked. Also at the same time i had intergrted adminlte 3 in my laravel vue app. the following are my configurations that worked: in App.js:

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

 import './bootstrap';
 import { createApp } from 'vue';
 // import LoadScript from "vue-plugin-load-script";
 import {store} from "./store/index";
 // components
 import Roles from './components/essentials/Roles.vue';
 import Auth from './components/essentials/Auth.vue';
 import Others from './components/essentials/Others.vue';
 import router from './router';
 import GuestmasterComponent from './components/GuestMaster.vue';
 import AuthmasterComponent from './components/AuthMaster.vue';
 import ExampleComponent from './components/ExampleComponent.vue';
 import Form from 'vform';
 import VueGoodTablePlugin from 'vue-good-table-next';
 import LoadScript from "vue-plugin-load-script";

 // import the styles
 import 'vue-good-table-next/dist/vue-good-table-next.css';

 const app = createApp({});

 //javascript requirement files
 app.component('guestmaster', GuestmasterComponent);
 app.component('authmaster', AuthmasterComponent);
 app.component('examplemaster', ExampleComponent);

 //global access
 window.Form = Form;

 // Vue.mixin
 app.mixin(Roles);
 app.mixin(Auth);
 app.mixin(Others);

 app.use(LoadScript);
 app.use(VueGoodTablePlugin);
 app.use(router);
 app.use(store);
 app.mount('#app');

in bootstrap.js

import _ from 'lodash';
window._ = _;

import 'bootstrap';
import $ from 'jquery'
import * as Popper from 'popper.js';


window.jQuery = window.$ = $
window.Popper = Popper.defaults;
import 'admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js';
import 'admin-lte/dist/js/adminlte.min.js';

/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

import axios from 'axios';
window.axios = axios;

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

/**
 * Echo exposes an expressive API for subscribing to channels and listening
 * for events that are broadcast by Laravel. Echo and event broadcasting
 * allows your team to easily build robust real-time web applications.
 */

// import Echo from 'laravel-echo';

// import Pusher from 'pusher-js';
// window.Pusher = Pusher;

// window.Echo = new Echo({
//     broadcaster: 'pusher',
//     key: import.meta.env.VITE_PUSHER_APP_KEY,
//     wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
//     wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
//     wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
//     forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
//     enabledTransports: ['ws', 'wss'],
// });

vite.cofig.js

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
import VitePluginBrowserSync from 'vite-plugin-browser-sync';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/sass/app.scss',
                'resources/js/app.js',
            ],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
        VitePluginBrowserSync({
            bs: {
              proxy: {
                  target: "http://surveyapp.test",
              },
              ui: {
                port: 3000
              },
              notify: false
            },
        }),
    ],
    resolve: {
        alias: {
            vue: 'vue/dist/vue.esm-bundler.js',
        },
    },
});
shahzada83's avatar

Laravel with vite Step 1 : npm install jquery --save-dev Step 2 : Add the below code to app.js //------------------------- import $ from 'jquery'; window.$ = $; //------------------------- Step 3: Try adding the below code in welcome.blade.php to test $('body').html('Hello World!'); Note : type="module" in script

loomy's avatar

Hi folks, I've followed your thread a while and now I am running into same issue: I want to use in my Laravel 10 installation with vite the package https://swiperjs.com/ so I've installed it: npm install swiper and now? I've tried to add import swiper from 'swiper' in my res/app.js file and @import in the res/app/app.css ran npm run build with no errors, but if I try to use it in my livewire blade file @section('scriptsafter') var swiper = new Swiper(".mySwiper", {}); @endsection I get the error that swiper is not defined. Can anyone here explain in simple words how to install and use a package in laravcel 10 if I want to install it with npm and use it in livewire or anywhere else in the page? Thank you!

London's avatar

I am also struggling getting smartWizard to run.

app.js

import './bootstrap';

bootstrap.js

import $ from 'jquery';
window.$ = $;
import "smartwizard/dist/css/smart_wizard_all.css";
import smartWizard from 'smartwizard';
window.jQuery = window.$ = $
window.smartWizard = smartWizard;

welcome.blade.php

@vite(['resources/sass/app.scss', 'resources/js/app.js'])
<script type="module">
            $(function() {
                $('#smartwizard').smartWizard();
            });
    </script>

Get error: jQuery.Deferred exception: $(...).smartWizard is not a function

London's avatar

In bootstrap.js had to change this line...

window.smartWizard = smartWizard();
Insurteched's avatar

I know this is an old post, but has anyone found an tidy solution to order the js loading with Vite. I have tried many permutations and get the feeling I am chasing my tail. Against my ideals, I am ready to go back to adding the js via cdn directly into the blade footer file.

For info, my current app.js looks like this:

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

import './bootstrap'; import 'jquery-ui/dist/jquery-ui'; import './custom.js';

This gives the following error coming from factory( jQuery ); in jquery-ui.js: Error: "Uncaught ReferenceError: jQuery is not defined"

Please or to participate in this conversation.