Making your CSS modular is a difficult thing to do, but using Webpack makes this so much easier. By adding a single line to your Webpack config, you can require you CSS, Stylus, Less, etc. files right from your directives and keep everything together.
[00:01] Now let's say that we want to style this directive. Say we want to change the color of the text, for example. Normally, what you would do is you'd create a file called "kcd-hello.css." We'll look at our template. We have the kcd-hello class. We'll say, "kcd-hello," "color." We'll just say it's green.
[00:22] If I save this and refresh, obviously, it's not going to be applied because this kcd-hello is not being loaded into the browser. Webpack is really cool in that you don't have to build all of your assets separately and then make sure that you deploy your styles.css and scripts.js and all of that.
[00:39] Instead, you just deploy your single bundle.js file. That will load everything that you need, including images, in most cases. What we're going to do is we'll just require all the things. Right here, in our directive definition, we're going to require kcd-hello.css.
[01:02] If we save this and we look at our output, we're going to see unexpected token. We've got problems right here. We need to load the appropriate loader for this file type. The appropriate loader is...Actually, there are two of them that we need.
[01:17] First, we need the CSS loader. That's going to give us the ability to read the CSS file, know what it means, and turn that something that the style loader will understand. The style loader will actually load this as a style tag, into the browser.
[01:32] We'll npm install, as a dev dependency, css-loader and style-loader. Now we're going to need to restart our Webpack server, but let's create our loaders first. We have our stuff for JS, HTML, and now CSS. Add our comma there. Our loader will now be style and CSS.
[02:05] Loaders run from the right to the left. First, our files will be run through the CSS loader. Loaders are separated by a bang symbol. Then it'll be run through our style loader. This will be applied to any file that matches .css.
[02:21] If we go back here, this file matches .css. This will be loaded through the CSS loader and then the style loader. Let's npm start to start our webpack-dev-server, and then we'll refresh. You see it's green. That's exciting. We're actually getting the styles in here. Let's look at the DOM and see what's actually going on here.
[02:44] We have this new style tag that we didn't have before, that has a kcd-hello color green. Just to be sure that we're not crazy or something, we'll change this to red. We'll save and refresh. Now that's color red. That is what's actually happening as these styles are getting loaded into the browser.
[03:03] Lots of times, you're going to want to use a preprocessor for your CSS. If that's something that you're wanting to do, you're going to need to have yet another loader. Let's add a new line here. We'll use stylus in this example. We're going to add one more loader, the stylus loader.
[03:26] The stylus loader will take a stylus file, convert it into CSS. Then the CSS loader will take that, convert it into something that the style loader can understand and inject into our DOM. We need to, obviously, install the stylus loader. We'll npm i -D stylus-loader and make sure that installs properly.
[03:50] Then we'll need to restart our Webpack server. We refresh. Everything's still working because we're still using this CSS here, but let's change this from CSS to styl. Then we'll change this into some stylus goodness here without all of that other stuff.
[04:12] There are times that you may need to restart your Webpack server just because it doesn't recognize file name changes in some cases and things. If you don't see this change from valid to invalid when you change a file, like that, then you've got a problem.
[04:26] You need to restart your Webpack server. We'll go ahead and restart it. We'll refresh. We are now getting an error. This error is coming because when we changed this file name, we forgot to change how we're requiring it. Here, we will require the styl file.
[04:44] Now we'll refresh. There, we have "Hello Webpack" in red. We can change that to green, just to make sure that everything's working. Now we have stylus. If we wanted to change that to less, we'd just change this to less, change this to less, and then, obviously, install the less loader.
[05:05] We'd change this file name to be less and, obviously, require it as a less file, and then change the syntax because less doesn't understand stylus syntax. That is how you include your CSS into the browser.
[05:21] In our case, we don't need this CSS loader or test case anymore. We have no files that match that, but we'll just leave that there anyway. That's how you have a specific style for a specific component. Again, all of these files live together.
[05:41] It makes things much more modular than the traditional thing that we're all used to, where we have different things being loaded from different directories. It's just a big mess. Everything is all together and makes things a lot easier to move around as architecture decisions change. That is using CSS with Webpack and Angular.
What's the point of excluding
node_modules from the style loader? It means that you can't require
You're absolutely correct. :-)
Are there no significant performance hits by bundling the CSS within the bundle.js? Are you sacrificing the browser's inherent caching of external CSS files?
If you are concerned, there are ways that you can inform the loaders to save the result in a separate file. But I would recommend that before adding that layer of complexity, you first measure whether it will make a difference for your use case.
How would you make your .styl code use variables from other files with webpack? For example, I have a file variables.styl located elsewhere, how can I use it in kcd-hello.styl?
You can still do normal imports in your stylus files. Treat them like normal stylus files and you'll be able to import variables normally :-)