Hot Module Replacement (HMR) or Hot Reloading is a technique used to refresh web pages as we make changes to the code of web pages, CSS and JavaScript which completely eliminate the manual page refreshing. The problem with Laravel Sail is, HMR does not work with its default configuration. The default Laravel Sail Docker Compose configuration only exposes the port 80 of the Laravel Docker container. So first of all, we need to expose a new port of the Laravel Docker container for the HMR to communicate with the browser. So when it detects a change in the file system, it can request a page refresh automatically using the newly exposed port.

Open the docker-compose.yml file and add port 3000.

services:
    laravel.test:
    	...
        ports:
            - '${APP_PORT:-80}:80'
            - '3000:3000'

Then open the webpack.mix.js file and add the following code at the end.

mix.browserSync({
    proxy: 'laravel.test',
    port: 3000,
    open: false,
});

If you have been already running Laravel Sail, stop it.

vendor/bin/sail down

Then run it again. Now it will start the Laravel Docker container with port 3000 opened.

vendor/bin/sail up -d

Run npm run watch with Laravel Sail. 

vendor/bin/sail npm run watch

Open the web browser and access the Laravel application with port 3000. Such as http://localhost:3000. Now change a blade view file, CSS or JavaScript file and the changes should be immediately visible without manually refreshing the browser.

If you do need to run the application in a separate port such as port 8080 instead of port 3000, use 3000:8080 in the docker-compose.yml file and port: 8080 in the webpack.mix.js file.