Using Laravel Mix in Your WordPress Theme

Categories: Frontend, WordPress

I have been using Laravel Mix or Elixer as it was once known with Laravel for a long time now and have recently started using it with my WordPress projects. I thought I would share how you can get up and running with as little hassle as possible. I also include my mix() method that will allow you to use cache-busting.

What is Mix?

Stragiht from the site

Laravel Mix provides a clean, fluent API for defining basic webpack build steps for your Laravel application. Mix supports several common CSS and JavaScript pre-processors.

If you’ve ever been confused about how to get started with module bundling and asset compilation, you will love Laravel Mix!

Laravel Mix comes as part of the popular PHP framework Laravel, But it’s not specific to Laravel. It can also be in standalone projects or even WordPress themes.

Lets get started.

Create a package.json file

The first thing that any node project needs are a package.json file. I grabbed the basic package setup from the laravel site and cleared everything out except for the Mix dependency.

  "private": true,
  "scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  "devDependencies": {
    "laravel-mix": "2.1.*"

Don’t worry too much about the details at the moment.

Next, you should install a few other dependencies. Let’s start with Bootstrap and jQuery.

In the terminal, run the following.

npm install bootstrap-sass --save-dev


npm install jquery --save-dev

Now lets create a WordPress theme style.scss, Here is a sample from my starter theme.

More on that here.

Theme Name: Handle
Template: Axe
Theme URI:
Author: Adam Patterson
Author URI:
Description: Handle is a child theme to Axe
Version: 1.0
License: GNU General Public License
License URI: license.txt

// @import "vendor/bootstrap/scss/bootstrap.scss"; #Bower
// @import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap"; #NPM

Next let’s create our app.js file and require jQuery and Bootstrap.


One of the nice things about Mix is that your config file is greatly simplified from standard Web Pack. Create a webpack.mix.js file.

const { mix } = require('laravel-mix');

mix.js('app.js', './js')
   .sass('style.scss', './');

You can read about a complete list of Mix options and settings in the Laravel Docs.

Next run npm run prod, If you included Bootstrap through NPM you should also notice that a folder fonts/vendor/bootstra-sass/... was created. Webpack is going to look at any paths in your CSS and move them to your project root. It’s possible for you to specify this path.

If you would rather control this your self then you can choose to use Bower installing components into a publicly accessible folder or take care of it your self.

In any case you can make a small change to your Webpack config.

const { mix } = require('laravel-mix');

let scssOptions = {
    processCssUrls: false

mix.js('app.js', './js')
   .sass('style.scss', './').options(scssOptions)

This will prevent Webpack from moving any resources and is usually the path I take.

If you experienced any issues, you might see something like sh: cross-env: command not found and if you do then run the following.

npm install cross-env --save-dev

Along with the production command, there are a few others like npm run dev and npm run watch. Dev is going to generate a non minified files, and source maps if configured. The watch will… watch for file changes, generating source maps as well if configured. Watch also lets you take advantage of browser reloading using Browser Sync, again, Read the Laravel Docs.

Using Mix for cache-busting.

Something that no one else seems to take advantage of is the versioning that Mix offers. For my own themes, I created the mix() method that replicates Laravels own Helper, More on that here.

This method will not work if you simply copy and paste it. It is meant to work with my theme as there are no standard asset paths with WordPress but you should be able to use what I have in this file and get your self setup. Also Feel free to use Axe and Handle, If you are interested in things like Vendor extraction I also go into more detail here

Use what I have suggested or take my helper file and adapt it to work for your case.

if ( ! function_exists('mix')) {
    function mix( $path )
        $pathWithOutSlash = ltrim($path, '/');
        $pathWithSlash    = '/' . ltrim($path, '/');
        $manifestFile     = __m();
//        No manifest file was found so return whatever was passed to mix().
        if ( ! $manifestFile) {
            return __t() . $pathWithOutSlash;
        $manifestArray = json_decode(file_get_contents($manifestFile), true);
        if (array_key_exists($pathWithSlash, $manifestArray)) {
            return __t() . ltrim($manifestArray[$pathWithSlash], '/');
//        No file was found in the manifest, return whatever was passed to mix().
        return __t() . $pathWithOutSlash;

mix('/assets/js/app.js') would result in something like: /assets/js/app.js?id=0b19d505dc2d65c946f3

mix('/assets/js/appNOFILE.js') would result in something like: /assets/js/appNOFILE.js

Enjoy and let me know how this worked out for you!

Adam Patterson

Adam Patterson

User Interface Designer & Developer with a background in UX. I have spent 5 years as a professionally certified bicycle mechanic and ride year-round.

I am a husband and father of two, I enjoy photography, music, movies, coffee, and good food.

You can find me on Twitter, Instagram, and YouTube!