Skip to content

Latest commit

 

History

History
258 lines (201 loc) · 8.89 KB

Stylesheets.md

File metadata and controls

258 lines (201 loc) · 8.89 KB

Stylesheets

nwb generates Webpack module.rules configuration which allows you to import stylesheets directly from JavaScript modules:

import './App.css'

import React from 'react'

export default class App extends React.Component {
  // ...
}

When running a development server, imported stylesheets will be injected into the page using <style> elements and hot-reloaded when they change.

When running a production build, imported stylesheets will be extracted out to static .css files.

Default Stylesheet Rules

Note: each generated Webpack rule and chained loader has an associated unique id which can be used in webpack.rules configuration to tweak its configuration.

Without any webpack.styles configuration, nwb generates a rule (id: css-rule) which handles .css files by chaining together a number of loaders:

  • loader id: style - applies styles using style-loader

    Note: use of this loader is only configured when running a development server

  • loader id: css - handles URLs, minification and can be configured to enable CSS Modules, using css-loader

    Default config: {options: {importLoaders: 1}}

  • loader id: postcss - processes CSS with PostCSS plugins using postcss-loader; by default, this is configured to manage vendor prefixes in CSS using Autoprefixer

    Default config: {options: {plugins: [Autoprefixer]}}

Default Rules for CSS Preprocessor Plugins

To allow you to import preprocessed stylesheets just by having a CSS preprocessor plugin installed, nwb will generate a default Webpack rule for every CSS preprocessor plugin in your package.json.

For example, if you install the nwb-sass plugin, nwb will also generate a default sass-rule rule which will allow you to import .scss and .sass stylesheets, chaining together the same loaders as the default css-rule above plus a loader for the preprocessor.

Ids for configuring this rule and its loaders using webpack.rules follow a similar pattern css-rule, except they prefix the name of the preprocessor to make them unique:

  • rule id: sass-rule
    • loader id: sass-style
    • loader id: sass-css
    • loader id: sass-postcss
    • loader id: sass - preprocesses imported stylesheets using sass-loader

The same pattern applies for nwb-stylus and nwb-less.

e.g. to enable CSS Modules in the default sass-rule's css-loader:

module.exports = {
  webpack: {
    rules: {
      'sass-css': {
        modules: true,
        localIdentName: '[name]__[local]__[hash:base64:5]'
      }
    }
  }
}

Configuring PostCSS

By default, nwb uses PostCSS to manage vendor prefixes in CSS using Autoprefixer.

If you want to make more significant use of PostCSS, you can use webpack.rules to provide your own list of plugins.

e.g. to provide your own list of plugins for your app's own CSS, configure webpack.rules.postcss:

module.exports = {
  webpack: {
    rules: {
      postcss: {
        plugins: [
          require('precss')()
          require('autoprefixer')()
        ]
      }
    }
  }
}

Custom Stylesheet Rules

If your application needs more than one stylesheet rule, you can configure generation of multiple rules using webpack.styles config.

This should be an object defining lists of style rule configuration objects, with properties named for the type of rule being configured.

Rules for vanilla .css files are configured with a css property and rules for CSS preprocessor plugins are configured using the appropriate plugin name, e.g. sass when using nwb-sass.

module.exports = {
  webpack: {
    styles: {
      css: [/* ... */],
      sass: [/* ... */]
    }
  }
}

Stylesheet Rule Configuration

Stylesheet rule configuration objects trigger generation of a rule with chained loaders as per the default configuration above and allow you to configure loader options for the rule.

Included Files

Specify which files the rule applies to using test, include and exclude properties.

Default test config will be provided for each style type - e.g. /\.css$/ for css rules - but you can override it if necessary.

Loader Options

Loader options can be configured using a property which matches the loader's name: style, css,postcss or the name of any preprocessor loader being used.

e.g. to configure use of CSS modules within a specific directory:

// Create a rule which uses CSS Modules for CSS imported from src/components
{
  include: path.resolve('src/components')
  // The 'css' property within a stylesheet rule configures options for css-loader
  css: {
    modules: true,
    localIdentName: (
      process.env.NODE_ENV === 'production'
        ? '[path][name]-[local]-[hash:base64:5]'
        : '[hash:base64:5]'
    )
  }
}

With this rule alone, CSS imported from other directories, including node_modules/, won't be handled, so we should specify another rule to handle everything else:

// Create a catch-all rule for all other CSS stylesheets
{
  exclude: path.resolve('src/components')
}

Putting these together, the final style rule config would look like this:

module.exports = {
  webpack: {
    // Custom stylesheet rule configuration
    styles: {
      // The 'css' property is used to configure rules for vanilla CSS files
      css: [
        // Create a rule which uses CSS modules for CSS imported from src/components
        {
          include: path.resolve('src/components')
          // Configuration options for css-loader
          css: {
            modules: true,
            localIdentName: (
              process.env.NODE_ENV === 'production'
                ? '[path][name]-[local]-[hash:base64:5]'
                : '[hash:base64:5]'
            )
          }
        },
        // Create a catch-all rule for all other CSS stylesheets
        {
          exclude: path.resolve('src/components')
        }
      ]
    }
  }
}

Using this configuration, it's possible to specify multiple rules for stylesheets imported by your app and your dependencies.

For example, React Toolbox is a dependency which imports stylesheets on your behalf and requires a specific Webpack setup using CSS Modules and PostCSS-cssnext.

var reactToolboxVariables = {
  'button-height': '30px'
}

module.exports = {
  webpack: {
    styles: {
      css: [
        // Create a rule which provides the setup [email protected] needs
        {
          include: /react-toolbox/,
          css: {
            modules: true,
            localIdentName: "[name]--[local]--[hash:base64:8]",
            sourceMap: true
          },
          // The 'postcss' property within a style rule configures options for
          // postcss-loader.
          postcss: {
            plugins: [
              require('postcss-cssnext')({
                features: {
                  customProperties: {
                    variables: reactToolboxVariables
                  }
                }
              }),
              require('postcss-modules-values'),
            ]
          }
        },
        // Create a catch-all rule for other, regular CSS
        {
          exclude: /react-toolbox/
        }
      ]
    }
  }
}

Disabling Style Rules

If you want to handle creating style rules manually, you can disable nwb's default rules by configuring webpack.styles as false:

module.exports = {
  webpack: {
    styles: false
  }
}

If you need to use any of the Webpack loaders nwb manages dependencies for - e.g. css-loader and postcss-loader - refer to them by loader name in your webpack.extra config or webpack.config function. nwb configures Webpack to resolve these loaders correctly if they're not installed locally in your project.