4

I have a web project with a working Webpack4 config using webpack-dev-server with HMR enabled and started this way via npm script:

cross-env NODE_ENV=development webpack-dev-server --inline --hot

All is OK, HMR works for my js and scss files. Now I'm wondering if it's possible to extend my Webpack config to have a full reload in the browser when I modify a view template file.

It seems for me that webpack-dev-server can't do this on its own, so I think I need some other plugin. After googling a bit this is I've got:

  1. webpack-dev-server + browser-sync-webpack-plugin
  2. rewrite my config to webpack-serve as it seems it can do it
  3. chokidar + webpack-dev-middleware (API for reloading?)

So my question is what is the best way to get HMR + watch given paths and reload browser on file change (blade/twig/php/etc...) with Webpack 4(.17.2) ?

Relevant part of my current config:

devServer: {
  index: '',
  open: true,
  hotOnly: true,
  publicPath: '/build/',
  host: 'mysite.test',
  proxy: {
    '**': {
      target: 'http://mysite.test',
      changeOrigin: true,
      headers: {
        'X-Dev-Server-Proxy': 'http://mysite.test'
      }
    }
  }
}
szegheo
  • 4,175
  • 4
  • 31
  • 35

1 Answers1

12

Answering myself, maybe others can benefit from it. Just to note: I have a Laravel project and I'm using Webpack4 for bundling it instead of its own Laravel Mix solution. My test Laravel site is served by nginx on mysite.test

1) webpack-dev-server + BrowserSync

Works great, BrowserSync has many good features, i like it! The only disadvantage is that it creates another proxy on top of Webpack's devserver. You can try it following these steps:

Install the browser-sync-webpack-plugin as described, then:

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

// Webpack config, plugins section
plugins: [
  new BrowserSyncPlugin({
    host: "mysite.test",
    port: 3000,
    proxy: "mysite.test:8080",
    open: "external",
    files: [
      './resources/views/**/*.blade.php'
    ]
  },{
    // prevent BrowserSync from reloading the page
    // and let Webpack Dev Server take care of this
    reload: false
  })
]

2) webpack-serve

Not on option anymore since webpack-contrib/webpack-serve went deprecated.

3) webpack-dev-server + Chokidar

Finally I started using this. Simple and fast. Chokidar is a file watcher, it's also used by Webpack's devserver internally for watching files. You may already have it in your node_modules but if not, install it with npm or yarn.

Here's my whole devServer config I originally wanted. CSS injection and Javascript changes handled by HMR and when a view file changes, devserver makes the browser reload automatically:

const chokidar = require('chokidar');

// Webpack's devServer config
devServer: {
  before(app, server) {
    chokidar.watch([
      './resources/views/**/*.blade.php'
    ]).on('all', function() {
      server.sockWrite(server.sockets, 'content-changed');
    })
  },
  index: '',
  open: true,
  host: 'mysite.test',
  proxy: {
    '**': {
      target: 'http://mysite.test',
      changeOrigin: true,
      headers: {
        'X-Dev-Server-Proxy': 'http://mysite.test'
      }
    }
  }
}

Tested on Webpack 4.19.1

szegheo
  • 4,175
  • 4
  • 31
  • 35
  • 2
    Thanks for posting your solution. Found it because I'm trying to do the same thing! Off how little info there is out there on this. We can't be the only ones who are mixing backend and frontend in webpack! – tarponjargon Jul 05 '19 at 16:52
  • I am kissing you now.. I have been trying to come up with this for two days full-time. You know that geek feeling you just HAVE to get this straight? OH MY GOD THANK YOU!!!! PS: debouncing the watch function helps performance quite a lot! :) – Mattia Rasulo Apr 12 '21 at 16:58
  • To clarify, this question is about watching arbitrary source files (from what I understand). File changes in built files can be watched with the [watch-content-base option](https://webpack.js.org/configuration/dev-server/#devserverwatchcontentbase). – Kisaragi Hiu Jun 24 '21 at 19:56
  • I've been looking for a solution like this myself. One question. I've been trying to get this to work with Webpack 5 and it doesn't seem to allow it. When I run it I get this error. "TypeError: server.sockWrite is not a function" I'm still looking for a solution for this if anyone knows. – Showcaselfloyd Jul 13 '23 at 14:57
  • 1
    So I actually found a solution to this issue on another site. If you using Webpack 5. Change server.sockWrite(server.sockets, 'content-changed'); to server.sendMessage(server.webSocketServer.clients, 'content-changed'); – Showcaselfloyd Jul 13 '23 at 15:08