Skip to content

feat: purge CSS by default, safely (production purge + guarded default flip)#2052

Merged
markdumay merged 3 commits into
mainfrom
styles/s2-defer-purge-flip
Jul 17, 2026
Merged

feat: purge CSS by default, safely (production purge + guarded default flip)#2052
markdumay merged 3 commits into
mainfrom
styles/s2-defer-purge-flip

Conversation

@markdumay

Copy link
Copy Markdown
Collaborator

What

Flips the theme default to style.purge = true and makes purging safe in every environment.

  • Production purges correctly. css.PostCSS executes inside resources.PostProcess — after
    every page has rendered — so PurgeCSS reads a complete hugo_stats.json. This is Hugo's own
    documented purge pattern; it already worked, this PR just makes it the default.
  • Development serves unpurged CSS. Under hugo server, resources.PostProcess does not run
    and the stats are incomplete, so purging there would drop rules against partial stats. Instead
    dev ships the unpurged CSS (every class present). This structurally removes the dev-server
    purge-poisoning failure class
    (the 2026-07-14 issue) — dev never purges, so there is nothing
    to poison.
  • Guarded flip. When style.purge is on but the site has no config/postcss.config.js,
    purge is skipped with an actionable warn-purge-postcss warning rather than a failure.
  • Stop committing hugo_stats.json (root + exampleSite) and gitignore it. build.buildStats
    still regenerates it each build.

Heads-up for review

Evidence (exampleSite, hugo --gc --minify)

  • purge-ON byte-identical to prior output (run-vs-run deterministic); purge-OFF equals the
    unpurged baseline (575,913 B).
  • Combined S1+S2+S3: green, 257,473 B; selector audit 0 over-purges (ancestor-aware).
  • Component smoke: modal/dropdown/carousel/offcanvas/accordion/tabs/toast/tooltip/popover survive
    in main.css; all datatable-* survive in the module bundle; dark-mode/search/cky-/fa- present.
  • Guard: missing config → warning + unpurged, exit 0, no panic. Dev: serves unpurged, 0 ERROR.

Migration (for release notes)

Sites that relied on the old purge = false default now ship purged CSS. If a site has a stale
safelist or classes only added by JS, review config/postcss.config.js's safelist. Opt out with
style.purge = false.

Part of the styles-pipeline modernization program (slice S2). Held pending the maintainer merge gate.

…t flip)

Flip the theme default to style.purge = true and make purging safe in every
environment:

- Purge runs only in production, where css.PostCSS executes inside
  resources.PostProcess (after every page renders) so PurgeCSS reads a complete
  hugo_stats.json. This is Hugo's documented purge pattern.
- Development (hugo server, where PostProcess does not run and the stats are
  incomplete) serves the unpurged CSS — every class is present, so no rule is
  ever dropped against partial stats. This structurally removes the dev-server
  purge-poisoning failure class.
- Guard the flip: when style.purge is on but the site has no
  config/postcss.config.js, skip purging and emit an actionable warning instead
  of failing. (A config that fails at runtime still errors at post-process, as
  css.PostCSS is deferred and cannot be caught in the template.)
- Stop committing the generated hugo_stats.json (root and exampleSite) and
  gitignore it; build.buildStats still regenerates it on every build.

Migration: existing sites that relied on the previous purge=false default now
ship purged CSS. If a site has a stale safelist or custom classes only added by
JS, review the PostCSS safelist. Set style.purge = false to opt out.

exampleSite gate: purge-ON byte-identical to the prior output (run-vs-run
deterministic), purge-OFF equals the unpurged baseline, selector audit shows no
over-purges, and the component smoke (modal/dropdown/carousel/offcanvas/
datatables/dark-mode/search) survives purge.
@netlify

netlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy Preview for gethinode-demo ready!

Name Link
🔨 Latest commit f5b951c
🔍 Latest deploy log https://app.netlify.com/projects/gethinode-demo/deploys/6a5a602df90d2000088ae44d
😎 Deploy Preview https://deploy-preview-2052--gethinode-demo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@markdumay
markdumay enabled auto-merge July 17, 2026 17:08
@markdumay
markdumay merged commit 41f767a into main Jul 17, 2026
16 checks passed
@markdumay

Copy link
Copy Markdown
Collaborator Author

🎉 This PR is included in version 3.6.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@markdumay
markdumay deleted the styles/s2-defer-purge-flip branch July 17, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant