Webpack + BrowserSync + PHP

Published Mar 8, 2017

Ok, look, I’m behind the curve when it comes to Webpack. I’ve heard for a while that it’s a great tool, it brings a lot of benefits to your workflow and it’s not (that) difficult to configure.

The other dev at work has finally made the jump to ES6 and so it opened up a bunch of new ideas to us. Not that Webpack requires ES6 or anything, but it does bring a lot of nice syntactic sugar that we’re able to make use of.

Now that the stars have aligned I finally took the plunge in converting our base template from Gulp over to Webpack. We don’t write a lot of crazy front end code at work, our sites are mostly static and are generated by PHP, so we have a fairly specific use case.

Writing pure JS is nice, if you’re able to do that, but I’m not able to do that, and so while I could fairly quickly get Webpack compiling my assets, I ended up having a lot of trouble getting some sort of live refreshing development server going. It seemed to be that I could either have Webpack live refreshing with webpack-dev-server or I could use BrowserSync to live update changes to my PHP files, by proxying a local server I have set up using MAMP, but it seemed like I could never do both - I couldn’t have the best of both worlds.

It took me much googling and tinkering to come up with something that works, so I thought I’d share it here in the hopes that it can help someone else as well. I’d also like to preface this by saying that I’m new to Webpack, so this may not necessarily be the best option - if you have any suggestions feel free to email me.

This is the config that I’ve come up with, essentially BrowserSync is proxying the Webpack Dev Server and I have a condition that checks if PHP files were modified, which then triggers a browser reload while still enabling hot reloading of CSS and JS.

Another point to note is that this code is using [email protected], since I often found it hard to find up to date examples for something like the below.

const BrowserSyncPlugin = require('browser-sync-webpack-plugin');

module.exports = {
    entry: './js/main.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/js/',
        publicPath: '/js/'
    },
    module: {
        loaders: [
            {
                test: /\.less$/,
                use: [
                    {
                        loader: "style-loader"
                    },
                    {
                        loader: "css-loader",
                        options: {
                            sourceMap: true
                        }
                    },
                    {
                        loader: "less-loader",
                        options: {
                            sourceMap: true
                        }
                    }
                ]
            },
            {
                test: /\.(png|gif|jpg|svg)$/,
                loader: "url-loader"
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    presets: ['es2015']
                }
            }
        ]
    },
    plugins: [
        new BrowserSyncPlugin(
        {
            proxy: 'http://localhost:8080',
            files: [
                {
                    match: [
                        '**/*.php'
                    ],
                    fn: function(event, file) {
                        if (event === "change") {
                            const bs = require('browser-sync').get('bs-webpack-plugin');
                            bs.reload();
                        }
                    }
                }
            ]
        },
        {
            reload: false
        })
    ],
    devServer: {
        proxy: {
            '/': {
                target: {
                    host: "project-url",
                    protocol: "http:",
                    port: 8888
                },
                changeOrigin: true,
                secure: false
            }
        }
    }
}

Take note of the plugin and devServer sections. The BrowserSyncPlugin is proxying the local Webpack Dev Server, but is watching for PHP file changes and will trigger a reload when it finds one. The devServer options are setting the Webpack Dev Server to proxy the local URL provided by MAMP. In this instance it’s browseable at http://project-url:8888 on my local machine.

This seems to be working well enough at the moment, I’ll update this if I run into any pain points.

Hopefully it helps you in the future.