2021-11-11

Next.js local postcss plugin

postcss, nextjs, plugin

banner

Image by Dragon77 from Pixabay

Introduction

While loading a custom local PostCSS plugin for Next.js, I ran into the following error.

Error: A PostCSS Plugin was passed as a function using require(), but it must be provided as a string.
Read more: https://nextjs.org/docs/messages/postcss-shape
Error: Malformed PostCSS Configuration

Next.js requires an object-based form for postcss plugins.

e.g.) So, instead of

1module.exports = {2  plugins: [require("tailwindcss"), require("autoprefixer")],3};

You have to use

1module.exports = {2  plugins: {3    tailwindcss: {},4    autoprefixer: {},5  },6};

If you created a plugin in the root of next.js project, postcss-my-plugin,
you have no choice but to use require('postcss-my-plugin') in the plugins array.

Now you are stuck because your custom plugin cannot be "resolved" by the name.
Note that I double quoted "resolved"

Solution

The link, https://nextjs.org/docs/messages/postcss-shape, in the error message doesn't provide the solution.
And @Timer provided an answer on GitHub for resolving the issue.

1// If you want to use other PostCSS plugins, see the following:2// https://tailwindcss.com/docs/using-with-preprocessors3module.exports = {4  plugins: [5    require.resolve("./postcss-tailwindcss-group"),6    require.resolve("tailwindcss"),7    require.resolve("autoprefixer"),8  ],9};

Now the plugin can be resolved by the name with require.resolve.

Should you need to pass an option to the plugin, you can pass an array of require.resolve and options.

1module.exports = {2  plugins: [3    require.resolve("./postcss-tailwindcss-group"),4    require.resolve("tailwindcss"),5    require.resolve("autoprefixer"),6    // 👇7    [require.resolve("postcss-preset-env")], { stage: 3 }],8  ],9};