Having trouble with PostCSS trying to use PurgeCSS

I’m having some confounding trouble getting PurgeCSS working. I’ve followed all the instructions to a T, even some that were not part of the instructions but were necessary for it to supposedly work. Researched all the help I could find on this forum and the general web. And no matter what I get the same issue.

When I run hugo serve I get the following error:

$ hugo server  --verbose
Start building sites …
hugo v0.103.0-beebf2afb09a7be36cf12bdec8a99ae9286504e2+extended windows/amd64 BuildDate=2022-09-15T16:23:56Z VendorInfo=gohugoio    
INFO 2022/09/25 12:24:57 syncing static files to \
INFO 2022/09/25 12:24:57 postcss: The filename, directory name, or volume label syntax is incorrect.                                syntax is incorrect.
Error: Error building site: POSTCSS: failed to transform "css/custom.css" (text/css): The filename, directory name, or volume label 
syntax is incorrect.

Git test repo is here:

Let me spell out my environment:

  • Project root is C:\_plain\ (It was in another location and I wondered if the spaces in the path name were causing issues but it seems not, at least the error hasn’t changed)
  • I have node v18.9.1 & npm 8.19.2 installed which are the very latest
  • In my project root, I ran the following commands:
$ npm init -y
$ npm install postcss postcss-cli @fullhuman/postcss-purgecss
$ npm list
_plain@1.0.0 C:\_plain
├── @fullhuman/postcss-purgecss@5.0.0
├── postcss-cli@10.0.0
└── postcss@8.4.16
  • I’ve even tried it with also installing autoprefixer but that didn’t do anything (I don’t know what it does but I saw a lot of people include it but it’s not part of the official guide)

  • I have the following postcss.config.js as directed by the official guide for Hugo

const purgecss = require("@fullhuman/postcss-purgecss")({
  content: [".\hugo_stats.json"],
  defaultExtractor: (content) => {
    const els = JSON.parse(content).htmlElements;
    return [...(els.tags || []), ...(els.classes || []), ...(els.ids || [])];
  },
  safelist: [],
});

module.exports = {
  plugins: [
    ...(process.env.HUGO_ENVIRONMENT === "production" ? [purgecss] : []),
  ],
};
  • My head.html partial contains the following:
<head>
  {{ $css := resources.Get "css/custom.css" | resources.PostCSS }}

  {{ if hugo.IsProduction }}
    {{ $css = $css | minify | fingerprint "sha256" | resources.PostProcess }}
  {{ end }}

  <link
  rel="stylesheet"
  href="{{ $css.RelPermalink }}"
  crossorigin="anonymous"
  integrity="{{ $css.Data.Integrity }}"
  media="all" />
</head>
  • My config.toml contains the following:
baseURL = 'http://example.org/'
languageCode = 'en-us'
title = 'My New Hugo Site'

[build]
  writeStats = true

No matter what I do, I get the same error. And there is no insight online as to what could be wrong.

I’m at a loss and the main website I’m working on, which is a private repo, uses bootstrap scss and the final size is ~300kb, most of it unused, so I really want PurgeCSS to work.

If I remove any content from the assets/css/custom.css file so that it is empty, I get the following error message:

$ hugo server  --verbose
Start building sites … 
hugo v0.103.0-beebf2afb09a7be36cf12bdec8a99ae9286504e2+extended windows/amd64 BuildDate=2022-09-15T16:23:56Z VendorInfo=gohugoio
INFO 2022/09/25 12:53:11 syncing static files to \
INFO 2022/09/25 12:53:11 postcss: use config file C:\_plain\postcss.config.js
INFO 2022/09/25 12:53:11 postcss: The filename, directory name, or volume label syntax is incorrect.
INFO 2022/09/25 12:53:13 postcss: ←[31mInput Error: Did not receive any STDIN←[39m
Error: Error building site: POSTCSS: failed to transform "css/custom.css" (text/css): The filename, directory name, or volume label 
syntax is incorrect.
Input Error: Did not receive any STDIN

Which tells me that it at least is reading the file at some point. But I’ve simplified all the file paths, installed all node module dependencies locally into the project root, have all the package.json and postcss.config.js files along with the config.toml and head.html requirements. What the heck!

On Windows, in the root of the C: drive…

git clone --recurse-submodules https://github.com/anakinsleftleg/hugo_plain _plain
cd _plain
git checkout help2/postcss
npm install
hugo

No errors.

That’s what I feared. Any ideas about how to diagnose?

Is there a way to run PostCSS or PurgeCSS independently in the CLI to help pinpoint the issue?

I appreciate you trying out the repo but unfortunately it doesn’t get me closer to a fix and i have no idea what to try.

What happens when you do exactly what I did?

cd c:
git clone --recurse-submodules https://github.com/anakinsleftleg/hugo_plain _plain
cd _plain
git checkout help2/postcss
npm install
hugo

doing as you did I get:

$ hugo
Start building sites …
hugo v0.103.0-beebf2afb09a7be36cf12bdec8a99ae9286504e2+extended windows/amd64 BuildDate=2022-09-15T16:23:56Z VendorInfo=
gohugoio
Error: Error building site: POSTCSS: failed to transform "css/custom.css" (text/css): The filename, directory name, or volume label syntax is incorrect.
Total in 1443 ms

I even completely uninstalled node, reinstalled the LTS version. Same damn issue.

Is this a vanilla Windows environment, or are you using WSL, WSL2, or docker?

consolidating replies

Vanilla Windows 10


if I install purgecss directly

npm install -g purgecss

And run:

$ purgecss --css public/css/custom.css --content hugo_stats.json --output public/css/build/

It works. The output is custom.css file that only has rules of tags listed in the stats. This is of course not ideal or really workable due to the hugo pipes processing and fingerprinting.


I have done a little more experimentation to attempt to isolate the problem. No solution yet but I’m wondering if it has something to do with Hugo (which I understand would be strange given that it worked for you) or a path or something.

  • I moved the hugo.exe directly into the C:\_plain project root wondering if there was some issue with where it was that cause PostCSS to error out. No change.
  • I ran npm install cssnano to install it locally and added it to my postcss.config.js to see if the command line postcss would work. I ran it as npx postcss assets/css/custom.css > public/css/custom2.css and it populated the output with the minified css.
  • Then I added back the suggested Hugo install config for purgecss in the postcss.config.js along with the cssnano and 1. changed ".\hugo_stats.json" to "\hugo_stats.json" and 2. removed the conditional on the purgecss call:
const purgecss = require("@fullhuman/postcss-purgecss")({
  content: ["\hugo_stats.json"],
  defaultExtractor: (content) => {
    const els = JSON.parse(content).htmlElements;
    return [...(els.tags || []), ...(els.classes || []), ...(els.ids || [])];
  },
  safelist: [],
});

module.exports = {
  plugins: [
    ...([purgecss]),
    require('cssnano')({
      preset: 'default',
    })
  ],
};

So when I now run npx postcss assets/css/custom.css > public/css/custom2.css it purges anything not in the hugo_stats.json and then minifies it. So this bit works which means that PostCSS via node does work when run alone.

Which is why it now feels like there is some Hugo relationship for why the PostCSS run via hugo fails. Maybe not but given the troubleshooting, I don’t see any other relationships. And it’s definitely looking like it’s something with my computer but I don’t have any idea what it could be or how to figure it out. My computer runs absolutely great and hasn’t had issues like that before. All my system environment paths seem fine.

I ran @jmooring pasted command process in my kids Win10 computer and it works. The output css is purged and everything. So what the hell.

@bep, is there anything in the PostCSS code in Hugo extended that would be sensitive or dependent on executable path (in windows) or some flow down of node paths or dependency paths?

Someone out there is my Obi-wan Kenobi because I need help and you’re my only hope.


Quick Tangent: Why do the hugo doc instructions suggest putting the resources.PostCSS call in the template but outside of the if hugo.isProduction conditional where the resources.PostProcess call is? Shouldn’t they be together? Why would you want to run PostCSS in development mode without also using PostProcess?

So definitely something in your environment. Just out of curiosity, when was the last time you rebooted your machine?

Hadn’t been in a while but I rebooted now along with some updates and still it has the exact same error.

I see there is this issue but given then we’ve run 1. on different computers and it has worked elsewhere and 2. i’m running from a folder in the root of the drive, it doesn’t seem to be strictly related. I just can’t think of what to do and a full system fresh install is just… not really an option.

I’ve made a little work around, since I don’t want to do a fresh install of windows just for PostCSS. I’m running an instance of WSL1 with node and hugo installed. I run it on the project root in the windows filesystem (via the /mnt/ path). It works pretty well it seems. No issues with PostCSS, and there are even spaces in my windows project path.

One strange thing is when I run the server in production mode (where it will purge and minify and postprocess), when i first load the page it seems to fail at building the css or fail at providing a correct reference to it. Every page is like this. I have to make a change, or just resave a file in the watched project and then Hugo rebuilds and then the css is loaded correctly. But you have to do this for every page. Very strange. I know @bep has said that PostCSS/PostProcess running in server mode could be troublesome. Maybe this is part of that.

One other slight drawback running via WSL1 is that when i make a change to a config file, the server build errors out. But a restart of the server will build it fine. Don’t really have this issue running Hugo on windows but then again, I cant’ run PostCSS in windows on my computer.

But i have moved all the PostCSS stuff into isProduction code so I can still use my normal workflow with windows hugo binary and if i ever need to locally check a production build, then i can do it via WSL1.

You can always use a CLI script instead of API config.

Here is my dev script without writeStats or API:

hugo && purgecss --css assets/css/material.css --content public/**/*.html --output assets/css/material-purge.css --safelist extra-class extra-class2 close collapse

Then my asset material-purge.css is imported in my style.scsswhich can then use Pipes ({{ $sass = resources.Get "sass/style.scss" | toCSS | postCSS | minify | fingerprint }})

I’m assuming you’re using WSL1 just so you can use the same project folder in both Windows and WSL? I wonder if the missing system calls in WSL1 are causing the problem with the config file changes.

No that was actually a bug in Hugo, which has since been updated. It works fine now. And yes, that’s why I’m using WSL1.

1 Like