This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

Webpack CSS, Preprocessors, and url assets

7:09 JavaScript lesson by

Webpack enables modularity by allowing you to require the styles needed for a particular component. Adding preprocessors is a breeze and it simplifies the deployment of your css assets.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

Webpack enables modularity by allowing you to require the styles needed for a particular component. Adding preprocessors is a breeze and it simplifies the deployment of your css assets.

Avatar
Zachary Klein

Any reason why webpack uses the "bang" symbol to pass through multiple loaders instead of a pipe (like in standard Unix)?

Avatar
Kent C.

Not sure. But you can use the array syntax instead (when doing this, you use loaders rather than loader): loaders: ['style', 'css']

In reply to Zachary Klein
Avatar
Anton Emery

Will this same setup work when using webpack -p to process all the code prior deploying the app?

Avatar
ckot

Would the same technique you used for bundling index.css by requiring it in index.js (removing the need for it's link tag) work for the link tag for the bootstrap.css as well? I'm guessing it's a little more involved as bootstrap is in node_modules, which is excluded in webpack.config.js

Avatar
Kent C.

Actually, you could/should definitely do the same for those assets as well:

require('bootstrap/dist/css/bootstrap.css')
In reply to ckot

With Webpack's loaders, you can actually load more than just JavaScript. You can load a lot of different assets for your application. One of those assets that we're going to load is CSS. Right now, the way that we're getting CSS into our application is through the link attribute. Rather, the link element in our head.

We want to modularize our application and load in the CSS that's needed, where it's needed. In our small, little app, that doesn't quite make as much sense, but in a large-scale application, it's really nice to be able to just simply require the CSS that's related to your component, whether that be in Angular, React, jQuery, or Ember, whatever.

What we're going to do is we're going to remove the index.css. If we refresh, you can see now everything's gone. We're going to actually require the CSS for our application in our index.js. The way that this looks is you simply require. We'll say, "index.css." That's odd if you're used to Node CommonJS. You don't really commonly require stuff that's not just JavaScript files.

Actually, we need to...Let's turn on Webpack watch here. If we refresh the page here, we don't actually have any changes because you can't find that module. We don't have a loader for that yet. We need to add a loader in our Webpack config. We'll do that here. We're going to apply this to all files that end in .css.

We're going to load these through, actually, two loaders. One is called "style." The other one is called "css." This is how you pass assets through loaders. It flows from the right to the left. They're separated by the bang symbol.

You have the CSS loader, which will read our CSS, and then you have the style loader, which will actually insert the styles into the DOM so that they're applied. We need to npm install those. Let's stop our Webpack here. We'll say, "npm i style-loader css-loader." We'll save dev.

From there, everything should just work out of the box. If we say "webpack --watch" here, shouldn't get any errors. Looks like we did. Sorry. There is one other catch here. If we go to our index.css, we can see it's complaining about this line right here. The CSS loader doesn't handle this URL for us.

We need to tell it how to handle that. We are going to have one more loader. It is the url-loader. We'll save dev. We're going to add to that as anything that ends in .png, any assets. In this URL, it will say, "Hey. I need to resolve this, webpack.png." We're going to say we want to resolve it with the url-loader.

Now, if we run Webpack watch, there are no errors. If we go in here and refresh the page, everything is working as expected. All of our styles are applied appropriately. Actually, if you look here, before, it just had a background image pointing directly to that URL, but now you see it's just a data string, a base64 data string.

This is actually really cool. Now, instead of having to ship your index.html and making sure that all of your assets are being passed up to the server properly and copied over and everything, you actually just need to ship this bundle.js because it contains your PNG images.

There is a threshold. If your image is too big, then it will actually be bundled separately. In that case, you will need to send those up. This is also configurable, but this is really nice and simplifies things in a lot of really great ways.

That is how you add the CSS loader. It's really cool. If we wanted to decide, "Hey. Let's use a preprocessor here. We'll change this to a less file," then all we need to do is pass this through our preprocessor for our less. We'll say, "npm install less-loader," and save dev.

This is valid less. What's cool about less? We can say, "body." We'll wrap all of this in the body. Now we'll say, "webpack." One other thing. Obviously, we'll need to change this to less because we changed file name. Then we say, "webpack --watch."

We are getting an error here. Obviously, we also need to change our test. This needs to change from "css" to "less." Now let's restart that. Everything should work here. Then we refresh. We've got everything. We have the power of less.

It would be really easy to...If somebody decided, "You know what? I don't really like less very much. I'm going to use stylus," then we could add one for stylus. Boom. We have it. In fact, I'll just do that really quick.

I don't know. We'll take the logo piece out. We'll put it in our own file, logo.styl. We'll turn this into a stylus happy thing without any of this, without those. Now this is valid stylus. Let's npm install stylus-loader. Save dev. Then, in our index.js, we'll require the logo.styl. We'll restart this. We have our new config. Everything's working. The logo is still there.

We're running less and stylus together in a single project, which is probably not a terrific idea, but that just demonstrates how easy it is to have Webpack load all kinds of different types of assets for you. That is how you use Webpack to load your styles.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?