elado / next-with-less

Next.js + Less CSS Support

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Global CSS cannot be imported from within node_modules.

JesperWe opened this issue · comments

Hi!

Thanks for trying to contibute to solving the Next 10 / Webpack 5 / Ant Design mess ;-)

I am trying you solution, but ending up with

info  - Creating an optimized production build  
Failed to compile.

./node_modules/antd/lib/affix/style/index.less
Global CSS cannot be imported from within node_modules.
Read more: https://nextjs.org/docs/messages/css-npm
Location: node_modules/antd/lib/affix/style/index.js
...
Error: > Build failed because of webpack errors

This does not happen if I try to add the component to your example code.
I cannot quite figure what the difference is though.
Any tips?

The solution is to import the .less files in your pages/_app instead of importing a JS file that imports them:

Not quite understanding this. You are saying that the normal way, like

import { Affix, Button, Col, Row } from "antd"

doesn't work, because it is importing a JS file that imports a Less file.

And that I need to import ALL less files of the components used across the app in _app.js to fix this?

Seems I am in for a bit of work... :-)

Can you share some more code? I'll take a look later

Sure, I'll try to show the relevant pieces. The project is huge ;-)

next.config.js:

const lessToJS = require( 'less-vars-to-js' )
const fs = require( 'fs' )
const path = require( 'path' )
const withLess = require("next-with-less");
const MomentLocalesPlugin = require( 'moment-locales-webpack-plugin' )

// Where your antd-custom.less file lives
const theme = lessToJS(
	fs.readFileSync( path.resolve( __dirname, './antd-custom.less' ), 'utf8' )
)

const withBundleAnalyzer = require( '@next/bundle-analyzer' )( {
	enabled: process.env.ANALYZE === 'true',
} )

module.exports = withBundleAnalyzer( withLess( {
	lessLoaderOptions: {
		lessOptions: {
			javascriptEnabled: true,
			modifyVars: theme,
		}
	},
	productionBrowserSourceMaps: false,
	publicRuntimeConfig: { theme },
	webpack: ( config, { buildId, dev, isServer, defaultLoaders, webpack } ) => {
		config.resolve.modules.push( path.resolve( './' ) )

		config.plugins.push(
			new MomentLocalesPlugin( {
				localesToKeep: [ 'sv' ]
			} ) )

		return config
	},
	i18n: {
		locales: [ 'en', 'sv' ],
		defaultLocale: 'sv'
	},
	future: {
		webpack5: true
	}
} ) )

antd-custom.less just has a set of theme variable overrides:

@text-color: #151716;
@component-background: #fff;
.... etc

Then there is a root app.less file that gets imported to _app.js. This is the only Ant css related import in the .js components. For the rest of the app we just import the ant components as shown in my post above.

app.less imports the default theme, then our theme customization and then some overrides to the default theme that is not exposed through the Less variables:

app.less:

@import "node_modules/antd/lib/style/themes/default.less";
@import "antd-custom.less";
@import "antd-overrides.less";

... and then lots of ordinary global (non component specific) css/less ...

This setup has served us fine since Next 9.2 or so but since the Next team seems inclined to drop the ball on Less support I found your "let's mimic their Sass setup" approach interesting ;-)

I'm not quite sure where it's coming from. Can you try converting

@import "node_modules/antd/lib/style/themes/default.less";

into

@import "~antd/lib/style/themes/default.less";

?

~ prefix is the common way of importing CSS with @import from node_modules.

If this still fails, try replicating the issue in the examples dir in a fork.

@JesperWe removing .babelrc that I had from Next.js example fixed this for me.

Good catch @akornato !
I could not remove .babelrc completely since it uses other (non-Ant) stuff, but removing the Ant plugin made the above error go away.

build runs a bit longer with this....however it now fails at

info  - Creating an optimized production build  
Failed to compile.

./app.less

// https://github.com/ant-design/ant-motion/issues/44
.bezierEasingMixin();
^
Inline JavaScript is not enabled. Is it set in your options?
      in /...../node_modules/antd/lib/style/color/bezierEasing.less (line 110, column 0)
    at runMicrotasks (<anonymous>)

even though I can see in the source line 51 has javascriptEnabled: true,

@JesperWe hmm not sure why, I no longer even have javascriptEnabled: true - my next.config.js is pretty much just as in this repo's example.

Yes, this plugin seems to always enable javascript but it somehow it is not working for me.
Maybe we are using components that you are not...

@JesperWe removing .babelrc that I had from Next.js example fixed this for me.

This issue was happening to me as well, did what @JesperWe suggested and it worked! Thanks!

I created a nextjs package next-remove-imports to solve the problem.

Example: https://codesandbox.io/s/nextjs-example-react-md-editor-qjhn7?file=/pages/index.js

// next.config.js
const removeImports = require("next-remove-imports")();

module.exports = removeImports({});
// pages/index.js

import Head from 'next/head'
import MDEditor from '@uiw/react-md-editor';
import "@uiw/react-md-editor/dist/markdown-editor.css";
import "@uiw/react-markdown-preview/dist/markdown.css";

export default function Home() {
  return (
    <div>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <MDEditor value="**Hello world!!!**" />
    </div>
  )
}

@JesperWe