I have multiple pages on my NextJS project and the react framework I used is Ant Design V5. The problem is only one pages has working styles but Ant or NextJS is not injecting/matching the styles on other pages properly. I tried the official document and the examples from the Ant GitHub repository but neither of them worked for me.
The questions are:
isolated-ant-bug
pages/_app.tsx
import { FC } from 'react'
import { AppProps } from 'next/app'
import { ConfigProvider } from 'antd'
import '../styles/globals.css'
import 'typeface-rubik/index.css'
const MyApp: FC<AppProps> = ({ Component, pageProps }) => (
<ConfigProvider
theme={{
token: {
fontFamily: '"Rubik", sans-serif',
}
}}
>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<Component {...pageProps} />
</ConfigProvider>
)
export default MyApp
pages/_document.tsx
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
} from "next/document";
import { StyleProvider, createCache, extractStyle } from "@ant-design/cssinjs";
const MyDocument = () => (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
MyDocument.getInitialProps = async (ctx: DocumentContext) => {
const cache = createCache();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
(
<StyleProvider cache={cache}>
<App {...props} />
</StyleProvider>
),
});
const initialProps = await Document.getInitialProps(ctx);
// 1.1 extract style which had been used
const style = extractStyle(cache, true);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{/* 1.2 inject css */}
<style dangerouslySetInnerHTML={{ __html: style }}></style>
</>
),
};
}
export default MyDocument;
pages/home.tsx
import { Button } from 'antd'
const Home = () => (
<div className="App">
<Button type="primary">Button</Button>
</div>
);
export default Home
{
"dependencies": {
"@ant-design/colors": "^5.0.1",
"@ant-design/compatible": "^5.1.1",
"@ant-design/cssinjs": "^1.13.2",
"@ant-design/icons": "^4.4.0",
"@ant-design/pro-layout": "^7.15.3",
"@fortawesome/fontawesome-free": "^5.15.2",
"@fortawesome/fontawesome-svg-core": "^1.2.34",
"@fortawesome/free-brands-svg-icons": "^5.15.2",
"@fortawesome/free-regular-svg-icons": "^5.15.2",
"@fortawesome/free-solid-svg-icons": "^5.15.2",
"@fortawesome/react-fontawesome": "^0.1.14",
"@fragaria/address-formatter": "^2.4.0",
"@next/bundle-analyzer": "^10.1.3",
"@reduxjs/toolkit": "^1.5.0",
"ahooks": "^3.7.8",
"antd": "5.x",
"axios": "^0.21.1",
"babel-plugin-import": "^1.13.3",
"color2k": "^2.0.0",
"cors": "^2.8.5",
"csv-parse": "^4.16.0",
"dotenv": "^8.2.0",
"highlight.js": "^11.2.0",
"http-status-codes": "^2.1.4",
"immer": "^8.0.1",
"isemail": "^3.2.0",
"leaflet": "^1.7.1",
"libphonenumber-js": "^1.9.19",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"next": "^12.3.4",
"next-plugin-antd-less": "^1.0.6",
"next-translate": "1.0.1",
"nominatim-browser": "^2.1.0",
"opening_hours": "^3.6.0",
"qs": "^6.9.6",
"rc-select": "^14.6.0-alpha.0",
"react": "^18.2.0",
"react-copy-to-clipboard": "^5.0.4",
"react-datepicker": "^4.12.0",
"react-dom": "^18.2.0",
"react-ionicons": "^4.2.0",
"react-leaflet": "^3.0.5",
"react-lowlight": "^2.0.0",
"react-redux": "^7.2.2",
"react-use": "^17.4.0",
"react-virtualized": "^9.22.3",
"redux": "^4.0.5",
"sqlite3": "^5.0.2",
"styled-components": "^5.2.3",
"styled-jsx": "^3.4.4",
"swr": "^0.4.0",
"title-case": "^3.0.3",
"typeface-rubik": "^1.1.13",
"valid-url": "^1.0.9"
},
"devDependencies": {
"@fortawesome/fontawesome-common-types": "^0.2.34",
"@types/jest": "^26.0.24",
"@types/leaflet": "^1.5.19",
"@types/lodash": "^4.14.168",
"@types/node": "^14.14.16",
"@types/qs": "^6.9.5",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.2",
"@types/react-redux": "^7.1.16",
"@types/react-virtualized": "^9.21.11",
"@types/valid-url": "^1.0.3",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"autoprefixer": "^10.4.4",
"eslint": "<8.0.0",
"eslint-config-airbnb": "^19.0.2",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-next": "^13.4.10",
"file-loader": "^6.2.0",
"jest": "^27.0.6",
"moment-locales-webpack-plugin": "^1.2.0",
"postcss": "^8.4.12",
"tailwindcss": "^3.0.24",
"ts-jest": "^27.0.3",
"tslib": "^2.6.0",
"typescript": "^4.4.4"
}
}
const nextTranslate = require('next-translate')
const MomentLocalesPlugin = require('moment-locales-webpack-plugin')
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
module.exports = nextTranslate(
withBundleAnalyzer({
webpack: (config, _options) => {
config.resolve.fallback = { fs: false }
config.plugins.push(
new MomentLocalesPlugin({
localesToKeep: [
'be',
'de',
'es',
'fr',
'it',
'nl',
'pt',
'ru'
],
}),
)
return config
},
redirects: async () => ([
{
source: '/maps',
destination: '/m/main',
permanent: true,
},
{
source: '/m',
destination: '/m/main',
permanent: true,
},
{
source: '/t',
destination: '/t/main',
permanent: true,
},
{
source: '/tables',
destination: '/t/main',
permanent: true,
},
{
source: '/tables/:path*',
destination: '/t/:path*',
permanent: true,
},
{
source:'/renn.html/:slug*',
destination: 'https://v0.kartevonmorgen.org/renn.html#/:slug*',
permanent: false
},
{
source:'/businesscard.html/:slug*',
destination: 'https://v0.kartevonmorgen.org/businesscard.html#/:slug*',
permanent: false
},
{
source:'/map.html/:slug*',
destination: 'https://v0.kartevonmorgen.org/map.html#/:slug*',
permanent: false
},
{
source:'/mapAndEntryList.html/:slug*',
destination: 'https://v0.kartevonmorgen.org/mapAndEntryList.html#/:slug*',
permanent: false
}
]),
i18n: {
locales: [
'be',
'de',
'en',
'es',
'fr',
'it',
'nl',
'pt',
'ru'
],
defaultLocale: 'de',
},
}),
)
/home
After many tries I found the problem. On dev mode the css classnames match the styles. They have a prefix of css-dev-only-do-not-override
. However, on the production mode the classnames in the style files just get the css
prefix while the elements still have the css-dev-only-do-not-override
. On using a normal CLI the transition between the prefixes gets done automatically. But, with a custom building and running script I had to implicitly set the node environment. Here are the build and run examples.
const cli = require('next/dist/cli/next-build')
process.env.NODE_ENV = 'production'
cli.nextBuild()
const cli = require('next/dist/cli/next-start')
process.env.NODE_ENV = 'production'
cli.nextStart(
[
'--port', process.env.PORT,
'--hostname', process.env.HOSTNAME,
],
)