laravel-mix: Hot reloading not working with laravel/sail [laravel 8]
- Laravel Mix Version: 5.0.9
- Node Version (
node -v): v15.5.0 - NPM Version (
npm -v): 7.3.0 - OS: Windows with Ubuntu 20.04 WSL2
Description:
Hot reloading is not working using laravel/sail.
Steps To Reproduce:
I have tried with sail npm run watch sail npm run hot and nothing seems to work.
Also when I run npm run hot it output this:
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from http://localhost:8080/
ℹ 「wds」: Content not from webpack is served from /var/www/html/public
ℹ 「wds」: 404s will fallback to /index.html
but clicking on http://localhost:8080/ actually opens http://localhost:14252/ which is so weird.
I also tried to add EXPOSE 8080 to the Dockerfile and 8080:8080 to the docker-compose.yml then I rebuilt the image and but still not working and I can’t see any side effect.
Any blade template I made changes on and save it, there is no autoreload on any browser. I have to activelly reload the page to check every change I made.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 15
- Comments: 31 (3 by maintainers)
Hi @moracabanas, I have gotten one step closer to getting this working by:
8080:8080to the dockerdocker-compose.ymlas you mentioned (EXPOSE 8080isn’t required)webpack.mix.js:Now when I run
sail npm run hotI can see that it picks up changes as I make them, and my javascript is now loading the first time in the browser. But currently my browser isn’t picking up and replacing the new ‘hot’ javascript parts.I will report back if I figure out how to solve this next issue.
Edit:
sail npm run watchis a work around for me at the moment which works okay. Yet to figure out how to get HMR working though.What finally, simply worked for me was the following:
8080port binding todocker-compose.yml:devServersetting towebpack.config.js:Note that the
hmrOptionsstuff inwebpack.mix.jsisn’t necessary, because it already defaults to usinglocalhostand8080.Update! I read the Laravel Mix code a bit better… It looks like the Webpack Config options can override the options set by
hmrOptions… Which means we can simply do this:webpack.mix.js(or you can replacelocalhostby something else if you have a custom domain set up in your Hosts file; but it doesn’t really matter andlocalhostshould probably always work)webpack.config.js(or put this in thewebpackConfig()function which might be the default for Mix 5.x) (you can also putlaravel.testinstead of0.0.0.0this will also work)Those 2 combined, along with the 8080 port binding in
docker-compose.ymlis now happily working for me!Do keep in mind that you just need to visit the normal URL without :8080 appended. I didn’t know this at first.
Here’s what works on mine and what I found out about the difference between hmrOptions on mix.options and devServer on mix.webpackConfig.
My environment is: Laravel v8.34.0 laravel-mix v6.0.6 npm: v7.7.6 node: v15.14.0
docker-compose.yml
webpack.mix.js
Accessing http://laravel.test:8085 would result in replacing
Looks like the devServer configuration is for configuring the container side on where to expect the hot files while the hmrOptions is what will mix use on the html side.
My setup is exactly the same as @moracabanas, except that I am using Laravel Mix 6.0.6. I am also running Laravel 8 on Sail with Node 15.5.0 and NPM 7.3.0. And I am also running a Ubuntu 20.04 WSL2 backend op Windows 10.
I finally got this to work (more or less) after tinkering around a lot.
I don’t get any output regarding HMR when I run
sail npm run hot. But perhaps that is not needed (anymore)?What I do see is that webpack picks up my changes because I see a fresh
Compiled successfully...message when I edit a Vue file.Initially I couldn’t get anything to load when visiting
http://localhost:8080. After adding a port binding for 8080 intodocker-compose.ymland restarting the containers I could theoretically connect to port 8080 but I wasn’t able to access it from my local machine.I also tried adding the
devServercode towebpackConfig(), but that didn’t fully work for me. I believe it has to do with the fact that Laravel Mix expectshmrOptionsto be set because it will do some things based on that, like create thehotfile (it will also automatically set thedevServeroptions behind the scenes if I understand the source correctly).So I added the following code into
mix.options()inwebpack.mix.js:laravel.testis the service name indocker-compose.yml. It also seemed to work if I just put0.0.0.0as the host there, but then0.0.0.0will be put into thehotfile and will be used as the JSsrcin the HTML, which I cannot access.By doing the above and after running
sail npm run hotI could then visithttp://localhost:8080but it would only return the following:Cannot GET /However… If I requesthttp://localhost:8080/js/app.jsI do get a response with compiled JS back.After that, I found out that I can just visit
http://localhost(without port 8080) and if the filehotexists in the public directory (which gets added and containshttp://laravel.test:8080) then I can visit the site as usual and I will seehttp://laravel.test:8080/js/app.jsbeing requested (because of thehotfile and themix()function generating the URL to the JS asset).So I added
laravel.testto my Hosts file (resolve to127.0.0.1) and then I reloaded the page and I finally saw this message in my JS console:[webpack-dev-server] Hot Module Replacement enabled.And indeed, after changing something in a Vue template, the change is reflected instantly in the browser!
Hopefully this can help you out too?
It looks like it is currently not possible to easily change the URL to something else besides
laravel.testbecause Laravel Mix seems to use thehostandportvalues fromhmrOptionsto (1) set the values for webpack-dev-server but also (2) create thehotfile which will be used to create a link to the “HMR assets” when themix()function is called. I think this should probably be configurable.PS: if you edit the
hotfile manually and remove thehttporhttpsfrom the URL, then themix()function will fallback tohttp://localhost:8080instead. Found this out by reading the ´mix()´ source code…Hello,
for everybody still having problems with the solution above (for a reason it didn’t work for me). In my case I am using inertia.js, which seems to cause problems when not running the
sail npm run watch-pollcommand. Either hot, nor watch were picking the changes done in the .vue files.For me watch-poll and browserSync did the trick for 100% hot reload experience, by calling
localhost:3000. For more information refer to this https://laravel-mix.com/docs/6.0/browsersync and this thread.here my webpack.mix.js
and my docker compose:
It is very important that you use Laravel’s global
mixfunction. This will load hashed/versioned assets on production, and when running HMR in development it will pull in the correct JS instead. So try this:<script src="{{ mix('/js/app.js') }}"></script>This is referenced (for production purposes) here: https://laravel.com/docs/8.x/mix#versioning-and-cache-busting
Does that work for you?
I got lost as well. After setting up everything as @synio-wesley described above, I can see that changes are detected:
I can see the newest version of js file under
http://localhost:8080/js/app.jsbut when I go tolocalhost:80there is still old version of app.js. Also, inpublic/js/app.jsthere is an old version of compiled file. I need to runnpm run watchto refreshpublic/js/app.js.Maybe this has something to do with the way I embade js script in a blade template:
<script src="/js/app.js"></script>I’ve been pulling my hairs out for hours trying to figure out where webpack is puts this app.js file. It must be somewhere if it’s available throught
http://localhost:8080/js/app.js, right?Any help would be greatly appreciate 🙏
webpack.mix.js
With laravel-mix 6.0.16 running Windows WSL2 with Ubuntu and sail @alexpcoleman solution worked.
I did have to expose 8080 in docker-compose.yml.
I didn’t need to specify the port in devServer config as 8080 seems to be the default.
@synio-wesley comment worked for me.
In case anyone else got the
server.sockWrite is not a functionerror, here’s a modified version of the blade reload trick:The last part to get this setup for me so it simply runs with
sail upwas to run command
sail artisan sail:publishthen todocker/8.0/supervisord.confaddeveryone in this thread thank you for your help
@cthom-dev try this:
Btw, thanks @synio-wesley so much! The use of
chokidaris more than what I had expected, combining with @cthom-dev solution, they all work perfectly!But HMR does work for you? (For example for Vue files and/or for CSS changes?) And you also set up the 8080 port binding in Docker?
It does look very similar to what I have here. The only difference is that I import the webpackConfig from a separate file, but I don’t think that this is an issue:
webpack.mix.js
webpack.config.js
There’s a few extra rules in there, but they are just for my specific project (postCss, vue-i18n)
Can you tell me what OS and Laravel versions you are running? And/or could you perhaps share the test project with me? I’m happy to take a look to see if I can find out why it’s behaving differently.
PS: In case you are only working with CSS and Blade files (not Vue or anything) you could probably also use something like BrowserSync instead
The solution in @jameshulse comment solved the problem for me. But when running
sail npm run hotthe command takes a lot of time compared to running it outside sail