Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid PostCSS Plugin found using TailwindCSS 4 and Vitest

I have a Next.js app that is running without any errors. However, I am using Vitest for my testing framework and when running a specific test (layout.test.tsx) it produces this error:

 FAIL  src/app/__tests__/layout.test.tsx [ src/app/__tests__/layout.test.tsx ]
Failed to load PostCSS config: Failed to load PostCSS config (searchPath: /Users/joe/my-app): [TypeError] Invalid PostCSS Plugin found at: plugins[0]

(@/Users/joe/my-app/postcss.config.mjs)
TypeError: Invalid PostCSS Plugin found at: plugins[0]

(@/Users/joe/my-app/postcss.config.mjs)
    at file:///Users/joe/my-app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:11827:15
    at Array.forEach (<anonymous>)
    at plugins (file:///Users/joe/my-app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:11809:10)
    at processResult (file:///Users/joe/my-app/node_modules/vite/dist/node/chunks/dep-DBxKXgDP.js:11876:20)
  Plugin: vite:css
  File: /Users/joe/my-app/src/app/globals.css

I have no idea what is causing this error and have search all over the internet and followed various suggestions. Here are some of the key files of the project:

postcss.config.mjs

const config = {
  plugins: ["@tailwindcss/postcss"],
};

export default config;

vitest.config.mjs

import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
  plugins: [tsconfigPaths(), react()],
  test: {
    environment: "jsdom",
    globals: true,
    setupFiles: "./vitest.setup.mjs",
  },
});

global.css

@import "tailwindcss";

:root {
  --background: #ffffff;
  --foreground: #171717;
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --font-sans: var(--font-geist-sans);
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
  }
}

body {
  background: var(--background);
  color: var(--foreground);
  font-family: Arial, Helvetica, sans-serif;
}

layout.tsx

import type { Metadata } from "next";
import { Geist } from "next/font/google";
import "./globals.css";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={`${geistSans.variable} antialiased`}>{children}</body>
    </html>
  );
}

layout.test.tsx

import { render, screen } from "@testing-library/react";
import RootLayout from "../layout";

describe("<RootLayout />", () => {
  describe("WHEN the component is rendered", () => {
    beforeEach(() => {
      render(
        <RootLayout>
          <div>Some content</div>
        </RootLayout>,
      );
    });

    test("THEN the child component is displayed", () => {
      const content = screen.getByText("Some content");
      expect(content).toBeVisible();
    });
  });
});
like image 802
JoeTidee Avatar asked May 11 '26 13:05

JoeTidee


1 Answers

Your PostCSS configuration is incorrect. It seems that in one of Next.js's pull requests, they fixed the PostCSS configuration in one of their Tailwind templates according to the response, but not all templates have been updated.

  • Nextjs-Vite broken in fresh install (storybook #30878)
  • PR #77376 - fix: Use standard PostCSS configuration in create-next-app format for ecosystem compatibility - merged
    • app-tw-empty/js fixed
    • app-tw-empty/ts fixed
    • app-tw/js not fixed (fixed via PR #79949)
    • app-tw/ts not fixed (fixed via PR #79949) - If I had to guess, this is probably what you used.
  • PR #79949 - Fix remaining PostCSS config issues (follow-up to #77376) - merged
    • app-tw/js fixed
    • app-tw/ts fixed

PostCSS Configuration

If plugins is an array, it expects functions.

postcss.config.mjs

import tailwind from "@tailwindcss/postcss";

const config = {
  plugins: [
    tailwind(),
  ],
};

export default config;

If it is an object, the key defines the plugin, and additional options can be passed like this:

postcss.config.mjs

const config = {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

export default config;

Extra note: For TailwindCSS v4, it's important to use .mjs. Also, make sure your project is set to module type in the package.json.

Alternative

If the postcss.config.mjs feels like a burden, you can also declare it in your package.json:

{
  "postcss": {
    "plugins": {
      "@tailwindcss/postcss": {}
    }
  }
}
like image 159
rozsazoltan Avatar answered May 13 '26 04:05

rozsazoltan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!