Javascript in Laravel (introducing Webpack)

Bundling with Webpack and Laravel Mix

Pim Hooghiemstra
PLint-sites
5 min readMay 2, 2018

--

Update May 2021

Please note that this post is currently 3 years old. As you know, things move fast in our tech world and event though the principles described in this post are still valid, there might be better ways to achieve the same result; You are free to continue reading, but I recently wrote a post about our current approach.

Additionally, Laravel 8 brings a new starter kit to quickly scaffold the frontend of your next project. It’s called Laravel Jetstream and is definitely worth taking a look. I’ll choose Laravel Jetstream with Inertia scaffolding for my next project.

Therefore, I am removing the code repository that originally came with this post.

Original post

This post is the second part of a greater series on applying Javascript to a Laravel project.

If necessary, you can catch up by reading the overview post where I introduce the problem and the sample code, or you can read about the jQuery way discussed in part 1.

So far we created a sample Laravel project containing a single route. The page shows a typical registration form and I like to add a little Javascript behaviour to the form. In the previous post I talked about the quick and dirty jQuery way and noted this is not a feasible approach in a larger project: with many script tags that need to be in order it quickly becomes unmaintainable.

In this post I’ll introduce Laravel Mix, a wrapper around Webpack. Although introducing a layer of complexity, once you have the module bundler working it makes implementing new features a joyful exercise!

Webpack has become the de facto bundler in recent years. It’s rather tough to get it running from scratch, but using Laravel Mix makes it a breeze!

Laravel Mix is basically a wrapper around webpack that fully configures the bundler for 90% of its users. You only have to define your entry points for either javascript, css or both and you are good to go.

Setting up Laravel Mix

A clean Laravel install comes with Laravel Mix installed. So when you open your webpack.mix.js file (you’ll find in the root of the project) you will see these two rows

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

The app.js file is the entry point for all javascript (more on that one below), and the app.scss file simply loads the bootstrap sass file that is also installed by default. The latter gives you the Bootstrap styling.

Compiling the Javascript and Sass code is very easy. The commands are located in the scripts section of the package.json file. Either run

npm run dev

to run it once or run

npm run watch-poll

to execute the scripts and keep watching for changes.

The output is stored in the public folder, more specifically in the directories public/js and public/css. All we have left to do now is including those scripts in our app.blade.php (see lines 15 and 33 below).

At first sight, this is much cleaner compared to our initial approach where we had script tags all over the place in the <head> section of the document. Now all we have is a single stylesheet that loads all Bootstrap styles (and could be easily extended to also load the home.css file which is included below it).

In addition, a script tag has been added to the bottom of the file.

Both the app.css and the app.js file are loaded using the mix command. Under the hood this uses the generated mix-manifest.json file in the public folder to map the filename css/app.css to the correct file. This becomes very usefull when we apply cache busting enabled by adding mix.version() in the webpack.mix.js configuration (later on in the series we’ll discuss this in more detail).

app.js in detail

Our app.js file looks like this

It simply requires the bootstrap.js file that comes installed by default and loads jQuery, Popper and Bootstrap (the framework) and make them available to our code. This is comparable to the last post because we still use jQuery as we’ll shortly see.

I know this might sound rather weird, loading a bootstrap file to load the Bootstrap framework. However, the bootstrap.js file must be seen as the file in which we import the modules we need in our project. One of these dependencies is the Bootstrap framework.

When the user visits the homepage, the registration.js file is imported. It contains nearly the same code as in the last post: an IIFE that is executed immediately:

Pros and cons of this approach

With this approach we are able to register a single entry point for all our Javascript which makes the code much more maintainable. There are no script tags in the <head> section of the page anymore, which improves the performance.

The bootstrapping code that imports jQuery, Popper and Bootstrap is put away in its own file and imported in app.js making the latter much more readable amd clean.

We keep a clean codebase by only importing the modules we need for each page.

However, this approach also has a downside:

Code splitting is possible, but if we would have 20 pages which each require a couple of modules, all this code is added to the bundle which becomes quite large (in terms of kB to download for the end user). However, Laravel Mix allows us to put all npm modules in a separate vendor bundle which reduces the download size of app.js. This way, the end user only needs to download the new app.js when you add more functionality to the app (at least until you add more modules to the vendor bundle).

Concluding remarks

In this post we have improved the workflow for adding Javascript to a Laravel project by using Laravel Mix and Webpack. This gives us a code base that is much more maintainable. This would become even more clear when extending the sample app to house multiple pages with their own Javascript behaviour.

However, there are still some downsides as the code still uses jQuery to manipulate the DOM and the bundle file may become quite large.

This could be improved by using a Javascript framework. Stay tuned for the next post where we implement the Vue framework in Laravel to further optimize the way we include Javascript in Laravel!

--

--

Pim Hooghiemstra
PLint-sites

Love to build Laravel + Vue applications! Founder of PLint-sites. https://plint-sites.nl