Sage 9 browsersync not updating right



I was able to consistently reproduce the issue. Very strange. I think it could be an issue with the bs-html-injector Browsersync plugin. I don’t think it was designed to work with Blade templates — let alone PHP. I will expand on this in a new topic or an issue when I find the time.


That would make sense, as just regular html in the blade templates does not seem to have an issue being injected, its mainly when it is mixed with php / blade directives.

I also wonder if there could be a dependency that has updated since the first release of Sage 9?

When I was working on the first couple of themes based on Sage 9, the page would reload after saving a .blade.php or .php file, and that behavior persists in those projects, but I am not sure what would happen if I deleted my node modules and re-ran yarn, since newer projects behave differently.

Let me know if there’s any more information I can give you, and thanks for the help in trying to diagnose the issue!


I’ve followed all of these and tried solutions on numerous other boards. They all (usually) work for a while and then quit working. I don’t have any other projects using webpack and hot reloading that have this issue. As much as I love using blade in my template and everything that Sage provides, I’m feeling like I can’t do anything but use a different starter template until these issues get addressed by the Roots team.

I’m currently watching my site reload constantly. I have to make a few changes, run yarn build, and then refresh, hoping there’s no error because the build fails without telling my why as its currently set up.


Can you please be more specific?

Starting off by sharing your config, and whatever else you’ve modified to try and fix your problem, would be a good start to solving the issues you’re running into

This should be a simple configuration issue


Ben, here’s the file I’m working with:

const url = require('url');
const webpack = require('webpack');
const BrowserSyncPlugin = require('browsersync-webpack-plugin');

const config = require('./config');

const target = process.env.DEVURL || config.devUrl;

 * We do this to enable injection over SSL.
if (url.parse(target).protocol === 'https:') {

  config.proxyUrl = config.proxyUrl.replace('http:', 'https:');

module.exports = {
  devServer: {
    watchOptions: {
      poll: true,
  output: {
    pathinfo: true,
    publicPath: config.proxyUrl + config.publicPath,
  devtool: '#cheap-module-source-map',
  stats: false,
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
    new BrowserSyncPlugin({
      proxyUrl: config.proxyUrl,
      delay: 1500,

It’s hard to troubleshoot because it’s hard to know what fixes things and what doesn’t. I’ve had sporadic luck by temporarily moving my views folder out of the structure, hard reloading so it stops the the auto reload, and then moving it back in. It works sometimes, other times it just keeps cycling through the page refreshses on-end.

I’ve also dumped my composer files and redone that based on the suggestion here but it didn’t change anything.

FWIW, I had this same issue at a previous job on a different Macbook Pro, but most of our sites were built with Sage 8 so it wasn’t as big of a deal when a site got stuck in a reload loop.

I use Flyhweel’s Local to run it on my machine.

Also, here’s my config file:

  "entry": {
    "main": [
    "customizer": [
  "publicPath": "/wp-content/themes/client-portal",
  "devUrl": "http://yesler-client-portal.local",
  "proxyUrl": "http://localhost:3000",
  "cacheBusting": "[name]_[hash:8]",
  "watch": [


What Node version are you on? (node -v)

Also, is there is anything in the browser console that would be helpful to share? I would recommend enabling “Persist Log” (in the browser console).

I also find adding the following (in helpful for debugging Browsersync related issues:

    new BrowserSyncPlugin({
      proxyUrl: config.proxyUrl,
      delay: 500,
+     advanced: {
+       browserSync: {
+         logLevel: 'debug',
+       },
+     },


I’m on Node v8.11.2.

I’ll add in the advanced portion there and see what happens.


Had it helped? I have got a similar issue (BrowserSync showing a notice (in upper right corner on page) that it updates but styles are not updated), the logLevel: 'debug' makes Browser Sync logging more information when it starts up (yarn start) but not when it recompiles after file change.

The following errors are logged to console when loading the page initially (over BrowserSync proxy):

inject.preload.js:373 GET blob:http://localhost:3000/236def65-7284-45c4-9deb-68885a965399 0 ()
(anonymous) @ inject.preload.js:373
__webpack_require__ @ bootstrap a58e717ca664391e8660:19
splitSelector.splitSelector @ common.js:103
__webpack_require__ @ bootstrap a58e717ca664391e8660:19
exports.textToRegExp @ bootstrap a58e717ca664391e8660:62
(anonymous) @ bootstrap a58e717ca664391e8660:62
(index):217 GET http://localhost:3000/app/themes/test-theme/dist/styles/main.css 404 (Not Found)
jquery-migrate.js?ver=1.4.1:23 JQMIGRATE: Migrate is installed with logging active, version 1.4.1


Alternatively, for a more verbose output you could comment out the stats option in whatever Webpack config you need it for and set stats: 'verbose'.

[Browsersync] Browser Connected: Chrome, version: 67.0.3396.99
[BS] [HTML Injector] Stashing: http://localhost:3000/
[Browsersync] Browser Connected: Chrome, version: 67.0.3396.99

(Changed something in main.scss and saved the file).

WAIT  Compiling...
DONE  Compiled successfully in 1206ms

(E.g. style) lint errors can be provoked and are logged in console and in browser.


I found the reason: wp_enqueue_script for sage/main.js was commented out, which also caused sage/main.css not being updated. This seems to be some kind of dependency bug in the end.

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style('sage/main.css', asset_path('styles/main.css'), false, null);
    //wp_enqueue_script('sage/main.js', asset_path('scripts/main.js'), ['jquery'], null, true);
}, 100);