Webpack 4 Fundamentals Webpack 4 Fundamentals

Hot Module Replacement with CSS

Check out a free preview of the full Webpack 4 Fundamentals course:
The "Hot Module Replacement with CSS" Lesson is part of the full, Webpack 4 Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Sean demonstrates how Webpack can patch changes incrementally and apply them to a web document without ever having to reload the browser.

Get Unlimited Access Now

Transcript from the "Hot Module Replacement with CSS" Lesson

[00:00:00]
>> Sean Larkin: Now what's really cool is that by default, if we were to look at this generated code, you're gonna see some special annotations wrapped around this JavaScript module. And the reason why is, is because see it there, loaders are really useful for helping support a unique webpack feature called hot module replacement.

[00:00:25] And I think it's easier to show you, or for you to experience what it is, instead of trying to explain how it works. So to experience it, all I want you to do is jump into your package.json and where you have your dev script. I want you to add another flag at the end that says --hot.

[00:00:48]
>> Sean Larkin: Let me zoom out on that just a little bit.
>> Sean Larkin: And I'm not really going to dive into what hot module replacement is beyond like what it provides you. So if we look now and we restart our build.
>> Sean Larkin: Why don't we take that import that we imported into footer?

[00:01:12] I know why, and let's move this into the entry point.
>> Sean Larkin: Let's see.
>> Sean Larkin: So jump to index and let's add it right here.
>> Sean Larkin: Let's see, that should still work. Yeah, it does, okay. If you wanted to even use import CSS from whatever, it still works. But really that code is just declarative or it creates side effects.

[00:01:53] So let's try and see if we get that feature again. If not, I'll leave it alone, and we can keep going and talk about how we're gonna change this for production mode.
>> Sean Larkin: There you go. Now, did you notice that? So, if you change a property now,
>> Sean Larkin: Instantly, you're seeing changes before your eyes, and we're not reloading the browser.

[00:02:27]
>> Sean Larkin: We do nothing. So this is how module replacement is. Webpack has this capability of being able to patch changes that are made incrementally and apply them without you ever having to reload the browser. It's just super valuable when you have capabilities, like something that has a lot of complex state and refreshing the browser would be a real pain to debug.

[00:02:50] And it's also just a really cool development experience. You can essentially like, as like this I think is really cool for designers to go through and they could get live feedback without having to mess with anything. Now let's also go ahead, now this wouldn't be something that we would wanna do.

[00:03:10] So the CSS that we have now, it's just adding a module and it's blocking the main thread, right? Because you're relying on JavaScript to attach a style tag. And so instead what we would wanna do, is we would wanna extract it out and have it in a separate tag, right?

[00:03:28] So, we can do this by adding the mini CSS extract plug-in. But we're gonna apply it to our, so close others, let's see. We're gonna apply this our production config.
>> Sean Larkin: Now I always forget the order, so I'm just gonna pull it up. And this is kind of the same thing.

[00:03:53] If there's a plugin you want to use, we stress really importantly the ability to have these options documented. But there's two pieces that you're gonna add for this. The first one is going to be the plugin itself, and then we're also gonna add kinda the module rules. And we're gonna leverage that plugin a special loader that extracts these pieces out.

[00:04:18] So, why don't we go ahead and just add that information? So first things first is that we'll go ahead and require that plugin. So const MiniCssExtractPlugin = require, here, I'll hide the window, we don't need it right now.
>> Sean Larkin: Here we go. And then we can just add that plugin in a plugins array, [COUGH] just as we see here.

[00:04:51] Now, these are just options that you can use. But, and they use the same name helpers like you're used to seeing for the output property. But by default, these are all set. So you can just pass a new reference. I think that's really nice. Good defaults are really important.

[00:05:07] So now, we also wanna add the module property.
>> Sean Larkin: So yeah, module and rules. Then in the same way we have to basically create an array of, or like we're defining when we want to apply these capabilities. So I'm pretty comfortable with copy pasta, only appropriate place number two to do it.

[00:05:41] So, we'll just add this inside ofthe rules array, right? Now there's a little difference that's gonna happen now, instead of using style loader, we're actually gonna use this MiniCssExtractPlugin.loader. So it'll be whatever name you give it here, .loader instead of style loader.
>> Sean Larkin: There we go. So why don't we go ahead and actually run our production config and see what happens.

[00:06:08] So yarn prod, or mpm run prod run prod. We get a build.
>> Sean Larkin: And if we look in the feedback, hey, we have now a completely separate CSS file that has been admitted to our dist folder.
>> Sean Larkin: Now, maybe for the ease of seeing what's in your dist, you can, it's always well, let's make one change here and that is in your production.

[00:06:39] Just so you don't get a new hash every time, just go ahead and change this back to bundle. That way this folder doesn't keep piling up. [COUGH] I just like deleting it. You can always get it back, webpack creates it. Yarn prod.
>> Sean Larkin: There you go. Nice and clean.

[00:07:02] So there is the styles that we wrote. In addition to, the CSS is actually put in the right location inside of the HTML.
>> Sean Larkin: So this is really the best practice for how you're trying to load CSS. Now, when we talk about code splitting tomorrow, I'm gonna go over how MiniCssExtractPlugin is really valuable to us.

[00:07:29] We just added this plugin and it's only webpack 4 compatible. But we added it because it has support for lazy loading CSS. I think that's really cool, because it's nothing that any build tools have been able to generate so far for us. And so really makes performance possible, especially in the realms of CSS.

[00:07:51]
>> Sean Larkin: Does anybody have any questions so far about this? We could even, if you wanted to preview it, you could, like an HTTP server. But the behavior will be identical in terms of what will show on the page, yeah?
>> Speaker 2: If you import multiple CSS files, will it inject multiple link tags?

[00:08:10]
>> Sean Larkin: Mm-hm, it will. I don't believe multiple link, well let's find out. I don't believe it's multiple link tags, it will be kind of in the same CSS file.
>> Speaker 2: So it could concatenate it?
>> Sean Larkin: Yep, and you can actually, I think there's even through the CSS loader, you can minify and do other capabilities.

[00:08:29] As long as it's in the loader chain, you can really apply any changes you want. And yeah, let's do that. We want to add another CSS file. We should, it makes sense. Let's just do one for the old button, right? So let's create
>> Sean Larkin: button.css. What's a good button attribute?

[00:08:56]
>> Sean Larkin: Background attachment button image outset. I'm not even sure what a great one is.
>> Speaker 3: Font family fantasy?
>> Sean Larkin: I like it, font family fantasy. Is it just like fantasy? Like that? Cool, ship it, let's run our production build.
>> Speaker 3: Actually I think it's a name value, you don't have to put it in quotes.

[00:09:22]
>> [CROSSTALK]
>> Sean Larkin: Nice, and lowercase?
>> Speaker 3: Yeah.
>> Sean Larkin: See, this is where I rely on you all. [LAUGH] Awesome. So let's take a look, yeah, and it looks like it's just one. So or unless we rebuild and we see multiples. Well, of course, we haven't actually imported this anywhere.

[00:09:44] So we don't see the extra one created. Let's jump to our entry point and actually import it. I always jump ahead of myself. New button from button.css. There we go.
>> Sean Larkin: Uh-oh, what happened?
>> Speaker 3: Button is already declared.
>> Sean Larkin: Thank you very much.
>> Sean Larkin: I love it.
>> Sean Larkin: That wasn't a very friendly error message, though.

[00:10:23] It was, okay. There we go. That's pretty helpful, though, for identifying that. Okay, so let's look at what the output is. So it's still a single. And we have both of our styles there.
>> Sean Larkin: Now what'd be cool in a perfect world is if it optimized it in the right way.

[00:10:44] We're hoping to work with the LinkedIn team, who kind of created this new tool called CSS Blocks. And that optimizing compiler really does things like that. How cool would that be? That seems like a core tenet that would make sense for webpack.
>> Speaker 4: So what's that, you're importing those to the top-level module there.

[00:11:01]
>> Sean Larkin: Mm-hm.
>> Speaker 4: And then it's just gonna be putting those all in the same scope there. So the CSS wouldn't be scoped to the module?
>> Sean Larkin: So that is a caveat to think about. And that's why, when we talk about, let's say, Code splitting CSS, it becomes valuable to then separate those into asynchronous applications.

[00:11:22] So you can, in real time, dynamically force a scope change by applying a new style sheet.
>> Sean Larkin: This is a very vanilla way of doing it, a lot of people will end up using CSS modules to have the scope capabilities. Or they'll use their framework's recommended way that webpack powers behind the scenes.

[00:11:48] But just from its primitive, yeah, exactly, from the simplest use case, that's what it will do.
>> Sean Larkin: So, I'm just gonna check this out really quick. So, if you want to play with the styles or launch the dev server, see how everything looks, feel free to go ahead and do so.

[00:12:06] I'm just gonna create a branch.