Webpack – what do you think of this way building CSS and Javascript separately

summary:

I describe below my setup building CSS and Javascript separately with webpack. It works nicely. It is not what the webpack documentation recommends. So I am interested to know what you think about it.

webpack doc for loading css:

The webpack doc asks to import the CSS files from the Javascript code and to then run extract-text-webpack-plugin to extract the CSS. I think it is preferable to build CSS and Javascript separately for many reasons given below, but especially for 2 reasons:

  1. If one wants to build only CSS, it will be faster if the bundler does not need to parse the Javascript source code.
  2. SASS building in isolation has been the tradition for years. Therefore, we can achieve better HTML semantics and maintainability.

Here is my setup:
– parallel-webpack requires 2 separates config files, one for CSS and one for webpack.
It will run the building and the watching of the 2 configs in parallel.
– In the CSS config file, I use ExtractTextWebpackPlugin to create the CSS bundle. And the only accepted extension in the config file is “.scss”. There is no “.js”. And in production, I run OptimizeCssAssetsPlugin to minimize the CSS.

It seems to me that building separately is better for the following reasons:
–> compilation time:
– If one wants to build only CSS, it will be faster if the bundler does not need to parse the Javascript source code. I can use an env variable that I pass to parallel-webpack in order to ask to build only CSS.
– My build time in development is so fast, of around 2 s, that I don’t need to use webpack-dev-server or hot module replacement. I just run webpack –watch and I refresh the page.
– parallel-webpack will build CSS and Javascript in parallel in separate threads. It will be faster than with the official way of building CSS in webpack.

–> SASS building in isolation has been the tradition for years:
Traditionally, SASS building has been separated from building the Javascript source code.
– The traditional way of structuring SASS, has a manifest file (or main file) that imports everything. It is isomorph to the final result with a CSS bundle that will be global to the entire web page.
– Most methodologies for good SASS (SMACSS, 7-1, OOCSS, etc) rely on the traditionaly way
– good CSS structuring is meant to focus on the HTML semantics for structure and maintainability. The mapping Javascript to SCSS is a secondary issue that can be solved with good ways of working.
– In production the CSS and the Javascript will be separated. So the mapping of Javascript to CSS in the Javscript code can only be temporary.
– the way of using of a manifest file for SASS is probably optimized in the C library libsass that is used to compile it.
– the manifest file (or main file) is not confusing. In most languages there is a main.c like file.
– It seems to me that the many people that currently use Gulp as a SASS bundler are doing a very similar setup as I propose with webpack. So we follow the tradition.

–> simplification of config files
– Separating the config files simplifies greatly the config files. It is not possible to separate with the official way because one has to mix the build, so one has to mix files extensions, folder locations, etc.

–> future proof for the use of package:
With SASS from Javascript, you become dependent of the people maintaining all the packages (webpack, node-sass, etc). Whereas building raw SASS has many libraries.
A completely new way of building may show up. In the past few years we saw many new build frameworks.

–> the web geek-spider goes fast but experimental technology may not work well:
Building raw SASS is stone-like robust to work. The official webpack way is experimental because it is new. The ordering in the CSS may not be controlled. variables have no global scope. Code could be repeated. A package may behave stangely.

–> with parallel webpack, it is simple to build and watch both the Javascript and the CSS bundles. One can even pass an env variable to build only CSS.

I found another benefit of separating CSS and Javascript in webpack. I can activate the source maps for CSS only and not for webpack, in order to speed up the build. This requires to separate the configs using parallel-webpack because for javascript the activation of source maps is global to the whole config.

I did not mention it because it is hard to quantify. But it seems that there are some benefits of bundling CSS and Javascript in parallel using parallel-webpack, like parallel threads.

One person suggested using node-sass directly. But I think there are lots of features webpack allows for CSS, and with the same config style as for javascript, like adding CSS minimization in production.

I agree for the most part, but then why use a JS module bundler in the first place if all you want to do is compile your Sass? I mean that’s what node-sass does already…

yarn node-sass src/scss/index.scss -wo dist

and your done. ;-)

As for (S)CSS imports in JS, this can be beneficial if you have styles that are directly tied to components (and probably residing in the very same directory), which you can then easily share / reuse in different projects as standalone modules with everything in one place. You can even scope the CSS to the components so that you don’t have to worry about interfering with other compontens’ CSS… angular would be a prominent proponent of such a structure, for example.

Using webpack for raw CSS building and not node-sass has the following benefits:

  • the watching and the building will be done in parallel for both the Javascript and the CSS bundles, and this using only one webpack command for both the JAvascript and the CSS bundles.
  • the config looks like the config for webpack bundling. One does not need to learn how to configure node-sass. In particular to locate the files to build. Potentially, one can activate more webpack features, like if/else in the config for production or not, or like the webpack-dev-server.

→ Do you have a link about why importing CSS from Javascript helps structuring with Angular or with React?

I am hesitant about CSS imports form Javascript. Traditionally in CSS, a folder components was used for things like buttons. A React component is not visible in the DOM. It is a virtual thing.

I gained even more build time by parallelizing the generation of HTML.

When I had to generate an HTML file with an extension to my urls to force the cache update on my assets (example (bundle.js?asd43fsa45dfsef), I used HtmlWebpackPlugin.

Using the shell command time, I compared the building time of 2 webpack builds that build all my assets (Javascript, CSS, HTML) using parallel-weback:

  • one build with the HtmlWebpackPlugin used together with my Javascript webpack config.
    It took: 6.468s
  • one build with the HtmlWebpackPlugin used in isolation by using an empty dummy.js as entry point.
    It took 6.028s

I had use HTML templates and use a manually generated Id for the url extensions. Quite in deviation from the official doc of the plugin HtmlWebpackPlugin.

In conclusion, it is very efficient to separate the building of all my assets into separate config files, one for JS, one for CSS, one for HTML. I can get maximum benefit from parallel-webpack. And even watch in parallel.

actually changes on js will not trigger a rebuild of the HTML. But this is fixable if a small hack ( edit the entry file fro HTML config as a callback of a watching plugin) and plugins to watch additional files.

Btu the benefit in build time is worth the hack.

Ah okay, got you! :-)

I don’t have a specific link off hand I’m afraid, but you can find plenty of articles on that topic via google. Anyway I think the main takeaway is that if you have a project structure like this

components
  |-slider
    |- slider.component.css
    |- slider.component.html
    |- slider.component.spec.ts
    \- slider.component.ts
  \-tabs
    |- tabs.component.css
    |- tabs.component.html
    |- tabs.component.spec.ts
    \- tabs.component.ts

you have encapsulated and highly reusable modules with a single entry point, which makes them easy to share across projects (you might even publish them as npm modules or export them to dedicated repos). It’s also easy to work with in general, as you don’t have to search in various directories all the time to find the related tests, templates and CSS files.

Me too. :-) I’m just saying that there’s a use case for directly linking CSS to JS like this… if it fits your project certainly depends though.

Sure there is a use case. The webpack official way is highly encouraging on proceeding so, whereas this JS to CSS mapping is not according to tradition of CSS builds. They could document the possibility to stick to the traditional way of not importing CSS from JS. As I explained, the build is made faster.

It seems to me that the modular way to group CSS and Javascript can be achieved with a good way of working, without having to import CSS from JS. For example, to map JS components and component-specific CSS, one can use a symbolic link from the Javascript component folder to the assets/components/_slider.css. THose links would be used only by the developer, not by webpack or node-sass.

Even when importing the CSS from Javascript, one will need to extract it to a separate CSS bundle for performance reason (to load CSS and JS i parallel as the doc recommends).

If we build the bundles in parallel, a change in one bundle cannot trigger the rebuilding of another bundle. But this can be solved as I explain below by watching additional files, and creating empty files.

I could fix this issue in a simple way and without hacks. I use webpack-watch-files-plugin to watch for additional files in the webpack config for the HTML creation. I watch the 2 bundles, the CSS one and the JS one: bundle.js and bundle.css.

However, the watching will only work if the files already exist before webpack is run. To solve this new problem I added some code at the top of the webpack config to create empty files if they do not exit.

I have recently read 2 books about SASS. The tradition I mentioned before is documented by those books.

  • Mastering Sass, by Luke Watt, August 2016.
    Excellent book. In particular it shows how to build all SASS from scratch using good methods (atomic, OOCSS, SMACSS, BEM, etc). HTML semantic means structure, and wrapping of all functionality in well named classes.
  • Sass and Compass Designer’s Cookbook, By Bass Jobsen, April 2016.
    Very thorough, and gives a glance to main frameworks (like Bourbon the SASS library, with the golden number ratio for text/line height)

In the SMACSS methodology, the SASS files are split into different folders as follows:

  • base
  • layout
  • modules
  • state
  • theme
    Often each folder can have sub-folders per page.

The react or angular components would traditionally be placed in the modules folder. This means the other folders should not be directly mapped to JS components.

In the 7-1 method, the folder components refer to concrete things like button, not at all a high level concept such as React or Angular component. Because the other folders should be more generic (like the folders called common).

SMACSS and 7-1 methods belong to the tradition. When associating CSS with Javascript-based react or Angular components, with the CSS imports from Javascript, you are doing something new. Perhaps you can do it right. In my case, I like to structure my SASS with the help of those books and with the methods of the tradition.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.