node -v
): 8.2.1npm -v
): 5.3.0When using browserSync, css changes are injected however the page is also reloaded due to the fact that the JS bundle is re-emitted even when the only file that changed was a sass file.
webpack.mix.js:
.js('resources/assets/js/main.js', 'public/assets/js/bundle.js')
.extract(['jquery', 'babel-polyfill'])
.autoload({
jquery: ['$', 'jQuery', 'window.jQuery']
})
.sass('resources/assets/sass/style.scss', 'public/assets/css')
.disableNotifications()
.options({
processCssUrls: false
})
.sourceMaps()
.browserSync({
proxy: process.env.APP_URL,
files: [
'app/**/*.php',
'resources/views/**/*.php',
'public/assets/js/**/*.js',
'public/assets/css/**/*.css'
]
})
Run npm run watch
, site is served at localhost:3000, save a sass file and watch the browser refresh rather than just inject the changes.
My setup is similar to yours, save for defining exactly which .css and .js file to 'watch' for — see the first two entries in the files: []
array:
mix.autoload({jquery: ['$', 'window.jQuery', 'jQuery']})
.js('_js/app.js', 'public/lib/js')
.sass('_scss/app.scss', 'public/lib/css')
.options({
processCssUrls: false
})
.sourceMaps()
.browserSync({
proxy: 'starter.dev',
files: [
'public/lib/css/app.css', // Generated .css file
'public/lib/js/app.js', // Generated .js file
'public/**/*.+(html|php)', // Generic .html and/or .php files [no specific platform]
'laravel/resources/views/**/*.php', // Laravel-specific view files
'craft/templates/**/*.+(html|twig)' // Craft-specific templates, as html and/or twig
]
});
Perhaps that has something to do with it?
I tried this, and it did not work for me:
.browserSync({
proxy: process.env.APP_URL,
files: [
'public/assets/css/**/*.css',
'public/assets/js/bundle.js',
'app/**/*.php',
'resources/views/**/*.php',
]
})
However it did uncover another quirk: when I save the sass file the first time, the bundle.js
file is emitted, then when I save the same file again the vendor.js
file is emitted.
Each is alternating being emitted on every save. I am guessing there might be a race condition here? Not sure. FYI on the times that only the vendor.js
is emitted the page does not refresh just as it should using the bundle.js
specific rule I just posted.
Does it happen if you roll-back to another version? I happen to be running 1.06 at the moment…
Sass compilation does emit only the necessary files and works with BrowserSync when I lock my version down to 1.0.6:
I guess now the question is what changed that prevents this from working like in the older version...
OK, cool … well, _not cool_, but that's one thing ruled out.
Yea, I am going to nuke my install and retry with the tagged version until I hit the one that doesn't work, will report back with my findings :)
So, after doing some installs, looks like the regression was added in version 1.2.0.
I did not dig deeper past the official tagged releases, but 1.1.0 did not emit the js bundle every time you compiled styles however 1.2.0 does just like the latest version.
With Mix 1.4.2 if I run npm run watch
everything works properly with BrowserSync. No page reloads. Here's my mix file:
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.sourceMaps()
.browserSync({
proxy: 'project.dev',
files: [
'public/css/*.css',
'public/js/*.js'
]
});
However with npm run hot
no SASS changes are detected nor injected. Not sure if it's related to this, but thought I'd mention it anyway. https://github.com/JeffreyWay/laravel-mix/issues/1057
I'm seeing this issue with mix 1.4.2 when using npm run watch
mix.js('resources/assets/js/app.js', 'public/js');
mix.sass('resources/assets/sass/app.scss', 'public/css');
mix.browserSync({
files: [
'**/*.js',
'**/*.css',
'**/*.php'
],
injectChanges: true,
logSnippet: true,
proxy: false,
notify: {
styles: {
top: 'auto',
right: 'auto',
left: '0',
bottom: '100px',
opacity: '0.5',
}
}
});
Looks like every other time I save a change in app.scss
, app.js
gets rebuilt which triggers a page reload.
Hello, I also have this issue with mix 1.4.2
const mix = require('laravel-mix');
const path = require('path');
const WEBSITE_URL = "http://test.dev.localtest.me/";
mix
.setPublicPath(path.normalize("public/dist"))
.setResourceRoot("/dist/")
.js('assets/scripts/main.js', 'scripts')
.sass('assets/styles/main.scss', 'styles')
.version();
if (!mix.inProduction()) {
mix
.browserSync({
proxy: WEBSITE_URL,
files: [
'craft/plugins/**/*.php',
'craft/translations/**/*.php',
'craft/templates/**/*.twig',
'public/dist/scripts/**/*.js',
'public/dist/styles/**/*.css'
]
});
}
The main.js file is compiled when the main.scss file is changed, so it injects the css and reload the page instead of only injecting the css.
Thanks,
Using 1.4.2 as well. Just found out, the JS doesn't get recompiled after CSS changes when you don't use .extract()
.
Confirming problem with CSS (SASS) page reloading when using extract() for JS.
I am also getting this problem where i make 1 change in a scss file and the page gets reloaded.
If i set browsersync to watch just the public/css/flytedesk.css
file, then it works, but as soon as I start watching public/js/*.js
it will reload the page every time.
I am using laravel-mix 1.4.2
Here is the output from browsersync while watching the public/js/*.js
directory:
WAIT Compiling... 6:06:03 PM
95% emitting[Browsersync] Reloading Browsers...
[Browsersync] File event [change] : public/css/flytedesk.css
DONE Compiled successfully in 1658ms 6:06:05 PM
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers...
[Browsersync] Reloading Browsers...
Per my last comment, I have also noticed that compilation is pretty slow for compiling scss files relative to what I feel like it used to be when i was using gulp. I suspect it may have something to do with this bug.
I have a lot of files I copy like bootstrap.min.js
among some other jquery plugins. I can see after I change 1 line in .scss file, weather or not I am watching them with browser sync, all those jquery plugins get updated timestamps, including my main app.js file. BrowserSync then thinks js has changed even though it has not.
I can confirm this is not BrowserSync related as well, I tried disabling BrowserSync and the timestamps on a bunch of my JS files get updated after changing a .scss file.
The same with Mix ^1.4.5
Also, if Mix builds all my assets everytime I change something, it's much slower than if it will build ONE changed asset.
I have same issues.
Same issue. 1.4.5
Same issue in version 1.5.0
Could it be that the reload is intended, because Mix checks for .vue
component files, which could contain CSS styles that it tries to extract?
If I use
.standaloneSass('assets/sass/styles.scss', 'build/css'),
instead of .sass()
, then it works fine for me. I guess if you don’t use CSS styles in your Vue components or if you don’t use Vue at all, then this might be the easiest solution. And it should be faster as well.
The only problem with this is that you do not get the benefits of actual webpack processing of your sass files. For example: referencing node_modules
files with ~module/file
and postcss support.
@SethTompkins I use node-sass-magic-importer
in my Gulp build system with node-sass
and it works good! If mix.standaloneSass
supports node-sass
API you can use it with importer
option:
const gulp = require('gulp');
const sass = require('gulp-sass');
const magicImporter = require('node-sass-magic-importer');
gulp.task('sass', function () {
return gulp.src('./**/*.scss')
.pipe(sass({
importer: magicImporter() // ← this
})
.on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
Ah, thanks for the tip @Grawl, that should work as a quick fix for my uses - although the underlying issue remains.
@SethTompkins okay I figured out how standaloneSass
handles Sass options.
include-path
. To enable additional options, we want to modify Laravel Mix to handle them.node-sass
with CLI.pluginOptions
in your mix.standaloneSass(src, dest, pluginOptions)
, and pluginOptions
argument will be available in StandaloneSass
class but there is only includePaths
option support.options
method in laravel-mix/src/StandaloneSass.js
:if(this.pluginOptions.importer) {
sassOptions.push('--importer ' + this.pluginOptions.importer)
}
And then you can add an importer
in your webpack.mix.js
file like this:
mix.standaloneSass('resources/assets/styles/style.sass', 'public/bundles', {
importer: 'node_modules/node-sass-magic-importer/dist/cli.js'
})
There is a PR #1248 that adds node-sass-tilde-importer
but there is so much other code that brokes some tests.
So I decided to create a simpler PR #1282 with only importer
support.
You can install Mix from github:Grawl/laravel-mix#patch-1
until my PR will be merged (or not).
Also, I created an issue #1283
@Grawl It doesn't break anything.
Tests were broken on Windows filesystem so much time ago before I created this PR.
And I fixed them in this PR - https://github.com/JeffreyWay/laravel-mix/pull/1267
@artemsky great! But since your large PRs are on moderation, my PR is already merged to master 😛
Same issue on version 2.0.0. 😭
Changing a .styl
file triggers rebuilding JS files, then causes page reloading.
Same issue here on version 2.1.11. Would be great if this can be fixed soon.
Same issue here using latest version my config is
let mix = require('laravel-mix').mix;
let exec = require('child_process').exec;
let webpack = require('webpack');
const WebpackShellPlugin = require('webpack-shell-plugin');
const filewatcherPlugin = require("filewatcher-webpack-plugin");
const themeInfo = require('./theme.json');
mix.webpackConfig({
plugins: [
new WebpackShellPlugin({ onBuildStart: ['echo "Starting"'], onBuildEnd: ['php ../../artisan stylist:publish -q ' + themeInfo.name], dev: false, safe: true}),
new filewatcherPlugin({watchFileRegex: ['views/**/*.php']})
]
});
mix.sass('resources/scss/main.scss', 'assets/css/all.css')
/**
* Concat scripts
*/
mix.scripts([
'node_modules/jquery/dist/jquery.js',
'node_modules/bootstrap/dist/js/bootstrap.js',
'node_modules/datepicker-bootstrap/js/core.js',
'node_modules/datepicker-bootstrap/js/datepicker.js',
'node_modules/slick-carousel/slick/slick.js',
'resources/assets/js/*.js',
'resources/js/*.js'
], 'assets/js/all.js');
/**
* Copy Font directory https://laravel.com/docs/5.4/mix#url-processing
*/
mix.copy(
'node_modules/datepicker-bootstrap/fonts/',
'../../public/fonts/vendor/datepicker-bootstrap'
);
mix.browserSync({
host: 'localhost',
port: 3000,
proxy: 'http://dohlapse.test',
files: [
'../../public/themes/dohlapse/css/all.css',
'../../public/themes/dohlapse/js/all.js'
],
reload: false,
open: false
});
if using the standaloneSass option I do not get any reloads but no watching as well
I spent two days and couldn't get browserSync or "npm hot" to work as expected. I get a page reload instead of reload one file. I used different versions 1.1.1 -> 2.1.11.
test.blade.php
test blade
<script id="__bs_script__">//<![CDATA[
document.write("<script async src='http://HOST:3000/browser-sync/browser-sync-client.js?v=2.18.12'><\/script>".replace("HOST", location.hostname));
//]]>
</script>
<script src="{{ mix('/js/test.js') }}"></script>
test.js
console.log(123);
webpack.erp.mix.js
const mix = require('laravel-mix');
var assetsDir = 'app/Modules/Erp/Resources/Assets/';
mix.js(assetsDir + 'js/test.js', 'js')
.setPublicPath('public/erp')
mix.browserSync({
proxy: 'erp.test',
open: false,
files: [
'public/erp/js/test.js',
],
reload: false
});
Result in terminal
DONE Compiled successfully in 83ms
/js/test.js 2.61 kB 0 [emitted] /js/test
[Browsersync] Reloading Browsers...
and reload page in browser
Is there some possible workaround? Development is really troublesome
@karneaud the only workaround is to use mix.standaloneSass
or just move styles build process out of Webpack
@Grawl I was trying to use standaloneSass but it doesn't seem to watch or trigger compile when editing scss files...what's the difference really?
Moving the styles build process out of webpack seems so tedious. I seem to be spending more time developing my tools than my project at this point.....
Using the standaloneSass I'm now getting
[Browsersync] File event [change] : ../../public/themes/dohlapse/css/all.css
[Browsersync] File event [change] : ../../public/themes/dohlapse/css/all.css
[Browsersync] Reloading Browsers... (buffered 5 events)
Compilation Started after change of - views/modules/brokerquotes/public/requests/web/partials/form.blade.php
Compilation ended for change of - views/modules/brokerquotes/public/requests/web/partials/form.blade.php
Compilation Started after change of - views/modules/brokerquotes/public/requests/web/partials/form.blade.php
Compilation ended for change of - views/modules/brokerquotes/public/requests/web/partials/form.blade.php
95% emittingfs.js:1103
return binding.unlink(pathModule._makeLong(path));
^
Error: ETXTBSY: text file is busy, unlink '/home/vagrant/Code/dohlapse/Themes/Dohlapse/mix.js'
at Error (native)
at Object.fs.unlinkSync (fs.js:1103:18)
at File.delete (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/laravel-mix/src/File.js:49:16)
at Compiler.compiler.plugin.stats (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/laravel-mix/src/webpackPlugins/MockEntryPlugin.js:23:25)
at Compiler.applyPlugins (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/node_modules/tapable/lib/Tapable.js:61:14)
at emitRecords.err (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/lib/Compiler.js:264:11)
at Compiler.emitRecords (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/lib/Compiler.js:371:38)
at emitAssets.err (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/lib/Compiler.js:258:10)
at applyPluginsAsyncSeries1.err (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/lib/Compiler.js:364:12)
at next (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/node_modules/tapable/lib/Tapable.js:218:11)
at Compiler.compiler.plugin (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/lib/performance/SizeLimitsPlugin.js:99:4)
at Compiler.applyPluginsAsyncSeries1 (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/node_modules/tapable/lib/Tapable.js:222:13)
at Compiler.afterEmit (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/lib/Compiler.js:361:9)
at require.forEach.err (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/lib/Compiler.js:350:15)
at /home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/node_modules/async/dist/async.js:473:16
at iteratorCallback (/home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/node_modules/async/dist/async.js:1050:13)
at /home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/webpack/node_modules/async/dist/async.js:958:16
at /home/vagrant/Code/dohlapse/Themes/Dohlapse/node_modules/graceful-fs/graceful-fs.js:43:10
at FSReqWrap.oncomplete (fs.js:123:15)
I just moved from injecting CSS using Browsersync to Chrome Dev Tools. I just added folder with assets into Sources › Filesystem › + Add folder to workspace. Now, Browsersync reload whole page on JS or template updates and injects CSS when file is updated.
Not sure if it's helpful, but this _is_ working for me as expected, using Mix 2.1.11, and the following config:
let mix = require('laravel-mix')
require('laravel-mix-purgecss')
const config = {
localUrl: 'project-url.test',
templates: [
// ========================================================================
// You probably need only one of the below lines, depending on which
// platform this project is being built upon.
// ========================================================================
'public/**/*.+(html|php)', // Generic .html and/or .php files [no specific platform]
'laravel/resources/views/**/*.php', // Laravel-specific view files
'craft/templates/**/*.+(html|twig)' // Craft-specific templates, as html and/or twig
]
}
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for your application, as well as bundling up your JS files.
|
*/
mix
.autoload({
jquery: ['$', 'window.jQuery', 'jQuery']
})
.options({
autoprefixer: {options: {grid: true}},
processCssUrls: false
})
.js('_js/app.js', 'public/lib/js')
.sass('_scss/app.scss', 'public/lib/css')
.sass('_scss/print.scss', 'public/lib/css')
.purgeCss({globs: config.templates})
.sourceMaps()
.webpackConfig({devtool: 'source-map'})
.browserSync({
proxy: config.localUrl,
files: config.templates.concat([
'public/lib/css/app.css', // Generated app.css file
'public/lib/css/print.css', // Generated print.css file
'public/lib/js/app.js', // Generated .js file
])
})
@marcamos what platform OS are you developing on? are you using VueJs in your development?
@karneaud macOS, whichever version is the most recent and, yes, we’re using VueJS.
Sorry me. I hurried. I didn't know that Browsersync doesn't support hot reloading for JavaScript. Browsersync always reloads the page if the file JS has been modified.
Separate running of SASS and JS works as it should, but not together.
I noticed that WebPack Watch compiles all the files every time.
I found this question, which you have to follow:
https://stackoverflow.com/questions/49553082/webpack-watch-compiles-every-file
https://github.com/webpack/webpack/issues/6901
I found out, that what causes the reload for me is mix.copy()
, which I use to copy a JS file from node_modules
to public
. If I don't use it, the CSS injection works as intended and without a reload. I know, that BrowserSync reloads upon changed JS. Could it be, that mix.copy()
is triggered upon every save?
it doesn't work for me i deleted this line -> .extract(['jquery', 'babel-polyfill'])
and worked.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Anyone still having this issue?
I'm using Laravel Mix 4.0.7 & BrowserSync 2.26.3.
When I leave in the mix.scripts() it's refreshing the browser on every save even scss
Anyone still having this issue?
I'm using Laravel Mix 4.0.7 & BrowserSync 2.26.3.
When I leave in the mix.scripts() it's refreshing the browser on every save even scss
Same thing on mix.babel()
Anyone still having this issue?
I'm using Laravel Mix 4.0.7 & BrowserSync 2.26.3.
When I leave in the mix.scripts() it's refreshing the browser on every save even scss
Using Laravel Mix 4.0.14 and I'm still experiencing this problem, when using min.scripts()
. Without min.scripts()
CSS injection is used instead of an entire page reload. To me this is a noticeable slow down in some of my larger projects, but unfortunately I couldn't find a solution yet.
IN 2020 (Laravel 7), config is:
.js("resources/js/app.js", "public/js")
.sass("resources/sass/app.scss", "public/css")
.browserSync({
proxy: 'localhost', // your domain test
port: 32816 // your port
});
I have the same problem using mix.scripts()
and mix.sass()
together. Is there any fix or workaround for this?
@arnoson try this config https://github.com/JeffreyWay/laravel-mix/issues/1053#issuecomment-645395293
It is working with your config, but I have a really simple setup where I don't need all the webpack specific stuff mix.js()
is adding to my js files. Both mix.scripts()
and mix.babel()
cause the full reload. So maye this is a bug/undesired behaviour?
Got is, try update babel package in your package.json, but I think is a bug too
Until this behaviour changes I now just use a different mode for development and production like this:
const mixJs = mix.inProduction() ? mix.scripts : mix.js
mixJs('src/index.js', 'dist')
This still appears to be an issue in Mix 5. To summarise the problem:
Using .js()
to compile your JS works fine, but using .babel()
or .scripts()
or .combine()
instead causes BrowserSync to do a full page reload even if you only changed a CSS file.
@arnoson's idea of forking between them based on inProduction() feels a bit risky to me, as .js()
is fundamentally different to scripts()
in that it compiles separate files into ES6 modules, which in turn will require you to use import
and export
if you ever need the code in one file to access the code in another file. My workaround was to refactor my JS to deliberately use ES6 modules. A good learning experience, though things do feel a bit more complex than necessary when simple concatenation would have done the job fine.
Hi @JeffreyWay ,
I believe this should be reopened since it is still happening with mix v6.0 too.
Anything you change while watching files will regenerate js and css files built using .babel()
, .scripts()
or .combine()
and .styles()
thus causing a full page reload with BrowserSync, even if you did not change those js files at all.
It is really counterproductive when, for example, you have a Vue app built with .js()
, but also some old scripts built with .babel()
. When changing something in the Vue app, it should go through Hot Module Replacement without reloading the page, but since the .js files built with .babel()
are also rebuilt, BrowserSync detects those changes and triggers a reload.
So far, the only workaround I found is to remove .js files built from .babel()
from BrowserSync (using the files option). This way, Vue HMR works, but in exchange of disabling browser reload for any of those babel js files. I could not find a solution to have both Vue HMR and babel js reload.
I finally found a workaround for my case.
I believe the issue is that laravel-mix's CustomTasksPlugin
runs all post-build tasks again for every rebuild. In these tasks is where all files built using .babel()
, .scripts()
, .combine()
, .styles()
and even .copy()
are built again.
Here is a drop in plugin that ensures these tasks only run at the first build. Subsequent watch builds won't rebuild all those files again unless you actually modified one of their files. This fixed all my browserSync reload problems.
mix.webpackConfig({
plugins: [{
apply(compiler) {
// Intercept done hook to modify CustomTasksPlugin tap function
compiler.hooks.done.intercept({
register: (tapInfo) => {
let firstRun = true;
if (tapInfo.name === "CustomTasksPlugin") {
const fn = tapInfo.fn;
tapInfo.fn = (stats, callback, ...args) => {
// Only run tap function (tasks) for first build
if (firstRun) {
fn(stats, callback, ...args);
firstRun = false;
} else {
callback();
}
};
}
return tapInfo;
}
})
}
}],
});
Most helpful comment
Could it be that the reload is intended, because Mix checks for
.vue
component files, which could contain CSS styles that it tries to extract?If I use
instead of
.sass()
, then it works fine for me. I guess if you don’t use CSS styles in your Vue components or if you don’t use Vue at all, then this might be the easiest solution. And it should be faster as well.