Sublimely Magnificent Laravel Mix

A remake of Laravel Elixir is now called Laravel Mix. It comes with Laravel 5.4 out-of-the-box and in this free tutorial, we will go through all the important parts so that you can quickly get started with it.



Introduction

In plain terms, the main difference between Laravel Elixir and Laravel Mix is that Laravel Mix is based on Webpack, while Laravel Elixir is based on Gulp. But, under the hood Laravel Mix is a much more elegant and cleaner solution.

In this tutorial, we will go through all the basics like:

  • installation
  • running
  • stylesheets (source maps)
  • JavaScript (code splitting)
  • copying
  • versioning
  • notifications

The main reason why I think that Laravel Mix is better than Laravel Elixir is because it does not assume the folder structure. You reference the resource files from the root directory, and your folder structure (input & output directories) can be whatever you want.

This means that you can use Laravel Mix outside a Laravel application without any additional configuration like we had to do with Laravel Elixir in my recent tutorial Laravel Elixir Without Laravel.

Another very cool feature of Laravel Mix is Code splitting. Continue reading to find out more.

Installation

Requirements for installing Laravel Mix are Node.js and NPM. You can verify that you have them installed by running these commands in your command line:

node -v
npm -v

If you do not have them installed, you can download the installers from the Node.js download page.

Because Laravel Homestead comes with Node.js and NPM preinstalled, a lot of you may be tempted to use it for asset manipulation. I suggest avoiding doing that, and instead, I suggest that you install Node.js and NPM on your host machine; in my case Windows PC.

Within a fresh installation of Laravel 5.4 comes a package.json file and inside it, you will find the following dependencies:

{
  ...
  "devDependencies": {
    "axios": "^0.15.3",
    "bootstrap-sass": "^3.3.7",
    "jquery": "^3.1.1",
    "laravel-mix": "^0.7.2",
    "lodash": "^4.17.4",
    "vue": "^2.1.10"
  }
}

If you read the documentation on Laravel Mix, it says that to install Laravel Mix, you just have to enter npm install in your command line which is false. Running npm install at this point will install the above mentioned "other" stuff, which if you are like me You don't actually need.

Laravel Mix does not need any of the other dependencies mentioned in that file to work. Those are some Laravel specifics which you probably don't need. I personally just delete them from package.json file, and leave only laravel-mix, so that my file looks like this:

{
  ...
  "devDependencies": {
    "laravel-mix": "^0.7.2"
  }
}

Now run npm install to install Laravel Mix.

One thing to mention. In the Laravel Mix documentation it says that if you are running a VM on a Windows host system, you may need to run npm install --no-bin-links. Don't do it!

If you have Node.js and NPM installed on Windows, and are using Git Bash (which comes with Git; with symbolic links enabled) then everything will work correctly. Using --no-bin-links just makes a huge mess on the disk and takes much more disk space.

Running

If you take a look in package.json file, you should see four scripts mentioned in that file:

  • dev
  • watch
  • hot
  • production

npm run dev - runs all Mix tasks. One time thing.

npm run watch - runs all Mix tasks and continues to watch your assets for changes. If a change occurs it automatically recompiles your assets. Use this while actively working on your assets.

npm run production - runs all Mix tasks and minifies output. When you are done working on your assets, run this command before pushing your application to production.

npm run hot - this is complicated to explain and I am not sure that I know exactly how it works, but here it goes. It runs all Mix tasks, but it stays active and watches for changes in your assets. If a change occurs it "updates" only the module which has changed, notifies your application of the change and updates the code in the browser without a refresh. Something like that... very cool!

Stylesheets (source maps)

webpack.mix.js file is the main file for Laravel Mix in which all of your tasks are to be defined.

Laravel Mix supports Less, Sass, plain CSS and Source Maps.

Less & Sass

The very basic example is this:

mix.less('resources/assets/less/app.less', 'public/css');

It compiles resources/assets/less/app.less into public/css/app.css.

You can modify the output file name and/or location by specifying it in the second argument like so:

mix.less('resources/assets/less/app.less', 'public/stylesheets/styles.css');

To compile multiple Less files you can chain the tasks together like so:

mix.less('resources/assets/less/app.less', 'public/css')
   .less('resources/assets/less/admin.less', 'public/css');

The same things apply to Sass tasks, namely .scss and .sass files. Just replace mix.less with mix.sass and you are ready to go.

Plain CSS

To combine multiple CSS files into a one file, you may use the mix.combine task like so:

mix.combine([
    'public/css/vendor/normalize.css',
    'public/css/vendor/videojs.css'
], 'public/css/all.css');

Source Maps

By default, source maps are disabled because they make the whole process of compiling assets longer and more resource demanding. I personally like using Source Maps because I find it very helpful to be able to inspect an element in the browser, and see exactly on which line and in which file is that style or class applied.

To enable Source Maps, you have to add mix.sourceMaps() to your webpack.mix.js file:

mix.js('resources/assets/js/app.js', 'public/js')
   .sourceMaps();

JavaScript (code splitting)

Running this single line of code:

mix.js('resources/assets/js/app.js', 'public/js');

takes care of:

  • compiling ECMAScript 2015
  • module bundling
  • minification
  • concatenating plain JavaScript files

Very cool stuff, but the feature that I find the most interesting is Code Splitting.

Code Splitting

So imagine that you are working on your application JS code and you import jQuery, React.js, Vue.js and many other "vendor" libraries. And besides that, you have your own JS code written in modules.

If you would to just use mix.js to compiles your JS files, you would get a huge file containing all the code necessary for execution. Lets says that that file is around 2MB in size. Every time you make a change to your JS code (it can be a simple console.log removal), your client browser has to fetch the new version of that bundled JS file which is again around 2MB in size.

Code splitting is here to reduce the size of the file that needs to be fetched by separating your code from the "vendor" libraries. That way, if your code changes, the browser only has to fetch the file containing your code and not the file containing the libraries.

mix.js('resources/assets/js/app.js', 'public/js')
   .extract(['vue'])

The extract method accepts an array of all libraries or modules that you wish to extract into a vendor.js file.

Using the above command will generate the following files:

  • public/js/manifest.js - The Webpack manifest runtime
  • public/js/vendor.js - Your vendor libraries
  • public/js/app.js - Your application code

To avoid JavaScript errors, be sure to load these files in the proper order:

<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script>
<script src="/js/app.js"></script>

Copying

As with Laravel Elixir, Laravel Mix comes with copy task.

mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');

You can copy files or directories. This is very helpful when you have to copy some fonts, CSS or JS files from node_modules directory to your public directory for further asset manipulation or reference.

Versioning

Another cool feature of Laravel Mix, but which was also available on Laravel Elixir is Versioning. Because files are cached in the browser for x period of time, there is no way of letting the browser know to fetch the latest version of the file if a change has occurred.

Versioning appends a unique hash at the end of the file, each time it changes so that the browser know to fetch the latest version.

mix.js('resources/assets/js/app.js', 'public/js')
   .version();

After running this task, you will not know the exact file name, so this is where Laravel's mix helper function comes into action. The mix function will automatically determine the correct file name:

<link rel="stylesheet" href="{{ mix('/css/app.css') }}">

Notifications

By default, OS notifications are displayed after each Laravel Mix task has completed. To disable the notifications you should add:

mix.disableNotifications();

to your webpack.mix.js file.


Thank you for reading this tutorial. If you have found a mistake on my part let me know in the comments bellow so that I can fix it. Have a great week.

Sources

Credits

  • Cover image Laravel - Ignited created by rafdesign

Comments