Laravel Mix

  • Laravel Mix provides a fluent API for defining Webpack build steps for your Laravel application (using several common CSS and JavaScript pre-processors and live preview with Browsersync)

Frontend scaffolding

  • While Laravel does not dictate which JavaScript or CSS pre-processors to use, it does provide a basic starting point for Bootstrap, React and/or Vue
  • The frontend scaffolding provided by Laravel is located in the Composer package laravel/ui
    • Open a terminal and install the package: composer require laravel/ui:^2.4
  • Next, you can install the basic Bootstrap frontend scaffolding (the login scaffolding comes later in this course):
    php artisan ui bootstrap

REMARK

For further reference, all ui artisan commands to install frontend scaffolding for Bootstrap, Vue and React, both without and with login/registration functionality, are listed below

// Generate basic frontend scaffolding
php artisan ui bootstrap
php artisan ui vue
php artisan ui react

// Generate login/registration scaffolding
php artisan ui bootstrap --auth
php artisan ui vue --auth
php artisan ui react --auth
1
2
3
4
5
6
7
8
9

Install Laravel Mix

  • Open a terminal and execute the command npm install to install the necessary Node modules
  • Open the Mix config file webpack.mix.js and add Browsersync at the end of the file



 
 
 
 

mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

mix.browserSync({
    proxy: 'vinyl_shop.test',
    port: 3000
});
1
2
3
4
5
6
7
  • Open a new terminal window and execute
    npm install browser-sync browser-sync-webpack-plugin@2.0.1 --save-dev --production=false --legacy-peer-deps
    to install some additional Node packages
  • Open a new terminal window and execute npm run watch (or click on the watch task from the npm tab)
    • This command runs a NPM script that launches a development web server which can be reached via http://localhost:3000 and which proxies our domain http://vinyl_shop.test. The script "watches" changes in relevant files, and if a change is detected, the tasks listed in webpack.mix.js are executed
      • The necessary JavaScript files are bundled and the resulting file is copied into the public/js folder (line 1)
      • The Sass/SCSS files are compiled and the resulting CSS file is copied into the public/css folder (line 2)
      • The page gets reloaded via Browsersync (lines 4-7)
  • Open http://localhost:3000 in a browser and edit one of the Blade pages to see Browsersync in action

REMARKS

  • The Sass compilation of the Bootstrap source code generates a lot of (deprecation) warnings stating that 'Using / for division is deprecated and will be removed in Dart Sass 2.0.0.'
    To suppress these warnings you should downgrade Sass to version 1.32.13 with npm install sass@1.32.13 --save-dev
  • If you use a CDN to link your CSS and JavaScript frameworks, you can remove (or comment out) the first two lines in webpack.mix.js, and skip the remainder of this section. Your Mix experience will be limited to Browsersync.
  • Add an additional line to the first mix statement if you would like to generate (Javascript and CSS) source maps:


 

   mix.js('resources/js/app.js', 'public/js')
      .sass('resources/sass/app.scss', 'public/css')
      .sourceMaps(true, 'source-map');
1
2
3

Update the template

  • After you run npm run watch there will be two extra files in the public folder
    • public/css/app.css: this file contains the full Bootstrap CSS
    • public/js/app.js: this file contains all the JavaScript code (jquery.js, and bootstrap.bundle.js)
  • Link these files in the template resources/views/layouts/template.blade.php using the Laravel mix() helper function
    • Replace the three CDN links (one CSS and two JavaScript links) in our template with the two links to these files





 









 



<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="{{ mix('css/app.css') }}">
    <title>@yield('title', 'The Vinyl Shop')</title>
    @include('shared.icons')
</head>
<body>
    @include('shared.navigation')
    <main class="container mt-3">
        @yield('main', 'Page under construction...')
    </main>
    @include('shared.footer')
    <script src="{{ mix('js/app.js') }}"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

WARNINGS

  • From now on you will program only in the SCSS and JavaScript files within the folders resources/js and resources/sass
  • Make sure that the npm run watch script is running, otherwise your changes will not be passed to the public folder (and thus, will not be visible in the browser)

Customize Bootstrap with SCSS

  • The folder resources/sass contains two files
    • The main file app.scss that will be automatically compiled to public/css/app.css
    • A partial _variables.scss
      • Imported in app.scss BEFORE the Bootstrap import
      • Can be used to overwrite Bootstrap variables or to add your own variables
  • Open resources/sass/app.scss


 







// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css');

// Variables
@import 'variables';

// Bootstrap
@import '~bootstrap/scss/bootstrap';
1
2
3
4
5
6
7
8
9
  • If you want to add some additional custom code (e.g. a minimum height for the main element), you can add it AFTER the Bootstrap import










  •  
     
     
     

    // Fonts
    @import url('https://fonts.googleapis.com/css?family=Nunito');
    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css');
    
    // Variables
    @import 'variables';
    
    // Bootstrap
    @import '~bootstrap/scss/bootstrap';
    
    //Custom code
    main {
      min-height: 500px;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    TIP

    If you have a lot of custom code, it is better to add some extra partials to make the code more readable

    • Create a new file resources/sass/_main.scss and add this code
    main {
      min-height: 500px;
    }
    
    1
    2
    3
    • Import _main.scss in app.scss AFTER the Bootstrap import











     

    // Fonts
    @import url('https://fonts.googleapis.com/css?family=Nunito');
    @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css');
    
    // Variables
    @import 'variables';
    
    // Bootstrap
    @import '~bootstrap/scss/bootstrap';
    
    // Custom code
    @import 'main';
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    Add additional JavaScript

    • If you need extra JavaScript that applies to every page (later in this course), it is best practice to create a global JavaScript file that you can incorporate into the automation immediately
    • Create a new file resources/js/vinylShop.js
      • Add a simple console log message to check if it's visible inside the browser console
    let VinylShop = (function () {
    
        function hello() {
            console.log('The Vinyl Shop JavaScript works! 🙂');
        }
    
        return {
            hello: hello    // publicly available as: VinylShop.hello()
        };
    })();
    
    export default VinylShop;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    • Open resources/js/app.js and import vinylShop.js


     
     
     
     
     

    require('./bootstrap');
    
    // Make 'VinylShop' accessible inside the HTML pages
    import VinylShop from "./vinylShop";
    window.VinylShop = VinylShop;
    // Run the hello() function
    VinylShop.hello();
    
    1
    2
    3
    4
    5
    6
    7

    REMARK

    The code above is based on the JavaScript revealing module pattern. We refer to the following introductions for the interested reader:

    JavaScript in console

    Versioning (optional)

    • Look at the source code inside the browser (F12 or Ctrl+U)
    • The CSS link (for example) looks like this:
    <link rel="stylesheet" href="/css/app.css" />
    
    1
    • Add the following code to webpack.mix.js in order to enable versioning (or cache busting): each time your code changes, a new hashed query string file will be generated
    mix.version();
    
    1

    REMARK

    You can either add the line above separately in your webpack.mix.js file, or you can add it alternatively like this:




     

       mix.js('resources/js/app.js', 'public/js')
          .sass('resources/sass/app.scss', 'public/css')
          .sourceMaps(true, 'source-map')
          .version();
    
    1
    2
    3
    4
    • Stop the watch script with Crtl + C and restart it with npm run watch
    • Look at the source code to see the extra hash at the end of the file
    <link rel="stylesheet" href="/css/app.css?id=e0a0cd9aee98968ed025" />
    
    1

    Disable notifications (optional)

    • If you don't like the pop-up (and beep) every time Mix compiles a new version, you can disable this by adding this line to webpack.mix.js
    mix.disableNotifications();
    
    1
    • Stop the watch script with Crtl + C and restart it with npm run watch

    Recompile for production

    WARNING

    The scripts compiled with npm run watch are NOT production ready! They are not minimized and still contain a lot of overhead code. Every time you put a new version of your CSS or JavaScript file online, first optimize your code with the command npm run prod.

    • Stop the watch script with Crtl + C
    • Build a minimized version of app.css and app.js with the command npm run prod
    • Upload the files to your hosting
    • Start the watch script (again) with the command npm run watch
    Last Updated: 10/10/2021, 8:58:05 AM