Skip to content

Latest commit

 

History

History
280 lines (211 loc) · 6.38 KB

File metadata and controls

280 lines (211 loc) · 6.38 KB
title Native CSS
sort 27
contributors
phoekerson

This guide shows how to use webpack native CSS handling with experiments.css.

T> experiments.css is still experimental. It is expected to become the default in webpack v6, but behavior can still change while development continues.

Getting Started

Enable native CSS support in your webpack configuration:

webpack.config.js

export default {
  experiments: {
    css: true,
  },
};

With this option enabled, webpack can process CSS without adding css-loader and mini-css-extract-plugin for the basic flow.

Importing CSS

After enabling the experiment, import .css files directly from JavaScript:

src/index.js

import "./styles.css";

const element = document.createElement("h1");
element.textContent = "Hello native CSS";
document.body.appendChild(element);

src/styles.css

h1 {
  color: #1f6feb;
}

Webpack will process the CSS and include it in the build output.

CSS Modules

Native CSS support also includes CSS Modules. The recommended approach is:

  • keep type: "css/auto" for mixed CSS handling,
  • use .module.css (or .modules.css) naming for CSS Modules files.

src/button.module.css

.button {
  background: #0d6efd;
  color: white;
  border: 0;
  border-radius: 4px;
  padding: 8px 12px;
}

src/index.js

import * as styles from "./button.module.css";

const button = document.createElement("button");
button.className = styles.button;
button.textContent = "Click me";
document.body.appendChild(button);

T> CSS Modules class names are exported. By default, named exports are enabled for CSS modules.

You can customize CSS Modules behavior using parser and generator options:

webpack.config.js

export default {
  experiments: {
    css: true,
  },
  module: {
    parser: {
      "css/module": {
        namedExports: true,
      },
    },
    generator: {
      "css/module": {
        exportsConvention: "camel-case-only",
        localIdentName: "[uniqueName]-[id]-[local]",
      },
    },
  },
};

Production Build

With experiments.css: true, webpack provides native CSS extraction and content hashing for CSS assets in production builds.

Compared to the classic setup:

  • Traditional approach: css-loader + mini-css-extract-plugin
  • Native approach: experiments.css with built-in extraction behavior

This reduces configuration and keeps the CSS pipeline closer to webpack core features.

Experimental Status & Known Limitations

experiments.css is explicitly experimental, so treat it as opt-in and test carefully before broad rollout.

Known points to keep in mind:

  • APIs and behavior may still evolve before webpack v6 defaults.
  • Some loader-specific options are not part of native CSS behavior (for example, loader-specific filters).
  • If your project relies on advanced loader chains, validate each part before migrating fully.

Migration Guide

If you currently use css-loader, mini-css-extract-plugin, and style-loader, migrate in small steps.

1) Start from a classic setup

webpack.config.js

import MiniCssExtractPlugin from "mini-css-extract-plugin";

export default {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
};

2) Switch to native CSS

webpack.config.js

export default {
  experiments: {
    css: true,
  },
};

3) Migrate css-loader options first

Most CSS Modules-related options should move to native parser/generator config.

webpack.config.js

export default {
  experiments: {
    css: true,
  },
  module: {
    parser: {
      css: {
        import: true,
        url: true,
      },
      "css/module": {
        namedExports: true,
      },
    },
    generator: {
      "css/module": {
        exportsConvention: "camel-case-only",
        localIdentName: "[local]-[hash:base64:6]",
      },
    },
  },
};

Notes:

  • import and url are native parser switches for CSS handling.
  • namedExports controls CSS Modules exports behavior.
  • exportsConvention and localIdentName provide class export/name shaping.
  • localIdentName supports hash placeholders (for example [hash:base64:6]); you can tune hashing globally with output.hashFunction, output.hashDigest, output.hashDigestLength, and output.hashSalt.
  • css-loader filter-style options are not available as direct equivalents; use webpack mechanisms such as IgnorePlugin when needed.

4) Replace mini-css-extract-plugin

When experiments.css is enabled, webpack provides native CSS extraction and content hash handling for CSS output files.

webpack.config.js

-import MiniCssExtractPlugin from "mini-css-extract-plugin";
-
 export default {
+  experiments: {
+    css: true,
+  },
   module: {
     rules: [
       {
         test: /\.css$/i,
-        use: [MiniCssExtractPlugin.loader, "css-loader"],
+        use: ["css-loader"],
       },
     ],
   },
-  plugins: [new MiniCssExtractPlugin()],
 };

You can remove:

  • MiniCssExtractPlugin.loader from module.rules,
  • the new MiniCssExtractPlugin() plugin instance.

5) Replace style-loader with exportType: "style"

If you used style-loader for runtime style injection, keep css/auto and use module naming (.module.css or .modules.css), then set exportType: "style":

webpack.config.js

export default {
  experiments: {
    css: true,
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        type: "css/auto",
        parser: {
          exportType: "style",
        },
      },
    ],
  },
};

This mode injects a <style> element from the webpack runtime and covers the typical style-loader use case.

If you cannot rename files to the CSS Modules naming convention, you can use type: "css/module" directly for the relevant rule.

6) Keep imports unchanged

Your JS imports can stay the same:

import "./styles.css";
import * as styles from "./button.module.css";

7) Validate output in development and production

Check that:

  • styles are applied correctly in development,
  • generated CSS files are emitted for production,
  • CSS Modules exports match your existing usage.