Issue 1:
I don't really know how to classify this. Maybe just something that should be documented.

I have a postcss.config.js file that returns a function (i.e takes ctx as a parameter, returns a config object). That works fine in Next.js 9.1. But in 9.2, I get this error:

Error: Your custom PostCSS configuration may not export a function. Please export a plain object instead.

at getPostCssPlugins (/path/to/node_modules/next/dist/build/webpack/config/blocks/css/plugins.js:4:296)

Looking at the code for plugin.ts, this is obviously intentional behavior. I tried to find this breaking change documented somewhere (e.g. release notes, blog posts, etc.), but didn't find anything (the pull request with the change does provide some context, but it's hard to find). I get it, new version, things change. So possibly the only resolution to this is to document it somewhere in the release notes, maybe explain why it's changed.

If it's helpful, this is what my postcss.config.js file looked like before. Granted, what I'm using ctx for is probably unnecessary (sourcemaps seem to be generated just fine using Next.js default behavior). So it's not a big deal for me to get rid of it.

module.exports = ctx => ({
map: ctx.env === 'production' ? false : {inline: true},
plugins: {
'postcss-import': {
resolve: createResolver({
alias: {
'@css': path.resolve(__dirname, 'client/style'),
'@client': path.resolve(__dirname, 'client'),
},
}),
},
'postcss-rem': {
baseline: 16,
fallback: false,
precision: 5,
},
'postcss-mixins': {},
'postcss-simple-vars': {},
'postcss-nested-ancestors': {},
'postcss-nested': {},
'postcss-custom-media': {},
'postcss-calc': {mediaQueries: true},
'postcss-preset-env': {
stage: 0,
browsers: 'last 2 versions',
},
'cssnano': {
zindex: false,
// autoprefixer is included in postcss-preset-env, so no need to do it again in nano
autoprefixer: false,
discardComments: {removeAll: true}
},
'postcss-reporter': {clearReportedMessages: true},
}
})

System information

OS: MacOS

Browser (if applies): NA

Version of Next.js: 9.2

Issue 2:
Bug report

Describe the bug

With the introduction of the marvelous Built-in CSS Support, a new non-standard PostCSS Config plugin syntax was introduced.

This syntax requires that plugins listed in postcss.config.js be strings rather than require statements. This breaks backwards compatibility and differs from the standard set by existing PostCSS documentation.

Additionally, this makes it tough (or impossible) to share a common PostCSS configuration with additional tools like Storybook.js.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

yarn add -D tailwindcss autoprefixer

Add the following postcss.config.js:

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

yarn next build

Expected behavior

The build succeeds, and either plugins imported with require() are supported

Or the build fails, and a more descriptive error is shown in the build log.

Screenshots

The following is shown when running next build:

Error: An unknown PostCSS plugin was provided (function creator() {
--
02:32:09 PM | var transformer = initializer.apply(void 0, arguments);
02:32:09 PM | transformer.postcssPlugin = name;
02:32:09 PM | transformer.postcssVersion = new _processor.default().version;
02:32:09 PM | return transformer;
02:32:09 PM | }).
02:32:09 PM | > Build error occurred

System information

OS: macOS

Version of Next.js: 9.2

Additional context

This work was likely done to be able to identify, dedupe, and acknowledge Next's default PostCSS plugins — and it's likely the solution to this issue is nothing more than better documentation.

Here are a couple proposed solutions:

1. Support require() statements in PostCSS config

I'd rely on @Timer's knowledge here, as there are likely other consequences (notably: not being able to inspect and dedupe plugins).

2. Display a warning/error that indicates deprecated behavior

This would be a simple check in packages/next/build/webpack/config/blocks/css/plugins.ts to see if the plugin is a function:

else if (typeof plugin === 'function') {
console.error(
`${chalk.red.bold(
'Error'
)}: A PostCSS Plugin must be provided as a ${chalk.bold(
'string'
)}. Instead, we got a function imported with require().`
)
}

I'm happy to submit PRs for either of these solutions! But looking for guidance from the core team.