Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

with webpack, why should one import CSS files from JS source code and not build CSS in isolation like the tradition did?

Tags:

css

webpack

webpack doc for loading css: https://webpack.js.org/guides/asset-management/#loading-css1

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.

--> with webpack, why should one import CSS files from JS source code and not build CSS in isolation like the tradition did?

By not importing CSS from Javascript, I mean that the webpack config for CSS has no ".js" extension, and it parses the CSS/SCSS files directly.

There are benefits of not importing CSS from javascript:

  1. (objective fact). If one wants to build only CSS, it will be faster if the bundler does not need to parse the Javascript source code. Besides, one can run the bundlers for CSS and Javscript in parallel by using parallel-webpack.

  2. (subjective, based on tradition, but most important in my opinion). SASS building in isolation has been the tradition for years. Therefore, we can achieve better HTML semantics and maintainability. Importing CSS from JS is virtual and may lead to neglect the generated separate CSS bundle.

  3. (objective fact) One can split more the config files for CSS and Javascript, for more clarity.

like image 472
Thierry Vilmart Avatar asked Dec 21 '17 08:12

Thierry Vilmart


1 Answers

I'm more a traditionalist than most as i've been doing this for over 15 years, but I would say the new way to separate concerns is better than the traditional way.

In the old thinking we use to separate layout from styling from functionality (html from css from js). This is more 'vertical' and made knowing where files are easy, but made finding specific code to do with 'features' hard. I.e. a button might be made up of a small button section within /src/shop-front.html, a few lines of code within /src/css/shop-front.css and then the enhanced functionality would live somewhere in /src/js/shop-front.js

The new way of thinking is to separate concerns by components. So now you would have your shop-front, but this would be made from /src/components/button/ and all files will live in the same place. Including the js file which includes the css as mentioned.

The benefit being, if you decide to swap button for fancy-button all you do is change the shop-front import button from 'button' to import button from 'fancy-button'. all old code will be removed automatically. no need to try to digest and change code in multiple places.

To address your concerns:

  1. true, node-sass is fast, but I would say the difference between that and going via webpack is negligible and the improvement in dev experience (as mentioned above) is worth any extra ms

  2. This point does apply as the way the css/sass is built does not change just because we require it from a js file. I guess you mean if you were to use css modules, but this is a choice, you don't have to. I use sass and apply class names as i would normally.

  3. In webpack config, you could split the js config from the css config if you wanted to. I wouldn't argue that this would make things any clearer though. the config is so small, it's not worth worrying about.

My folder structure is nice and easy to reason with:

enter image description here

This is a basic config for simple scss imports

const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { SRC, DIST } = require('./src/config/paths');

module.exports = {
  devtool: 'source-map',
  cache: true,
  context: SRC,
  entry: {
    app: [`${SRC}/client-entry.js`]
  },
  output: {
    path: DIST,
    filename: '[name]-[chunkhash].js',
    publicPath: '/'
  },
  plugins: [
    new ExtractTextPlugin('[name]-[contenthash].css'),
  ],
  resolve: {
    modules: ['node_modules', SRC],
    extensions: ['.js', '.jsx', '.scss']
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        include: [/src/],
        loader: 'babel-loader',
        options: {
          cacheDirectory: true
        }
      },
      {
        test: /\.s?css$/,
        include: [/src/],
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'postcss-loader', 'sass-loader']
        })
      }
    ]
  }
};
like image 57
peter.mouland Avatar answered Nov 13 '22 00:11

peter.mouland