Skip to main content

Options for CSS

Option: css

Type:

type CssOptions = {
test?: RegExp;
filename?: FilenameTemplate;
chunkFilename?: FilenameTemplate;
outputPath?: string;
inline?: 'auto' | boolean;
hot?: boolean;
};

Default properties:

{
test: /\.(css|scss|sass|less|styl)$/,
filename: '[name].css',
chunkFilename: '[name].css',
outputPath: null,
inline: false,
hot: false,
}
  • test - an RegEpx to process all source styles that pass test assertion
  • filename - an output filename of extracted CSS. Details see by filename option.
  • chunkFilename - an output filename of non-initial chunk files, e.g., a style file imported in JavaScript.
  • outputPath - an output path of extracted CSS. Details see by outputPath option.
  • inline - inject CSS into into HTML at render time, available values:
    • false - stores CSS in an output file (defaults)
    • true - adds CSS to the DOM by injecting a <style> tag
    • 'auto' - in development mode - adds to DOM, in production mode - stores as a file
  • hot - inject CSS into the DOM at runtime and enable HMR (hot update CSS without a full reload), similar to how it works in style-loader.

All source style files specified in <link href="..." rel="stylesheet"> are automatically resolved, and CSS will be extracted to output file. The source filename will be replaced with the output filename.

For example:

<link href="./style.scss" rel="stylesheet" />
warning

Don't import source styles in JavaScript. Styles should be specified directly in HTML.
Don't define source JS files in Webpack entry. Scripts must be specified directly in HTML.

The default CSS output filename is [name].css. You can specify your own filename using webpack filename substitutions:

const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
module.exports = {
plugins: [
new HtmlBundlerPlugin({
css: {
filename: 'css/[name].[contenthash:8].css',
},
}),
],
};

The [name] is the base filename of a loaded style. For example, if source file is style.scss, then output filename will be css/style.1234abcd.css.
If you want to have a different output filename, you can use the filename options as the function.

css.hot option

caution

⚠️ Limitation

  • HMR works only for styles imported in JavaScript files. Doesn't works for styles defined directly in HTML via link tag.
  • Hot update without a full reload works only for styles imported in a last JavaScript file.
    If you have many JS files defined in HTML, where are imported styles, and change a style file imported in the first JS file, then changes will not be detected in HMR module. You should reload the browser manually. This behavior is a BUG in Webpack. The style-loader has exactly same limitation.

If you use the Live Reload configuration, then be sure to exclude the style files (CSS/SCSS) from watching, otherwise after changes a style file, a page will be full reloaded.

info

If devServer is configured for HRM with styles, then after changing the styles defined in HTML, Live Reload will not work for them. You should then reload the browser self.

Configuration of devServer to enable HMR:

devServer: {
static: {
directory: path.join(__dirname, 'dist'),
},
watchFiles: {
paths: ['src/**/*.(html|eta)'], // <= exclude *.s?css from watching
options: {
usePolling: true,
},
},
},
tip

To enable HMR for all style files without a full reload, import all those styles in one JS file.

warning

Don't use mini-css-extract-plugin because the bundler plugin extracts CSS much faster than other plugins.

Don't use resolve-url-loader because the bundler plugin resolves all URLs in CSS, including assets from node modules.

Don't use style-loader because the bundler plugin can auto inline CSS and HMR.