Chapters
-
Course Code
Subscribe to download the code!
Subscribe to download the code!
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
HMR: See Changes without Reloading
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeIf you use Webpack's dev-server
, then as soon as it detects a change, our page automatically reloads. Cool... but not cool enough! Find your terminal, hit Control + C to stop Encore, then re-run the dev server with a --hot
option.
Tip
If you're using Webpack Encore 1.0 or higher, you do not need to pass the --hot
flag: it's already, automatically, enabled.
yarn dev-server --hot
That stands for hot module replacement. Once that finishes... I'll move over and reload the page one time just to be safe.
Let's do the same trick: add two exclamation points, then quick! Go back to the browser! Woh! It's there... but I didn't even see it reload! And no matter how fast you are, you'll see the update but you'll never see a page refresh: it's just not happening anymore! How cool is that? Webpack is able to dynamically update the JavaScript without reloading. It even keeps any Vue data the same.
This hot module replacement thing doesn't work with all JavaScript, but it does work well with Vue and React.
Disabling CSS Extraction
But... there's one tiny problem. Don't worry it's not a big deal. Back in our editor, at the bottom, let's make a CSS change: I'm pretty sure a designer just told me that the hover background should be pink.
This time, back on the browser, hmm: the style did not update. But if we refresh, it is there. HMR isn't working for styles.
This is easy to fix by disabling a feature in Encore. Let me show you. Open up webpack.config.js
and go all the way to the bottom so we can use an if
statement. Here, say if not Encore.isProduction()
- a nice flag to see if we're building our assets for production or not - then Encore.disableCssExtraction()
.
Show Lines
|
// ... lines 1 - 91 |
if (!Encore.isProduction()) { | |
Encore.disableCssExtraction(); | |
} | |
Show Lines
|
// ... lines 95 - 97 |
CSS extraction means that any CSS that Webpack finds should be extracted into an external CSS file. That's why a products.css
file is being output. When you disable CSS extraction, it tells Webpack not to do this anymore. Instead, it embeds the CSS into the JavaScript. Then, when the JavaScript loads, it adds the CSS as style
tags on the page.
I'll explain that a bit more in a minute... but let's see how our page changes first. Because we updated our Webpack config, at your terminal, stop Encore and restart it:
yarn dev-server --hot
Now, refresh the page. Did you see that? It looks the same, but it was unstyled for just a second. If you view the HTML source, there are no CSS link tags anymore. The CSS is being added by our JavaScript files. And because it takes a moment for those to load, our page looks ugly for an instant.
Two important things about this. First, disabling CSS extraction should only ever be done in dev mode: you always want real CSS files on production. And second, the only reason we're going to all the trouble of disabling CSS extraction at all, is because hot module replacement only works when it's disabled. Hopefully, someday, that won't be the case... and we won't need to do this.
The end result is pretty sweet though. Our hover links are still pink but now let's change them to green. And... yes! You could see it change from pink to green almost instantly. If we remove the extra background entirely... that time it was faster than me!
I'm going to do the rest of the tutorial using the dev-server with hot module replacement because I love it! But it did require some work - like using http://
or getting the ssl certificate setup and disabling CSS extraction.
Your situation may require even more work. If it does, consider using yarn watch
instead. The dev-server
is supposed to make your life easier. If it doesn't leave it behind.
Next, let's really start organizing our app - and making it more realistic - by splitting our code into several new components.
8 Comments
Hey Edin,
Thank you for sharing these tips with others! Yeah, HMR is a cool thing... though might cause some problems, so use it at your own risk :)
Cheers!
If you run an external development server with a local domain and webpack-encore keeps outputting "http://localhost:8080
" in your header.
Try this:
yarn dev-server --host 0.0.0.0 --hot --disable-host-check --public 'http://[replace-with-your-domain]:8080'
Also works with yarn inside a docker container, but you must expose the container port (-p 8080:8080
) and open the firewall.
Hey Pablo,
Thanks for this tip! Yeah, using Symfony built-in web server may be simpler, but for more complex setups you need to do more work.
Cheers!
Hi there!
You wrote: If you use Webpack's dev-server, then as soon as it detects a change, our page automatically reloads. Cool... but not cool enough
But at my webpack configuration it doesn't work. I run yarn watch (yarn dev-server doesn't generate build files).
When I modify a .vue file, I have to hit the browser because it doesn't automatically reload the webpage.
I added these lines inside my Webpack config file but that doesn't work either:
Encore.configureWatchOptions(function(watchOptions) {
// enable polling and check for changes every 250ms
// polling is useful when running Encore inside a Virtual Machine
watchOptions.poll = 250;
});
What's wrong? 🤔
Hey @Abelardo!
Ok, there are two similar, but not-identical "modes" for Webpack:
A) "watch" mode - this is what you get with yarn watch
. This generates physical files into your public/build
directory and it automatically rebuilds those files whenever you change one of then. But it doesn't automatically update what you see in the browser: you need to refresh so the browser downloads the new files.
B) "dev server" mode - this is what you get with yarn dev-server
. THIS one, if HMR is enabled and can be leveraged by the JS you're writing (which in Vue, it should work) is the one where your browser automatically updates without refreshing. But, the dev-server
is a bit strange. As you noticed, it does not generate any build files. That is expected. Instead, Symfony will output your script/link tags to point to something like https://localhost:8080/build/app.js
and that localhost:8080
(or whatever the address is, I can't remember the default) is actually a mini "web server" that is run by dev-server
that returns your assets. So, no physically files, but your files WILL be downloaded. So if you want HMR, use the "dev server" mode, but don't expect to see any physical files ;).
Cheers!
Significant changes since webpack-encore 1.0.0 have happened.
* https, is now defined within webpack.config.js
* New in version 1.0.0:Before Encore 1.0, you needed to pass a --hot flag at the command line to enable HMR. You also needed to disable CSS extraction to enable HMR for CSS. That is no longer needed.
see: https://symfony.com/doc/cur...
''' package.json versioning.
"devDependencies": {
"@symfony/stimulus-bridge": "^2.0.0",
"@symfony/webpack-encore": "^1.0.0",
"@vue/compiler-sfc": "^3.0.5",
"core-js": "^3.0.0",
"regenerator-runtime": "^0.13.2",
"sass": "^1.32.7",
"sass-loader": "^11.0.0",
"stimulus": "^2.0.0",
"vue": "^3.0.2",
"vue-loader": "^16.1.0",
"webpack-notifier": "^1.6.0"
},
Hey @Lloyd!
Ah yes! Thanks for mentioning those! I was aware (I wrote those changes!) but I didn’t think of how they would impact this spot if you’re using the latest version. We’ll add a note to help others :).
Cheers!
"Houston: no signs of life"
Start the conversation!
What JavaScript libraries does this tutorial use?
// package.json
{
"devDependencies": {
"@symfony/webpack-encore": "^0.30.0", // 0.30.2
"axios": "^0.19.2", // 0.19.2
"bootstrap": "^4.4.1", // 4.5.0
"core-js": "^3.0.0", // 3.6.5
"eslint": "^6.7.2", // 6.8.0
"eslint-config-airbnb-base": "^14.0.0", // 14.1.0
"eslint-plugin-import": "^2.19.1", // 2.20.2
"eslint-plugin-vue": "^6.0.1", // 6.2.2
"regenerator-runtime": "^0.13.2", // 0.13.5
"sass": "^1.29.0", // 1.29.0
"sass-loader": "^8.0.0", // 8.0.2
"vue": "^2.6.11", // 2.6.11
"vue-loader": "^15.9.1", // 15.9.2
"vue-template-compiler": "^2.6.11", // 2.6.11
"webpack-notifier": "^1.6.0" // 1.8.0
}
}
This HMR stuff is great, except when it's not :)
To elaborate: I had a lot of sass warnings when compiling assets like:
These warnings were also visible on the website in a full screen modal. Only clicking on a X button top right made it go away.
Luckily you can suppress these sass warnings by adding some options to the sassLoader in webpack.config.js like this:
Just for full info: I did update everything before starting this course with composer update and also some packages in package.json (but that should not be related to the sass warnings)