Library / SDK
webpack/postcss-loader avatar
webpack/postcss-loader

postcss-loader: webpack 4 lives on version 4, and three doc examples repeat their own keys

PostCSS loader for webpack

2,839 stars212 forksJavaScriptMIT

At a glance

What is it?
The official webpack loader for running PostCSS over CSS, published by the webpack organisation with three runtime dependencies and a build that transpiles src with Babel. Its documentation is careful about where PostCSS options belong and blunt about what is going away, and it leans on an experimental webpack CSS flag that only exists from webpack 5.87.0.
Who is it for?
postcss-loader is the loader to reach for when a webpack project needs PostCSS and nothing beyond it, and its narrow dependency list is the reason it is easy to live with: configuration discovery, a TypeScript aware config loader and a version comparison, nothing that duplicates PostCSS itself. Three things to check first.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • webpack/postcss-loader2,839 ★ · -2
Star history
Repository2026-10-042026-11-13
webpack/postcss-loader2.8k2.8k

-2 Stars in the last 40 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The loader's major version tracks webpack's major version

The first constraint in the documentation is a version fork rather than a feature list. It states that webpack v5 is needed for the latest version, and that webpack v4 users have to install postcss-loader v4. So the loader's major number is not an API redesign cycle of its own; it is tracking the bundler's. Installation is shown three times over, once per package manager, and in each case PostCSS itself is installed alongside the loader:

console
npm install --save-dev postcss-loader postcss

with the yarn and pnpm equivalents given as `yarn add -D postcss-loader postcss` and `pnpm add -D postcss-loader postcss`. That the examples show npm, yarn and pnpm while the repository ships an npm lockfile is a small sign of how widely this package is consumed rather than how it is developed. The version in the manifest is 8.2.1, matching the newest release, and the two before it are 8.2.0 and 8.1.1, with the last push to the default branch dated 2026-09-03.

The documented configuration sits on top of an experimental webpack CSS flag

Every configuration example in the documentation turns on webpack's built-in CSS support:

js
module.exports = {
  experiments: {
    css: true,
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        type: "css/auto",
        use: ["postcss-loader"],
      },
    ],
  },
};

Two facts hide in that. The flag is described as an experiment and as available only from webpack 5.87.0, so the documented setup does not apply to an earlier v5 even though v5 as a whole is supported. And the rule's `type` is `css/auto`, which the comment describes as treating `*.module.css` files as CSS modules and every other file as regular CSS. The alternative path is spelled out too: keep `css-loader` and `style-loader` in the list, and place `postcss-loader` before them. The example configuration also relies on `postcss-preset-env`, which carries a note that it is not installed by default.

postcssOptions takes a function, and that is where per-file logic goes

The option's declared type is a union, and the second arm of it is a callback:

ts
export type PostCSSLoaderOptions =
  | PostCSSConfig
  | ((api: PostCSSLoaderAPI) => PostCSSConfig);

The API object handed to that function carries the loader context fields: `mode`, `file` taken from the context's resource path, the whole `webpackLoaderContext`, `env` which mirrors `mode`, and the `options` already resolved. So a project that needs different PostCSS settings per file is expected to write a function, not to swap configuration files. The same section carries the performance advice that shapes this: for large projects it is better to pass `postcssOptions` in the loader configuration and set `config: false`, because that removes the need to look up and load external config files repeatedly during a compilation. The trade is explicit, inline options for speed, or a config file for portability.

Source maps get their own option because from, to and map are discouraged

The options list is short, four entries: `execute`, `postcssOptions`, `sourceMap` and `implementation`. Two of them are documented in full and two are named. The guidance that has the most practical effect is a warning inside the `postcssOptions` section: do not specify `from`, `to` and `map`, because doing so can lead to wrong paths in source maps, and use the loader's `sourcemap` option instead if source maps are needed. That is a small thing to get wrong and an expensive one to debug, since the symptom is a map pointing at the wrong file rather than an error. The first option, `execute`, is a boolean defaulting to undefined, and it exists for CSS-in-JS: when styles are written in JavaScript and parsed with the `postcss-js` parser, the loader has to be told to execute rather than treat the input as plain text.

Two plugin syntaxes are already marked for removal in the next major

The plugins array accepts several shapes, and two of them come with the same warning. The current form takes plain names, a name with an options object, a resolved path, and an already instantiated plugin object:

js
plugins: [
  "postcss-import",
  ["postcss-short", { prefix: "x" }],
  require.resolve("my-postcss-plugin"),
  myOtherPostCssPlugin({ myOption: true }),
  // Deprecated and will be removed in the next major release
  { "postcss-nested": { preserveEmpty: true } },
],

That last line is a bare object inside the array, commented as deprecated. A second, longer example is labelled deprecated in its heading and uses a whole object map, `{ "postcss-import": {}, "postcss-short": { prefix: "x" } }`, where plugins are keys rather than array entries. So a configuration written in the object style still runs today and will stop running at the next major, which is a migration to schedule rather than a bug to report.

The syntax and parser examples declare the same key two and three times

The examples for `syntax`, `parser` and `stringifier` show every accepted shape inside one object literal, which makes them shape illustrations rather than valid configurations. The syntax block declares `syntax: "sugarss"` and then `syntax: require("sugarss")` in the same object. The parser block goes further and declares `parser: "sugarss"`, `parser: require("sugarss")` and `parser: require("sugarss").parse`, so a reader has to pick one, because in JavaScript the last key wins. Each of those blocks is preceded by an `<!-- eslint-skip -->` comment in the source of the page, which is consistent with the snippets being deliberately unlinted. The third block, for `stringifier`, is cut off mid-statement at a line beginning `const Midas = requ`, so the accepted forms for a custom stringifier are not readable here. That is the point at which the documentation for `sourceMap` and `implementation` also stops.

Every test run starts with three linters, and installing the package builds it

The scripts make the workflow visible. A single `lint` script fans out to every task with the prefix, so prettier, eslint and cspell all run in parallel, and `pretest` calls that lint script, which means a test run cannot start until formatting, code and spelling all pass. Tests are jest, with `test:coverage` collecting from `src/**/*.js`. The `prepare` script is `husky && npm run build`, so a plain install inside a checkout compiles the package as a side effect, and the build is Babel from `src` into `dist` with a clean step first. Publishing is handled by `standard-version` while commit messages are validated by `commitlint --from=main`, and a `security` script runs `npm audit --omit=dev` against production dependencies only. The published surface is `dist` alone, the entry point is `dist/cjs.js`, and the three runtime dependencies are cosmiconfig for configuration discovery, jiti for loading configuration and semver for version comparison. Version numbers in the manifest come from that tool rather than being maintained by hand, since standard-version derives the next number from the commits since the last tag and writes it back into the file the build reads.

Editorial conclusion

postcss-loader is the loader to reach for when a webpack project needs PostCSS and nothing beyond it, and its narrow dependency list is the reason it is easy to live with: configuration discovery, a TypeScript aware config loader and a version comparison, nothing that duplicates PostCSS itself. Three things to check first. The version line tracks webpack's, so webpack 4 users are on postcss-loader 4 and a v5 upgrade is not a patch. The documented configuration depends on an experimental webpack feature for CSS that only landed in 5.87.0, so on an older v5 the examples do not apply and the css-loader plus style-loader path is the one that does. And two plugin syntaxes are already labelled deprecated with removal in the next major, so configuration written in the object form is on a clock.

Frequently asked questions

what is postcss loader

It is the webpack loader for processing CSS with PostCSS, published by the webpack organisation under the MIT license. You install postcss-loader together with postcss, and you need webpack v5 for the latest loader version while webpack v4 users must install postcss-loader v4.

Which options does postcss-loader accept?

Four: execute, postcssOptions, sourceMap and implementation. postcssOptions is either a PostCSS configuration object or a function receiving an API with mode, file, env, options and the webpack loader context, which is how per-file settings are expressed.

Do I need css-loader and style-loader alongside postcss-loader?

Not if you use webpack's built-in CSS support, which the examples enable with the experiments css flag available in webpack 5.87.0 and later. If you prefer css-loader and style-loader, keep them in the loader list and use postcss-loader before them.

Why do my postcss-loader source maps point at the wrong file?

The documentation recommends against setting from, to and map in postcssOptions, because those options can lead to wrong paths in source maps. It says to use the loader's own sourcemap option instead when source maps are needed.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. webpack/postcss-loader on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/webpack-postcss-loader.svg)](https://hysenlabs.com/projects/webpack-postcss-loader)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/webpack-postcss-loader.svg)](https://hysenlabs.com/projects/webpack-postcss-loader)

Was this useful?