When I setup my Next.js with support Ant Design. I can't use CSS Modules feature of Next.js
Steps to reproduce the behavior, please provide code snippets or a repository:
./components/Header.module.css 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> .appc {
| color: #fff;
| background: #16191e;
/* eslint-disable */
const withLess = require('@zeit/next-less');
const withSass = require('@zeit/next-sass');
const lessToJS = require('less-vars-to-js');
const fs = require('fs');
const path = require('path');
// Where your antd-custom.less file lives
const themeVariables = lessToJS(
fs.readFileSync(path.resolve(__dirname, './css/antd.less'), 'utf8')
);
module.exports = withSass({
cssModules: true,
...withLess({
lessLoaderOptions: {
javascriptEnabled: true,
modifyVars: themeVariables, // make your antd custom effective
importLoaders: 0
},
cssLoaderOptions: {
importLoaders: 3,
localIdentName: '[local]___[hash:base64:5]'
},
webpack: (config, { isServer }) => {
//Make Ant styles work with less
if (isServer) {
const antStyles = /antd\/.*?\/style.*?/;
const origExternals = [...config.externals];
config.externals = [
(context, request, callback) => {
if (request.match(antStyles)) return callback();
if (typeof origExternals[0] === 'function') {
origExternals[0](context, request, callback);
} else {
callback();
}
},
...(typeof origExternals[0] === 'function' ? [] : origExternals)
];
config.module.rules.unshift({
test: antStyles,
use: 'null-loader'
});
}
return config;
}
})
});
import headerStyled from '../components/Header.module.css'
export default () => {
return (
<>
<div className={headerStyled.appc}>
Hello World
</div>
</>
)
}
Can view website normally with using CSS Modules feature.

Add any other context about the problem here.
Using custom CSS plugins opts out of Next's built-in CSS modules features. In order to use them you would have to remove your CSS plugins.
@jamesmosier,
Currently, my project using Next.js with Ant Design. And I want to customize theme of Ant Design, therefore I need @zeit/next-less module to re-compile Ant Design CSS.
Is there any way to still keep built-in CSS features plus with @zeit/next-less to customize Ant Design Theme ?
I have similar problem
There is no way around this currently when you are using a custom CSS/LESS/SASS plugin with Next.
See this docs for more info: https://err.sh/next.js/built-in-css-disabled
After ask on some channels ( Stack Overflow, Medium, GitLab, ... ), Sumit Sarkar (@sumitsarkar01) was helped me config the next.config.js ,
And now, It work correctly!
@jamesmosier, could you review it for me ? Is the any way simple or official about this case ?
const withLess = require('@zeit/next-less')
const lessToJS = require('less-vars-to-js')
const withPlugins = require('next-compose-plugins')
const fs = require('fs')
const path = require('path')
const dotenv = require('dotenv')
dotenv.config()
// Where your antd-custom.less file lives
const themeVariables = lessToJS(
fs.readFileSync(path.resolve(__dirname, './css/antd.less'), 'utf8')
)
const plugins = [
[withLess({
lessLoaderOptions: {
javascriptEnabled: true,
modifyVars: themeVariables, // make your antd custom effective
},
webpack: (config, { isServer }) => {
if (isServer) {
const antStyles = /antd\/.*?\/style.*?/
const origExternals = [...config.externals]
config.externals = [
(context, request, callback) => {
if (request.match(antStyles)) return callback()
if (typeof origExternals[0] === 'function') {
origExternals[0](context, request, callback)
} else {
callback()
}
},
...(typeof origExternals[0] === 'function' ? [] : origExternals),
]
config.module.rules.unshift({
test: antStyles,
use: 'null-loader',
})
}
const builtInLoader = config.module.rules.find((rule) => {
if (rule.oneOf) {
return (
rule.oneOf.find((deepRule) => {
return deepRule.test && deepRule.test.toString().includes('/a^/');
}) !== undefined
);
}
return false;
});
if (typeof builtInLoader !== 'undefined') {
config.module.rules.push({
oneOf: [
...builtInLoader.oneOf.filter((rule) => {
return (rule.test && rule.test.toString().includes('/a^/')) !== true;
}),
],
});
}
config.resolve.alias['@'] = path.resolve(__dirname);
return config;
}
})]
]
const nextConfig = {
env: {
}
}
module.exports = withPlugins(plugins, nextConfig)
@maysam, I was updated this config to my test project, you can check it out
https://github.com/thobn24h/nextjs-with-ant
@thobn24h you are my new hero
Anytime you alter the webpack config you run the risk of something within Next breaking unintentionally. So I would certainly exercise caution with this. But glad it worked for you!
For now there is no official way to do this.
@thobn24h @maysam
https://github.com/mit123suki/next-ant-setup
This repo shows how to setup with ant without customizing the webpack. But this requires some effort for first time, refer readme for more details
you can try next-plugin-antd-less , support next.js v9.5.
@thobn24h Thankyou verymuch bro
spent last night struggling with this.
.less file without CSS module support (especially for third party libs like Ant Design) at the same time I want to use CSS Module for my own style files like **.module.lessnpm i @zeit/next-css @zeit/next-less less
*@zeit/next-less is mainly for the less-loader, you can install it youself, but should adjust the the structure of lessLoaderOptions that pass down to it based on the version of less-loader you use.
creating a new next-less.config.js:
const cssLoaderConfig = require('@zeit/next-css/css-loader-config')
module.exports = (nextConfig = {}) => {
return Object.assign({}, nextConfig, {
webpack(config, options) {
if (!options.defaultLoaders) {
throw new Error(
'This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade'
)
}
const { dev, isServer } = options
const {
cssLoaderOptions,
postcssLoaderOptions,
lessLoaderOptions = {}
} = nextConfig
// use Object for `test` to bypass NextJS detection
// so that it will keep CSS and SASS support.
config.module.rules.push({
test: {
and: [/\.less$/],
not: [/\.module\.less$/]
},
use: cssLoaderConfig(config, {
extensions: ['less'],
cssModules: false,
cssLoaderOptions,
postcssLoaderOptions,
dev,
isServer,
loaders: [
{
loader: 'less-loader',
options: lessLoaderOptions
}
]
})
})
config.module.rules.push({
test: /\.module\.less$/,
use: cssLoaderConfig(config, {
extensions: ['module.less'],
cssModules: true,
cssLoaderOptions,
postcssLoaderOptions,
dev,
isServer,
loaders: [
{
loader: 'less-loader',
options: lessLoaderOptions
}
]
})
})
if (typeof nextConfig.webpack === 'function') {
return nextConfig.webpack(config, options)
}
return config
}
})
}
then just use this as a new plugin:
const withLessExcludeAntd = require("./next-less.config.js");
module.exports = withLessExcludeAntd({
lessLoaderOptions: {
javascriptEnabled: true,
}
})
A little break down here:
.module.lessrule.test in my first less rule, which will bypass the NextJS detection, and my second rule.test /\.module\.less$\ will bypass the detection as well.Yes, bypassing the NextJS detection is hacky, but the whole solution atm NextJS team provides for Less users are far from perfect neither.
https://github.com/mit123suki/next-ant-setup
This repo shows how to setup with ant without customizing the webpack. But this requires some effort for first time, refer readme for more details
I used a similar approach but only @import './../node_modules/antd/lib/style/index.less'; at the global level and only import more when I have added the ANTD component. So far it works OK.
If anyone is still struggling with this, i managed to get it working with @zeit/next-css, here is the config:
module.exports = withPlugins(
[
[
withCSS,
{
postcssLoaderOptions: {
parser: true,
},
cssModules: true,
cssLoaderOptions: {
importLoaders: 2,
localIdentName: "[local]___[hash:base64:5]",
sourceMap: true,
getLocalIdent: (context, localIdentName, localName, options) => {
const hz = context.resourcePath.replace(context.rootContext, "");
if (/node_modules/.test(hz)) {
return localName;
} else {
return cssLoaderGetLocalIdent(
context,
localIdentName,
localName,
options
);
}
},
},
},
],
[
withLess,
{
lessLoaderOptions: {
javascriptEnabled: true,
modifyVars: themeVariables,
},
},
],
],
nextConfig
);
spent last night struggling with this.
Key Points
- NextJS does not have built-in LESS support, see this issue to see why #11584
- NextJS will disable the CSS/SASS built in support by default if any other css custom config is detected (see the source code here about how exactly they detect the config):
- The @zeit/next-css and @zeit/next-less are all quite outdated (next-less uses next-less). They are using [email protected]. So basically the configs we built using next-less and next-css will be probably quite different from the NextJS builtin config. I do prefer to keep the built in CSS/SASS support while having extra LESS support
- personally for me, I want to be able to compile
.lessfile without CSS module support (especially for third party libs like Ant Design) at the same time I want to use CSS Module for my own style files like**.module.lessMy solution:
npm i @zeit/next-css @zeit/next-less less*@zeit/next-less is mainly for the
less-loader, you can install it youself, but should adjust the the structure oflessLoaderOptionsthat pass down to it based on the version of less-loader you use.creating a new
next-less.config.js:const cssLoaderConfig = require('@zeit/next-css/css-loader-config') module.exports = (nextConfig = {}) => { return Object.assign({}, nextConfig, { webpack(config, options) { if (!options.defaultLoaders) { throw new Error( 'This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade' ) } const { dev, isServer } = options const { cssLoaderOptions, postcssLoaderOptions, lessLoaderOptions = {} } = nextConfig // use Object for `test` to bypass NextJS detection // so that it will keep CSS and SASS support. config.module.rules.push({ test: { and: [/\.less$/], not: [/\.module\.less$/] }, use: cssLoaderConfig(config, { extensions: ['less'], cssModules: false, cssLoaderOptions, postcssLoaderOptions, dev, isServer, loaders: [ { loader: 'less-loader', options: lessLoaderOptions } ] }) }) config.module.rules.push({ test: /\.module\.less$/, use: cssLoaderConfig(config, { extensions: ['module.less'], cssModules: true, cssLoaderOptions, postcssLoaderOptions, dev, isServer, loaders: [ { loader: 'less-loader', options: lessLoaderOptions } ] }) }) if (typeof nextConfig.webpack === 'function') { return nextConfig.webpack(config, options) } return config } }) }then just use this as a new plugin:
const withLessExcludeAntd = require("./next-less.config.js"); module.exports = withLessExcludeAntd({ lessLoaderOptions: { javascriptEnabled: true, } })A little break down here:
- I added two rules so that css module will only be enabled when you use
.module.less- I used the object format for
rule.testin my first less rule, which will bypass the NextJS detection, and my second rule.test/\.module\.less$\will bypass the detection as well.Is It Hacky?
Yes, bypassing the NextJS detection is hacky, but the whole solution atm NextJS team provides for Less users are far from perfect neither.
So I would suggest anyone who cares about using Less UPVOTE this issue
The custom styles are not updated when using route jumps by next/router, the page must be refreshed to work properly
Most helpful comment
After ask on some channels ( Stack Overflow, Medium, GitLab, ... ), Sumit Sarkar (@sumitsarkar01) was helped me config the next.config.js ,
And now, It work correctly!
@jamesmosier, could you review it for me ? Is the any way simple or official about this case ?
@maysam, I was updated this config to my test project, you can check it out
https://github.com/thobn24h/nextjs-with-ant