next-compose-plugins
next-compose-plugins copied to clipboard
Incompatible with next.js 12.2.0: "Invalid next.config.js options detected"
When compiling with next.js 12.2.0, this warning is shown, even when an empty array is passed for the plugins parameter:
warn - Invalid next.config.js options detected:
[
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "webpackDevMiddleware"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "configOrigin"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "target"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "analyticsId"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "webpack5"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "/amp/canonicalBase",
"schemaPath": "#/properties/amp/properties/canonicalBase/minLength",
"keyword": "minLength",
"params": {
"limit": 1
},
"message": "must NOT have fewer than 1 characters"
},
{
"instancePath": "/basePath",
"schemaPath": "#/properties/basePath/minLength",
"keyword": "minLength",
"params": {
"limit": 1
},
"message": "must NOT have fewer than 1 characters"
},
{
"instancePath": "/generateEtags",
"schemaPath": "#/properties/generateEtags/isFunction",
"keyword": "isFunction",
"params": {},
"message": "must pass \"isFunction\" keyword validation"
},
{
"instancePath": "/i18n",
"schemaPath": "#/properties/i18n/type",
"keyword": "type",
"params": {
"type": "object"
},
"message": "must be object"
},
{
"instancePath": "/webpack",
"schemaPath": "#/properties/webpack/isFunction",
"keyword": "isFunction",
"params": {},
"message": "must pass \"isFunction\" keyword validation"
}
]
I am using next-compose-plugins with next-pwa, @sentry/nextjs and @next/bundle-analyzer and I get similar warnings
const nextPlugins = [
[withBundleAnalyzer],
[
withPWA,
{
pwa: {
dest: 'public',
register: true,
skipWaiting: true,
disable: process.env.NODE_ENV === 'development',
buildExcludes: [/middleware-manifest.json$/],
},
},
],
(nextConfig) => withSentryConfig(nextConfig, sentryWebpackPluginOptions),
];
...
module.exports = withPlugins(nextPlugins, nextConfig);
I ditched next-compose-plugins since it's unmaintained and replaced it with these lines:
module.exports = (_phase, { defaultConfig }) => {
const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack]
return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config })
}
I ditched
next-compose-pluginssince it's unmaintained and replaced it with these lines:module.exports = (_phase, { defaultConfig }) => { const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack] return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config }) }
How would you use the extend feature with your method? I have a ton of redirects so I put them in their own separate config file.
Just spread them too.
I ditched
next-compose-pluginssince it's unmaintained and replaced it with these lines:module.exports = (_phase, { defaultConfig }) => { const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack] return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config }) }
Hey @fabb... using your example, I see the same warning message:
warn - Invalid next.config.js options detected:
[
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "webpackDevMiddleware"
},
"message": "must NOT have additional properties"
},
...
For me the warnings are gone, so I guess one of your plugins or your config sets webpackDevMiddleware etc. somewhere?
module.exports = (_phase, { defaultConfig }) => { const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack] return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config }) }
Strange... i am just using the withBundleAnalyzer plugin for now.
In my tests I tried this code below:
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = (_phase, { defaultConfig }) => {
const plugins = [withBundleAnalyzer]
return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...nextConfig })
}
related issue https://github.com/vercel/next.js/issues/38909
I ditched
next-compose-pluginssince it's unmaintained and replaced it with these lines:module.exports = (_phase, { defaultConfig }) => { const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack] return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config }) }
why i got like this

with config
const withPWA = require('next-pwa');
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: false,
swcMinify: true,
compiler: {
removeConsole: true,
},
};
module.exports = (_phase, { defaultConfig }) => {
const plugins = [
withPWA({
pwa: {
dest: 'public',
disable: process.env.NODE_ENV === 'development',
register: true,
},
}),
];
return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...nextConfig });
};
I don't understand, I don't have webpack customisations but I get lots of warnings:
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
};
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
const withMDX = require('@next/mdx')({
extension: /\.mdx?$/,
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'mdx'],
});
const plugins = [withBundleAnalyzer, withMDX];
module.exports = (_phase, { defaultConfig }) => {
const finalConfig = { ...defaultConfig, config };
plugins.forEach(plugin => plugin(finalConfig));
return finalConfig;
}
Next yells about:
$ next dev -p 80
ready - started server on 0.0.0.0:80, url: http://localhost:80
info - Loaded env from /Users/damians/Desktop/webapp/.env
warn - Invalid next.config.js options detected:
[
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "webpackDevMiddleware"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "configOrigin"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "target"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "analyticsId"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "webpack5"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "",
"schemaPath": "#/additionalProperties",
"keyword": "additionalProperties",
"params": {
"additionalProperty": "config"
},
"message": "must NOT have additional properties"
},
{
"instancePath": "/amp/canonicalBase",
"schemaPath": "#/properties/amp/properties/canonicalBase/minLength",
"keyword": "minLength",
"params": {
"limit": 1
},
"message": "must NOT have fewer than 1 characters"
},
{
"instancePath": "/assetPrefix",
"schemaPath": "#/properties/assetPrefix/minLength",
"keyword": "minLength",
"params": {
"limit": 1
},
"message": "must NOT have fewer than 1 characters"
},
{
"instancePath": "/basePath",
"schemaPath": "#/properties/basePath/minLength",
"keyword": "minLength",
"params": {
"limit": 1
},
"message": "must NOT have fewer than 1 characters"
},
{
"instancePath": "/experimental/outputFileTracingRoot",
"schemaPath": "#/properties/experimental/properties/outputFileTracingRoot/minLength",
"keyword": "minLength",
"params": {
"limit": 1
},
"message": "must NOT have fewer than 1 characters"
},
{
"instancePath": "/generateEtags",
"schemaPath": "#/properties/generateEtags/isFunction",
"keyword": "isFunction",
"params": {},
"message": "must pass \"isFunction\" keyword validation"
},
{
"instancePath": "/i18n",
"schemaPath": "#/properties/i18n/type",
"keyword": "type",
"params": {
"type": "object"
},
"message": "must be object"
},
{
"instancePath": "/webpack",
"schemaPath": "#/properties/webpack/isFunction",
"keyword": "isFunction",
"params": {},
"message": "must pass \"isFunction\" keyword validation"
}
]
See more info here: https://nextjs.org/docs/messages/invalid-next-config
i got fixing config next-pwa (v 5.5.5) with this config
const withPWA = require('next-pwa');
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
compiler: {
removeConsole: process.env.NODE_ENV !== 'development',
},
pwa: {
dest: 'public',
disable: process.env.NODE_ENV === 'development',
register: true,
},
};
module.exports = () => {
const plugins = [withPWA];
const config = plugins.reduce((acc, next) => next(acc), {
...nextConfig,
});
return config;
};
but i go twice print [PWA] Compile server like this

or [PWA] PWA support is disabled

I ditched since it's unmaintained and replaced it with these lines:
next-compose-pluginsmodule.exports = (_phase, { defaultConfig }) => { const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack] return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config }) }Hey @fabb... using your example, I see the same warning message:
warn - Invalid next.config.js options detected: [ { "instancePath": "", "schemaPath": "#/additionalProperties", "keyword": "additionalProperties", "params": { "additionalProperty": "webpackDevMiddleware" }, "message": "must NOT have additional properties" }, ...
I faced the same problem, but it worked fine by removing defaultConfig.
/** @type {import('next').NextConfig} */
const nextConfig = {
// ...
};
module.exports = (_phase, { defaultConfig }) => {
const plugins = [/* ... */]
return plugins.reduce((acc, plugin) => plugin(acc), { ...nextConfig })
}
Just ignore default config. Seems, its NextJS related issue.
Even using defaultConfig as is throws an error:
module.exports = async (phase, { defaultConfig }) => {
return defaultConfig
};
Hence, its not a next-compose-plugins package error.
So, as a workaround, use it like below (just ignore defaultConfig existence):
module.exports = async (phase) => {
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true
};
const defaultConfig = {}
return withPlugins([], nextConfig)(phase, { defaultConfig });
// return withPlugins([], nextConfig)(phase, { undefined }); // also works
};
For anyone who switched to @gendaineko2222's suggested solution (like I did) and ran into a TypeError: plugin is not a function when passing a plugin as an array with some plugin-specific configuration (as outline here: https://github.com/cyrilwanner/next-compose-plugins/#configuration-object), this is the change that I had to make to handle that case:
module.exports = (_phase, { defaultConfig }) => {
return plugins.reduce(
(acc, plugin) => {
if (Array.isArray(plugin)) {
return plugin[0](acc, plugin[1]);
}
return plugin(acc);
},
{ ...nextConfig }
);
};
For anyone looking for a full next.config.js solution that removes the warnings, here's what I use:
/* eslint-disable @typescript-eslint/no-var-requires */
const CircularDependencyPlugin = require('circular-dependency-plugin')
const withPWA = require('next-pwa')({
dest: 'public',
disable: process.env.NODE_ENV === 'development',
})
const plugins = []
if (process.env.ANALYZE === 'true') {
// only load dependency if env `ANALYZE` was set
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: true,
})
plugins.push(withBundleAnalyzer)
}
plugins.push(withPWA)
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
webpack: (config) => {
config.plugins.push(
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/,
include: /src/,
failOnError: true,
allowAsyncCycles: false,
cwd: process.cwd(),
}),
)
return config
},
}
module.exports = () => plugins.reduce((acc, next) => next(acc), nextConfig)
module.exports = () => { const plugins = [withPWA]; const config = plugins.reduce((acc, next) => next(acc), { ...nextConfig, }); return config; };
This work for me
Just ignore default config. Seems, its NextJS related issue.
Even using
defaultConfigas is throws an error:module.exports = async (phase, { defaultConfig }) => { return defaultConfig };Hence, its not a
next-compose-pluginspackage error.So, as a workaround, use it like below (just ignore defaultConfig existence):
module.exports = async (phase) => { /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, swcMinify: true }; const defaultConfig = {} return withPlugins([], nextConfig)(phase, { defaultConfig }); // return withPlugins([], nextConfig)(phase, { undefined }); // also works };
What you can do instead is:
import nextComposePlugins from 'next-compose-plugins'
const { withPlugins } = nextComposePlugins.extend(() => ({}))
and then as before
const config = withPlugins(
[...],
nextConfig
)
export default config
I ditched
next-compose-pluginssince it's unmaintained and replaced it with these lines:module.exports = (_phase, { defaultConfig }) => { const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack] return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config }) }
I was still seeing the warnings after this change because of what was in defaultConfig. This workaround resolved them for me, and still maintained the defaultConfig usage. Still seeing the warning about .assetPrefix as it errors if you remove the field.
module.exports = (_phase, { defaultConfig }) => {
// Workaround
delete defaultConfig.webpackDevMiddleware;
delete defaultConfig.configOrigin;
delete defaultConfig.target;
delete defaultConfig.webpack5;
delete defaultConfig.amp.canonicalBase;
delete defaultConfig.experimental.outputFileTracingRoot;
delete defaultConfig.i18n;
const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack]
return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config })
}
Related issue: https://github.com/vercel/next.js/issues/39161
Used Fix: @meiblorn @comment.
From:
const withPlugins = require('next-compose-plugins');
const nextTranslate = require('next-translate');
const nextConfig = {
reactStrictMode: true,
};
module.exports = withPlugins([[nextTranslate]], nextConfig);
To:
const withPlugins = require('next-compose-plugins');
const nextTranslate = require('next-translate');
const nextConfig = {
reactStrictMode: true,
};
module.exports = async (phase) => withPlugins([nextTranslate], nextConfig)(phase, { undefined });
If you want to keep the default config you could do the following:
module.exports = async (phase, { defaultConfig }) =>
withPlugins([nextTranslate], nextConfig)(phase, { ...defaultConfig, ...nextConfig });
I think all of the codes above make the things complex, you can just use one reduce line for composing all the plugins.
const bundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true'
});
const nextTranslate = require('next-translate');
// Compose all the plugins one by one.
const plugins = [bundleAnalyzer, nextTranslate];
/** @type {import('next').NextConfig} */
const bookstairsConfig = {
reactStrictMode: true,
};
module.exports = plugins.reduce((config, plugin) => plugin(config), bookstairsConfig)
I think all of the codes above make the things complex, you can just use one reduce line for composing all the plugins.
const bundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true' }); const nextTranslate = require('next-translate'); // Compose all the plugins one by one. const plugins = [bundleAnalyzer, nextTranslate]; /** @type {import('next').NextConfig} */ const bookstairsConfig = { reactStrictMode: true, }; module.exports = plugins.reduce((config, plugin) => plugin(config), bookstairsConfig)
it keeps telling me TypeError : plugin is not a function
I'm using next-pwa, @sentry/nextjs and @next/bundle-analyzer and completely removed next-compose-plugins. No warnings and works with @sentry/nextjs
const {PHASE_PRODUCTION_BUILD} = require('next/constants');
/** @type {import('next').NextConfig} */
const nextConfig = {
// your config
}
};
module.exports = phase => {
const plugins = [];
if (phase === PHASE_PRODUCTION_BUILD) {
if (process.env.ANALYZE === '1') {
plugins.push(
require('@next/bundle-analyzer')({
enabled: true
}),
);
}
plugins.push(
require('next-pwa')({
// your config
}),
);
plugins.push(nextConfig =>
require('@sentry/nextjs').withSentryConfig(
{
...nextConfig,
sentry: {
// your config
},
},
{silent: true},
)(phase, {nextConfig}),
);
}
return plugins.reduce((acc, plugin) => plugin(acc), nextConfig);
};
I'm using next-pwa, @sentry/nextjs and @next/bundle-analyzer . Did this without next-compose-plugins
module.exports = withSentryConfig(withPWA(withBundleAnalyzer(yourNextConfig)), { silent: true });
Works fine 👍🏻
I ditched
next-compose-pluginssince it's unmaintained and replaced it with these lines:module.exports = (_phase, { defaultConfig }) => { const plugins = [withStaticImport, withBundleAnalyzer, withCustomWebpack] return plugins.reduce((acc, plugin) => plugin(acc), { ...defaultConfig, ...config }) }
For those using the .reduce() strategy, please be aware that the return value of plugin(acc) isn't always a function (depending on the plugin you use: https://github.com/getsentry/sentry-javascript/issues/6447#issuecomment-1340671081
I'd suggest the following edit:
const bundleAnalyzer = require(https://github.com/vercel/next.js/tree/master/packages/next-bundle-analyzer)({
enabled: process.env.ANALYZE === 'true'
});
module.exports = (phase, defaultConfig) => {
const plugins = [
// other plugins
bundleAnalyzer,
(config) => withSentryConfig(config, sentryWebpackPluginOptions),
// other plugins
];
const config = plugins.reduce((acc, plugin) => {
const update = plugin(acc);
return typeof update === "function" ? update(phase, defaultConfig) : update;
}, { ...nextConfig });
return config;
};
I have the same issue, but i cannot find out anything about target