0

I'm working on my first Laravel project (5.4), actually I don't understand why my js script doesn't work like I expected. I use Mix and Blade :

// webpack.mix.js
let { mix } = require('laravel-mix').mix;

    // copy fonts and patterns
mix .copy('resources/assets/vendor/bootstrap/fonts', 'public/fonts')
    .copy('resources/assets/vendor/font-awesome/fonts', 'public/fonts')
    .copy('resources/assets/patterns', 'public/css/patterns')

    // compile scss and concatenate css files
    .sass('resources/assets/sass/app.scss', 'public/css')
    .styles([
        'resources/assets/vendor/bootstrap/css/bootstrap.css',
        'resources/assets/vendor/animate/animate.css'
        // ...
    ], 'public/css/vendor.css')

    // concatenate js files
    .js([
        'resources/assets/vendor/jquery/jquery-3.1.1.min.js',
        'resources/assets/vendor/bootstrap/js/bootstrap.js',
        'resources/assets/js/app.js'
        // ...
    ], 'public/js/app.js')
    .options({ processCssUrls: false }); // fix for path issue : https://github.com/almasaeed2010/AdminLTE/issues/1360

After npm run dev compliation looks good :

DONE  Compiled successfully in 6497ms                                                     4:20:57 PM

                                   Asset      Size  Chunks                    Chunk Names
  fonts/glyphicons-halflings-regular.ttf   45.4 kB          [emitted]         
                              /js/app.js    1.2 MB       0  [emitted]  [big]  /js/app
                       mix-manifest.json  66 bytes          [emitted]         
  fonts/glyphicons-halflings-regular.eot   20.1 kB          [emitted]         
fonts/glyphicons-halflings-regular.woff2     18 kB          [emitted]         
  fonts/glyphicons-halflings-regular.svg    109 kB          [emitted]         
 fonts/glyphicons-halflings-regular.woff   23.4 kB          [emitted]         
                            /css/app.css    178 kB       0  [emitted]         /js/app
           fonts/fontawesome-webfont.ttf    166 kB          [emitted]         
           fonts/fontawesome-webfont.svg    444 kB          [emitted]  [big]  
           fonts/fontawesome-webfont.eot    166 kB          [emitted]         
          fonts/fontawesome-webfont.woff     98 kB          [emitted]         
         fonts/fontawesome-webfont.woff2   77.2 kB          [emitted]         
                   fonts/FontAwesome.otf    135 kB          [emitted]         
         css/patterns/header-profile.png   5.88 kB          [emitted] 

CSS works fine, bootstrap.js also works and when I check inside /js/app.js it seems like everything is inside.

An here is my tempate :

{{-- app.blade.php--}}
<!DOCTYPE html>
<html lang="{{ config('app.locale', 'en') }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@yield('title')</title>
    <link rel="stylesheet" href="{!! asset('css/vendor.css') !!}" />
    <link rel="stylesheet" href="{!! asset('css/app.css') !!}" />
</head>
<body>
    <!-- Main view  -->
    @yield('content')

    <script src="{!! asset('js/app.js') !!}" type="text/javascript"></script>

    @section('scripts')
    @show
</body>
</html>

My troubles began when I want to add a script inside the script section from a child.

@extends('layouts.app')

@section('scripts')
    <script type="text/javascript">
        $(document).ready(function () {
            alert('test');
        });
    </script>
@endsection

I got Uncaught ReferenceError: $ is not defined like if jquery wasn't loaded.

I have no clue why, any idea ?

[note]
It works if I replace inside app.blade.php :

<script src="{!! asset('js/app.js') !!}" type="text/javascript"></script>

with :

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
2
  • For fun, if you replace $ with jQuery (so you'd have jQuery(document).ready(function () {), does it work? Also, if you open your browser's dev tools, is app.js loading successfully? Commented Mar 30, 2017 at 19:42
  • Same error with jQuery. As far I can see app.js is loaded, that why I don't understand what is wrong. Commented Mar 30, 2017 at 19:56

3 Answers 3

4

I finally figure who was guilty : Mix (or the way I used Mix)

I wrongly believed that mix.js and mix.scripts was the same function. But mix.scripts only combine and minify files while mix.js also do compiling ECMAScript 2015 and module bundling. I don't really know why but it was a problem in my case.

mix.js(['public/js/admin.js',
    'public/js/dashboard.js'], 'public/js');

replaced by :

mix.scripts(['public/js/admin.js',
    'public/js/dashboard.js'], 'public/js/all.js');

See more : Laravel doc

Sign up to request clarification or add additional context in comments.

2 Comments

You need to specify a destination filename option for mix.scripts, such as 'public/js/all.js' just specifying a directory results in a EISDIR: illegal operation on a directory error.
Sorry I meant for the mix.scripts one only, the mix.js one is fine as a folder
2

I had a similar issue, and the problem was that at the moment I was using jQuery for the first time, the app.js file generated by webpack wasn't loaded yet.

You can do a simple test to see if you have the same issue. In your first chunk of code where you use jQuery (the line of code that throws you the $ error), wrap that code in this:

document.addEventListener("DOMContentLoaded", function(event) { 
 // Your jQuery code
});

One workaround is to load app.js earlier in your blade main layout file, but I am sure it can be done in a better way. I am fairly new to Laravel, so I am still figuring out these kinds of things...

Edit:

Ok, I think I understood now how to do it properly:

  1. In your main blade layout (in my case app.blade.php), at the bottom right before the </body> tag, load your webpack script, all other external scripts you might load, and finally add a yield scripts section.

Example:

<script src="/js/app.js"></script>
<script src="other/scripts/that/you/need.js"></script>
@yield('scripts')
  1. In the blade template where you need jQuery code, instead of adding it directly in the content section, you create a new section called scripts.

Example:

@section('content')
//Your view code
@endsection

@section('scripts')
//Your jQuery code
@endsection

That way, your jQuery code is loaded after the main layout has already loaded the webpack javascript file (which loads jQuery).

2 Comments

Nice try, but it doesn't work, document.addEventListener doesn't solve the issue. And the html structure that you suggest is the one I currently use.
This just saved me hours of frustration. Thanks dude.
0

Simply include js file as shown below in your blade files as in my case I'm including add-section.js which is placed inside public/js

<script src="{{ asset('/js/add-section.js') }}"></script>
@yield('scripts')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.