Skip to content

ESM resolver fails for postcss.config.js files which are located in a theme #13987

@schnerring

Description

@schnerring

What version of Hugo are you using (hugo version)?

$ hugo version
hugo v0.150.0-3f5473b7d4e7377e807290c3acc89feeef1aaa71+extended windows/amd64 BuildDate=2025-09-08T13:01:12Z VendorInfo=gohugoio

Does this issue reproduce with the latest release?

yes

The PurgeCSS v7 release requries the following breaking change (migrating from CJS to MJS)

import { purgeCSSPlugin } from '@fullhuman/postcss-purgecss';

I successfully migrated my theme's postcss.config.js:

import path from "path";
import postcssImport from "postcss-import";
import postcssUrl from "postcss-url";
import postcssNesting from "postcss-nesting";
import postcssCustomMedia from "postcss-custom-media";
import postcssPresetEnv from "postcss-preset-env";
import cssnano from "cssnano";
import { purgeCSSPlugin } from "@fullhuman/postcss-purgecss";

export default {
  plugins: [
    postcssImport({
      path: [
        // Check for imports in <theme-dir>/css/assets
        // TODO use Hugo's built-in inlineImports?
        path.posix.join(import.meta.dirname, "assets", "css"),
      ],
    }),
    postcssUrl([
      {
        filter: "**/typeface-*/files/*",
        url: (asset) => {
          // Construct font path relative to <publish-dir>/css/bundle.css
          // Fonts must be mounted into static/ dir
          return path.posix.join("/", "fonts", path.basename(asset.pathname));
        },
      },
    ]),
    postcssNesting,
    postcssCustomMedia,
    ...(process.env.HUGO_ENVIRONMENT === "production"
      ? [
          postcssPresetEnv,
          cssnano,
          purgeCSSPlugin({
            content: ["./hugo_stats.json"],
            defaultExtractor: (content) => {
              let els = JSON.parse(content).htmlElements;
              return els.tags.concat(els.classes, els.ids);
            },
            safelist: ["data-theme"],
          }),
        ]
      : []),
  ],
};

Running hugo works fine within the theme context. However, as soon as I load the theme as a module, hugo's ESM resolver fails with the following error:

Error: error building site: POSTCSS: failed to transform "/." (application/octet-stream): Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'postcss-import' imported from C:\Users\Me\AppData\Local\hugo_cache\modules\filecache\modules\pkg\mod\github.com\schnerring\hugo-theme-gruvbox@v0.0.0-20250916195141-44d3016d746b\postcss.config.js
Did you mean to import "postcss-import/index.js"?
    at Object.getPackageJSONURL (node:internal/modules/package_json_reader:268:9)
    at packageResolve (node:internal/modules/esm/resolve:768:81)
    at moduleResolve (node:internal/modules/esm/resolve:854:18)
    at defaultResolve (node:internal/modules/esm/resolve:984:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:685:12)
    at #cachedDefaultResolve (node:internal/modules/esm/loader:634:25)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:617:38)
    at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:273:38)
    at ModuleJob._link (node:internal/modules/esm/module_job:135:49) {
  code: 'ERR_MODULE_NOT_FOUND'
}

The module resolver probably tries looking for the PostCSS modules in %LOCALAPPDATA%\hugo_cache\modules\filecache\modules\pkg\mod\github.com\schnerring\hugo-theme-gruvbox@v0.0.0-20250916195141-44d3016d746b\node_modules.

Using a replace directive for the the module, which points to a local directory and running npm install inside fixes the issue.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions