网页
综合
更新时间 2026-11-14 05:12:22
Native CSS | webpack
自动蜘蛛
webpack.js.org
正文约 6000 字
This guide shows how to use webpack's native CSS handling with experiments.css, and how to migrate an existing setup off css-loader, style-loader, and mini-css-extract-plugin.
Native CSS is stable and the recommended way to load CSS in webpack 5.109.0 and later — it is on by default, with no configuration. Use it instead of css-loader, style-loader and mini-css-extract-plugin, which are deprecated. The option keeps its experiments.css name until webpack v6 makes it unconditional.
On webpack 5.109.0 or later there is nothing to install and nothing to configure — import a .css file and webpack handles it:
experiments.css defaults to 'auto', which turns the built-in support on as long as no module.rules entry already claims .css files. Set it to true yourself only when you add such a rule — for example to run postcss-loader on .css files:
Either way, webpack understands .css files as first-class modules: it parses them itself instead of handing them to a loader.
"Built-in" means webpack does the work itself, with no loader in the chain — not that it covers everything the CSS loaders do. The scope is exactly this:
So a project whose CSS setup is css-loader + style-loader (or mini-css-extract-plugin) with default options needs no CSS loader at all. A project that reaches for the options in the right-hand column keeps that loader for the files that need it — the two can coexist, rule by rule.
Since webpack 5.109.0 the option defaults to 'auto': built-in CSS support turns on unless a module.rules entry with a loader (or an explicit module type) already matches .css files. An existing css-loader setup therefore keeps working untouched, and you can migrate one rule at a time. Set it to true to force the native support, or false to switch it off.
After enabling the experiment, import .css files directly from JavaScript:
Webpack processes the CSS and includes it in the build output.
Native CSS introduces four Rule.type values. Knowing which one applies is the key to migrating, because each maps to a different css-loader modules.mode:
The default rule webpack adds for /\.css$/i is css/auto, so *.module.css files become CSS Modules and everything else stays global — matching the most common css-loader configuration out of the box.
css/auto decides per file, by name: a resource path matching /\.modules?\.[^.]+$/i is parsed as a CSS Module (css/module), anything else as plain global CSS (css). The test looks at the file name only, with any extension — so it applies just as well to the output of a preprocessor rule as to .css files.
Given this project, with no CSS configuration at all apart from one Sass rule:
each file is handled like this (class names from a project whose package.json name is my-app):
All four end up in the same extracted main.css, in import order. Inside a CSS Module, :global(.theme-dark) .card keeps .theme-dark as written and scopes only .card, and composes makes the exported value a space-separated list of class names.
To treat a file differently from what its name says, give its rule an explicit type instead: css/module makes every matched file scoped, css/global keeps selectors global but honors :local(), and css disables CSS Modules parsing entirely.
Scoped class names come from the localIdentName generator option. It sits directly on the generator options for the module type — module.generator["css/auto"] for every file the default rule handles, or a rule's own generator for a subset:
The local ident hash is computed from localIdentHashSalt, output.uniqueName, the file path relative to context and the local name, so it is stable across builds and across web / node targets.
Prefer the base64url digest (or the default [fullhash]) over base64 in a template: base64 can produce + and /, which are valid in a class name only once escaped, so the stylesheet ends up with selectors such as .card_Hsi\/i.
exportsConvention renames the local before [local] is interpolated. With "camel-case-only", .card-title is exported as cardTitle and emitted as .cardTitle when the template contains [local] — keep that in mind if global CSS or tests target the original spelling.
With css/auto, name a file *.module.css (or *.modules.css) to opt it into CSS Modules:
src/button.module.css
By default namedExports is enabled, so import the locals as a namespace (import * as styles) or by name (import { button } from "./button.module.css"). Set it to false to keep the classic default-import object.
You can customize CSS Modules behavior with parser and generator options — see All options with examples below:
Native CSS Modules understand the same authoring features as css-loader, so most stylesheets migrate unchanged:
A single CSS module can be emitted in four ways. The exportType parser option selects which one, and each replaces a different piece of the classic toolchain:
Set it globally per module type:
or per rule for a subset of files:
With the default exportType: "link", CSS follows the chunk graph exactly like JavaScript does: every chunk that contains CSS modules gets its own .css file, named by output.cssFilename for initial chunks and output.cssChunkFilename for the rest. No plugin decides where styles go — optimization.splitChunks does, the same way it does for scripts.
Take two entries that both import shared.css and card.module.css, plus one stylesheet of their own each, and a lazily imported lazy.css:
The loading side needs no configuration: an entry's initial CSS chunks are listed in the entrypoint (and injected by native HTML when it builds the page), and the runtime inserts a <link> for an async chunk's CSS before it resolves the import().
A cache group's type option selects modules by their module type, which for native CSS is the type the matching rule assigned — css/auto for the default rule, but css/module or css/global for a rule that sets one explicitly. Use a regular expression so the group catches all of them:
To keep vendor styles in their own long-cached file instead, combine type wit
本页为82搜索生成的网页快照,内容来自站内索引;演示数据的原文链接仅作示例。