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-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 }) }
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-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 }) }
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-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 }) }
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-plugins
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" }, ...
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
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 };
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-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 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-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 }) }
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

