New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jQuery is not defined after migrating to Laravel 5.4 #17634

Closed
DominiqueFERET opened this Issue Jan 28, 2017 · 32 comments

Comments

Projects
None yet
@DominiqueFERET
Copy link

DominiqueFERET commented Jan 28, 2017

  • Laravel Version: 5.4.6
  • PHP Version: 7.0.13

Description:

After migrating to Laravel 5.4 => javascript bug => ReferenceError: jQuery is not defined
(With Elixir in 5.3 everything works fine.)
This variable is defined in asset/js/bootstrap.js
window.$ = window.jQuery = require('jquery');
in javascript console, i see "$" is correctly defined and a variable name jQuery311052537473254022181 is define...

Seem to be a suffix added ... A bug of wepack config of laravel.mix ???

Steps To Reproduce:

Make a simple javascript closure like
function()({ ... })(jQuery);

then compile assets with command "npm run dev" (same thing with npm run production).

When you try the javascript closure => jQuery is not defined.

@tabirkeland

This comment has been minimized.

Copy link

tabirkeland commented Jan 29, 2017

Try changing:

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

to

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

This comment has been minimized.

Copy link
Contributor

reinink commented Feb 7, 2017

Thanks @tabirkeland, that did it for me! I'm no JavaScript wizard, could you explain why $ would be available globally but not jQuery, even though they are both being assigned to window?

@rappasoft

This comment has been minimized.

Copy link

rappasoft commented Feb 12, 2017

I also had this same problem and the above fixed.

@joval-sv

This comment has been minimized.

Copy link

joval-sv commented Mar 15, 2017

I am having the same issue with Framework 5.4.15, but the above fix does not work.

@nejtr0n

This comment has been minimized.

Copy link

nejtr0n commented Apr 23, 2017

Same issue. Fix does not work =(

@mhulu

This comment has been minimized.

Copy link

mhulu commented May 1, 2017

Same error in my fresh 5.4.21, I fixed it using:

  1. delete window.$ = window.jQuery = require('jquery') in bootstrap.js;
  2. in webpack.mix.js add
    mix.webpackConfig({
    resolve: {
    alias: {
    jquery: "jquery/src/jquery"
    }
    }
    });
@mailnike

This comment has been minimized.

Copy link

mailnike commented May 6, 2017

This issue is not yet resolved. Not sure why this was closed?

@gustav1105

This comment has been minimized.

Copy link

gustav1105 commented May 9, 2017

If this is happening inside a child vue component you can add this to that component script and it will work
window.$ = window.jQuery = require('jquery');

@Christophvh

This comment has been minimized.

Copy link

Christophvh commented Jun 10, 2017

@mhulu solution solved my issue.

@shahzadm287

This comment has been minimized.

Copy link

shahzadm287 commented Jun 13, 2017

@tabirkeland not work for me :(
@mhulu please mention file location ? where we add this code.
No idea about this file location.

@UniquelySimilar

This comment has been minimized.

Copy link

UniquelySimilar commented Jul 15, 2017

@tabirkeland solution did not work for me either. I researched Laravel Mix a bit, but didn't want to head down that road just yet.

I found the file /public/js/app.js which appears to contain all of the required js, including jquery.

This appears to be built from /resources/assets/js/app.js by Laravel Mix webpack.mix.js (at my project root):
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');

I noticed that in /resources/views/layouts/app.blade.php the <script> tag
<script src="{{ asset('js/app.js') }}"></script>
was the last tag nested in the body tag.

I moved this <script> tag to the top of the body tag and this seems to have solved the problem.

@tabirkeland

This comment has been minimized.

Copy link

tabirkeland commented Jul 18, 2017

All, Mix has been updated extensively since my solution was posted. I would suggest going with @mhulu solution by modifying your webpack.mix.js and aliasing JQuery.

@Sam-WWHC

This comment has been minimized.

Copy link

Sam-WWHC commented Aug 28, 2017

Yo all. I've just been playing about with this. My problem disappeared when I stopped trying to extract bootstrap's into the vendor's.js.
I'm no js Supremo, but I'm guessing that's where a lot of people's problems might be coming from. It's an obvious file to want to extract, It still looks like a bug to me, but hopefully that'll help someone track it down a bit more accurately.

@ggwebdev

This comment has been minimized.

Copy link

ggwebdev commented Sep 5, 2017

Yes @Sam-WWHC! When i stopped of try extract the jquery from node_modules path the problem disappeared! Thanks!

@devcircus

This comment has been minimized.

Copy link
Contributor

devcircus commented Sep 5, 2017

You can extract, but you'll need to autoload as well if you're using any scripts that expect it to be available globally.

https://github.com/JeffreyWay/laravel-mix/blob/master/docs/autoloading.md

Be sure to only call autoload once and include everything you need autoloaded. Subsequent calls to autoload seem to overwrite previous calls.

@luchaos

This comment has been minimized.

Copy link
Contributor

luchaos commented Sep 11, 2017

thanks @devcircus ! after adding 'jQuery' to the autoload the extraction works as expected again.

after some recompilations the autoload directive randomly suddenly seemed to make a difference. threw some other errors before that - does webpack cache so hard that it needs several recompilations?

the order in which the extractions are defined doesn't matter, right?

mix.js('resources/assets/js/app.js', 'public/js')
    .extract([
        'axios',
        'blazy',
        'bootstrap',
        'd3',
        'jquery',
        'js-cookie',
        'laravel-echo',
        'localforage',
        'localforage-startswith',
        'moment',
        'nvd3',
        'responsive-toolkit',
        'socket.io-client',
        'vue',
        'vue-echo',
        'vue-moment',
        'vue-strap',
        'vuedraggable'
    ])
    .autoload({
        jquery: ['$', 'window.jQuery', 'jQuery'],
    });
@vaxilicaihouxian

This comment has been minimized.

Copy link

vaxilicaihouxian commented Sep 12, 2017

@muhulu
you save my life

@shahzadthathal

This comment has been minimized.

Copy link

shahzadthathal commented Sep 30, 2017

Laravel 5.5
@UniquelySimilar thanks your solution works, it's not good to move js file in the header but it fixed my issue.
The issue is "app.js" loaded at the end of the file and I need some jquery code in register view so I was getting jquery undefined.

I used @mhulu solution but after changing mentioned files and after refresh, the browser, jquery does not work maybe I need to rebuild app.js again, I don't know how to rebuild app.js :)

@UniquelySimilar

This comment has been minimized.

Copy link

UniquelySimilar commented Oct 1, 2017

@shahzadthathal just to clarify, I suggested moving the script tag to the top of the body tag, not into the head tag.
However, opinions of where to place script tags can vary, like many other ideas in the programming world:
https://stackoverflow.com/questions/3531314/should-i-write-script-in-the-body-or-the-head-of-the-html
I'm not interested in starting a discussion or debate, as it is off the subject of this issue. Whatever works for a specific situation.

@chriz74x

This comment has been minimized.

Copy link

chriz74x commented Jan 18, 2018

@devcircus still this doesn't work if you need to bind other components to the same variable.
For example this doesn't work anymore: window.$ = window.jQuery = require('jquery');require('jquery-ui-bundle'); and for the life of me I can't find a solution to make this bundle work again. All I got is "autocomplete is not a function error". The bundle is mixed in app.js still it's not available to the window.

@skinnyvin

This comment has been minimized.

Copy link

skinnyvin commented Jan 27, 2018

Boostrap etc is loaded at the end of the resources/views/layouts/app.blade.php you can place your scripts after this by adding your js that is reliant on jquery to a section in your view:
@section('footer-js') <script> $(function() {alert('Jquery is defined and ready for service.');});</script> @endsection

then yield the section in your layout file AFTER the app.js declaration:

<script src="{{ asset('js/app.js') }}"></script> @yield('footer-js')

This way you can keep your js in your view and load it after Jquery is made available by app.js.

@RPJ18

This comment has been minimized.

Copy link

RPJ18 commented Mar 22, 2018

I found a solution for me with something similar to what you wrote. @UniquelySimilar but i didn't put the script tag for app/js on top of body, i put it at the end. Whatever works. oh, i almost forgot, I also remove the defer attribute of the script tag.

@UniquelySimilar

This comment has been minimized.

Copy link

UniquelySimilar commented Mar 22, 2018

@RPJ18 thanks for the update. I recently started working with Vue.js and WebPack, and if doing it again would probably try to resolve this issue with Laravel Mix/WebPack rather than moving the script tag, but it worked for me at the time.

@KangYoosam

This comment has been minimized.

Copy link

KangYoosam commented May 29, 2018

#17634 (comment)
this fixed my problem

@abhaymaurya

This comment has been minimized.

Copy link

abhaymaurya commented Jun 8, 2018

I have been experiencing this issue as well and I found myself the cause of the problem was "defer" attribute in script addition of app.js

<script src="{{ asset('js/app.js') }}" defer></script>

this "defer" tag was forcing script to load only after page was loaded. So I simply put the same attribute to the other js file addition as well where I needed jQuery and of course put it below the app.js addition.

This way both scripts loaded after page has completed loading and as app.js came before, it made jQuery available to my other script.

Maybe helps someone.

@tuhin-paul

This comment has been minimized.

Copy link

tuhin-paul commented Jun 21, 2018

None of the above worked for me. I solved this issue by adding the following:

mix.webpackConfig(webpack => {
  return {
	        plugins: [
	            new webpack.ProvidePlugin({
	                $: 'jquery',
	                jQuery: 'jquery',
	                jquery: 'jquery',
	               'window.jQuery': 'jquery'
	        })
	    ]
      };
  })

mix.autoload is supposed to do the same internally but it somehow isn't working as expected for me. This is the only way I could extract Bootstrap without getting jQuery is not defined error.

P.S. found this here: https://stackoverflow.com/questions/49351415/laravel-mix-uncaught-referenceerror-jquery-is-not-defined

@mohamedhakika

This comment has been minimized.

Copy link

mohamedhakika commented Oct 9, 2018

I was having the same problem in laravel 5.7, I tried some solutions above did not work,
For me adding type="text/javascript" solved the problem.
Before <script src="{{ asset('js/app.js') }}"></script> did not work.
Now <script src="{{ asset('js/app.js') }}" type="text/javascript"></script> this solved my day, but I don't know why.

@rameshnavi

This comment has been minimized.

Copy link

rameshnavi commented Oct 22, 2018

Faced the same problem. For me, it was defer loading app.js in the header was creating the issue.
Moved to the footer, removed defer, and added inline script below that. It worked :-)

<script src="{{ asset('js/admin.js') }}"></script>
@yield('local_script')
@steve5287

This comment has been minimized.

Copy link

steve5287 commented Nov 12, 2018

I fixed by just removing "defer" from script tag.
My laravel 5.7 installation included <script src="{{ asset('js/app.js') }}" defer></script> <--- this tag, so i removed the defer as i mentioned before by just leaving <script src="{{ asset('js/app.js') }}"></script> like that... It fixed now =)

@LarBearrr

This comment has been minimized.

Copy link

LarBearrr commented Dec 14, 2018

@steve5287 I too was able to solve the $ reference error by removing defer however, I now have an error about Vue not being able to find #app

Did you run into this same issue?

UPDATE: Just moving things around, and putting <script src="{{ asset('js/app.js') }}"></script> at the end of my layout Blade, before the scripts section has solved both issues. Would still like to know how to get this working without modifying the vanilla templates, if possible.

Also, what is the underlying issue here? It seems rather odd that a vanilla Laravel app would have such difficulty using jQuery in a Blade template.

@steve5287

This comment has been minimized.

Copy link

steve5287 commented Dec 14, 2018

@steve5287 I too was able to solve the $ reference error by removing defer however, I now have an error about Vue not being able to find #app

Did you run into this same issue?

UPDATE: Just moving things around, and putting <script src="{{ asset('js/app.js') }}"></script> at the end of my layout Blade, before the scripts section has solved both issues. Would still like to know how to get this working without modifying the vanilla templates, if possible.

Also, what is the underlying issue here? It seems rather odd that a vanilla Laravel app would have such difficulty using jQuery in a Blade template.

I also moved the app.js tag at the end of the blade template. Don't know why they put it at the top "head" tag. Still having problems?

@bhanushalimahesh3

This comment has been minimized.

Copy link

bhanushalimahesh3 commented Jan 8, 2019

@luchaos autoload worked like charm for me :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment