vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.73k stars 26.94k forks source link

Next.js 9 with antd + less, yarn build get an error #8054

Closed SolidZORO closed 5 years ago

SolidZORO commented 5 years ago

QUESTION

yarn dev is work, but yarn build get an error.

> Build error occurred
{ /<PROJECT-PATH>/node_modules/antd/lib/style/index.less:1
(function (exports, require, module, __filename, __dirname) { @import './themes/index';
                                                              ^

SyntaxError: Invalid or unexpected token
    at new Script (vm.js:79:7)
    at createScript (vm.js:251:10)
    at Object.runInThisContext (vm.js:303:10)
    at Module._compile (internal/modules/cjs/loader.js:656:28)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
    at Module.load (internal/modules/cjs/loader.js:598:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
    at Function.Module._load (internal/modules/cjs/loader.js:529:3)
    at Module.require (internal/modules/cjs/loader.js:636:17)
    at require (internal/modules/cjs/helpers.js:20:18) type: 'SyntaxError', '$error': '$error' }
error Command failed with exit code 1.
SolidZORO commented 5 years ago

RESOLVE

i found that with-ant-design-less can handles this error, but project/pages's less style don't work. so I wrote a next-antd.config.js to solve this problem.

next.config.js

const fs = require('fs');
const path = require('path');

const lessToJS = require('less-vars-to-js');
const FilterWarningsPlugin = require('webpack-filter-warnings-plugin');

const withImage = require('./configs/next-image.config');
const withDotenv = require('./configs/next-dotenv.config');
const withAntd = require('./configs/next-antd.config');

const antdVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, './styles/variables.less'), 'utf8'));

// fix: prevents error when .less files are required by node
if (typeof require !== 'undefined') {
  require.extensions['.less'] = file => {};
}

module.exports = withDotenv(
  withImage(
    withAntd({
      cssModules: true,
      cssLoaderOptions: {
        sourceMap: false,
        importLoaders: 1,
      },
      lessLoaderOptions: {
        javascriptEnabled: true,
        modifyVars: antdVariables,
      },
      webpack: config => {
        config.plugins.push(
          new FilterWarningsPlugin({
            // ignore ANTD chunk styles [mini-css-extract-plugin] warning
            exclude: /mini-css-extract-plugin[^]*Conflicting order between:/,
          }),
        );

        return config;
      },
    }),
  ),
);

next-antd.config.js

const cssLoaderConfig = require('@zeit/next-css/css-loader-config');

module.exports = (nextConfig = {}) => ({
  ...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 { cssModules, cssLoaderOptions, postcssLoaderOptions, lessLoaderOptions = {} } = nextConfig;

      // for all less in clint
      const baseLessConfig = {
        extensions: ['less'],
        cssModules,
        cssLoaderOptions,
        postcssLoaderOptions,
        dev,
        isServer,
        loaders: [
          {
            loader: 'less-loader',
            options: lessLoaderOptions,
          },
        ],
      };

      config.module.rules.push({
        test: /\.less$/,
        exclude: /node_modules/,
        use: cssLoaderConfig(config, baseLessConfig),
      });

      // for antd less in client
      const antdLessConfig = {
        ...baseLessConfig,
        ...{ cssModules: false, cssLoaderOptions: {}, postcssLoaderOptions: {} },
      };

      config.module.rules.push({
        test: /\.less$/,
        include: /node_modules/,
        use: cssLoaderConfig(config, antdLessConfig),
      });

      // for antd less in server (yarn build)
      if (isServer) {
        const antdStyles = /antd\/.*?\/style.*?/;
        const rawExternals = [...config.externals];

        config.externals = [
          (context, request, callback) => {
            if (request.match(antdStyles)) {
              return callback();
            }

            if (typeof rawExternals[0] === 'function') {
              rawExternals[0](context, request, callback);
            } else {
              callback();
            }
          },
          ...(typeof rawExternals[0] === 'function' ? [] : rawExternals),
        ];

        config.module.rules.unshift({
          test: antdStyles,
          use: 'null-loader',
        });
      }

      if (typeof nextConfig.webpack === 'function') {
        return nextConfig.webpack(config, options);
      }

      return config;
    },
  },
});

.babelrc.js

module.exports = {
  presets: [['next/babel']],
  plugins: [
    [
      'import',
      {
        libraryName: 'antd',
        libraryDirectory: 'lib',
        style: true,
      },
    ],
  ],
  ignore: ['node_modules'],
};

package.json

 "devDependencies": {
    "@zeit/next-css": "^1.0.2-canary.2",
    "@zeit/next-less": "^1.0.1",
    "less": "^3.9.0",
    "less-vars-to-js": "^1.3.0",
    "null-loader": "^3.0.0",
    "webpack-filter-warnings-plugin": "^1.2.1"
  }
zadzbw commented 5 years ago

@SolidZORO good job, thanks

mohamedmagdy17593 commented 5 years ago

@SolidZORO thanks ^_^

afsanefdaa commented 5 years ago

const fs = require('fs'); const path = require('path');

const lessToJS = require('less-vars-to-js'); const FilterWarningsPlugin = require('webpack-filter-warnings-plugin');

const withImage = require('./configs/next-image.config'); const withDotenv = require('./configs/next-dotenv.config'); const withAntd = require('./configs/next-antd.config');

const antdVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, './styles/variables.less'), 'utf8'));

// fix: prevents error when .less files are required by node if (typeof require !== 'undefined') { require.extensions['.less'] = file => {}; }

module.exports = withDotenv( withImage( withAntd({ cssModules: true, cssLoaderOptions: { sourceMap: false, importLoaders: 1, }, lessLoaderOptions: { javascriptEnabled: true, modifyVars: antdVariables, }, webpack: config => { config.plugins.push( new FilterWarningsPlugin({ // ignore ANTD chunk styles [mini-css-extract-plugin] warning exclude: /mini-css-extract-plugin[^]*Conflicting order between:/, }), );

    return config;
  },
}),

), );

Could you please explain more what changes you applied to the next config?

SolidZORO commented 5 years ago

updated 2020-01-12.

because next-less has too many black box details, I configured webpack directly. https://github.com/SolidZORO/leaa/blob/legacy-www/packages/leaa-www/tools/next/next-webpack.js

@afsanefda you can https://github.com/SolidZORO/leaa/blob/legacy-www/packages/leaa-www/tools/next/next-webpack.js

afsanefdaa commented 5 years ago

Thank you. I saw the code but I need to know exactly what causes this problem?

afsanefdaa commented 5 years ago

I added the next-ant.config to my project But what should I do exactly with my next config?

my next.config.js

const withPlugins = require('next-compose-plugins');
const withCss = require('@zeit/next-css');
const withSass = require('@zeit/next-sass');
const BrotliPlugin = require('brotli-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const withImages = require('next-images');

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

// fix: prevents error when .css files are required by node
// https://github.com/zeit/next.js/blob/master/examples/with-ant-design/next.config.js
if (typeof require !== 'undefined') {
  require.extensions[".css"] = file => {}; // eslint-disable-line
}

// main next config, including webpack
const nextConfig = {
  distDir: '_next', // used to define the name of build dir, we need it to be _next, for serving gzip files

  // next js caches pages in dev mode, this config is used to increase cache time to have better dev experience
  // https://github.com/zeit/next.js/issues/1939
  onDemandEntries: {
    // Make sure entries are not getting disposed.
    maxInactiveAge: 1000 * 60 * 60,
    // number of pages that should be kept simultaneously without being disposed
    pagesBufferLength: 5,
  },

  // webpack config
  webpack: (config, { dev }) => {
    // Add brotli plugin
    !dev &&
      config.plugins.push(
        new BrotliPlugin({
          asset: '[path].br[query]',
          test: /\.js$|\.css$|\.html$/,
          threshold: 10240,
          minRatio: 0.7,
        }),
      );

    // Add gzip compression plugin
    !dev &&
      config.plugins.push(
        new CompressionPlugin({
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          test: /\.js$|\.css$|\.html$/,
          threshold: 10240,
          minRatio: 0.7,
        }),
      );
    return config;
  },
};

module.exports = withPlugins(
  [
    [withImages],
    [withCss],
    [
      withSass,
      {
        cssModules: true,
        cssLoaderOptions: {
          localIdentName: '[path]___[local]___[hash:base64:5]',
        },
      },
    ],
    [withBundleAnalyzer],
  ],
  nextConfig,
);

and my babel.config.js:

module.exports = {
  presets: ['next/babel'],
  plugins: [
    '@babel/plugin-proposal-optional-chaining',
    [
      'import',
      {
        libraryName: 'antd',
        style: 'css',
      },
    ],
    [
      'react-intl',
      {
        messagesDir: './locale',
        extractSourceLocation: true,
      },
    ],
  ],
};
SolidZORO commented 5 years ago

because server don't know *.less, just browser know it. so we need to deal with this.

savalanpour commented 5 years ago

This issue solved here https://stackoverflow.com/questions/57542802/build-error-occurred-in-node-modules-antd-lib-style-index-css7/57543812#57543812

Carrie999 commented 5 years ago

thanks

flasco commented 4 years ago

it's useful, tks!

maysam commented 4 years ago

you're a life saver

maotora commented 4 years ago

@SolidZORO Hi, I have installed and applied webpack-filter-warnings-plugin but I still get the warnings.

Here is my next.config.js file.

const withCss = require('@zeit/next-css')
const FilterWarningsPlugin = require('webpack-filter-warnings-plugin')

module.exports = withCss({
  webpack: (config, { isServer }) => {
    if (isServer) {
      const antStyles = /antd\/.*?\/style\/css.*?/
      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.plugins.push(
        new FilterWarningsPlugin({
          // ignore ANTD chunk styles [mini-css-extract-plugin] warning
          exclude: /mini-css-extract-plugin[^]*Conflicting order between:/,
        }),
      );

      config.module.rules.unshift({
        test: antStyles,
        use: 'null-loader',
      })
    }

    // Fixes npm packages that depend on `fs` module
    config.node = {
      fs: 'empty'
    }

    return config
  },
  distDir: "../../dist/client"
})
SolidZORO commented 4 years ago

@maotora

you can try exclude: /mini-css-extract-plugin[^]*Conflicting order between:/, change to exclude: /Conflicting order/,.

maotora commented 4 years ago

Hi @SolidZORO , Thanks for fast reply however I still get the warnings.

A mountain full of them mini-css-extract-plugin warnings

SolidZORO commented 4 years ago

@maotora I haven't written next.js code for a while, you may need to debug it yourself. 😭

you can see here. https://github.com/SolidZORO/leaa/blob/legacy-www/packages/leaa-www/tools/next/next-webpack.js

maotora commented 4 years ago

I think I have 😁 ...

I had to move the plugin code from the isServer block.

const withCss = require('@zeit/next-css')
const FilterWarningsPlugin = require('webpack-filter-warnings-plugin')

module.exports = withCss({
  webpack: (config, { isServer }) => {
    config.plugins.push(
      new FilterWarningsPlugin({
        // ignore ANTD chunk styles [mini-css-extract-plugin] warning
        exclude: /Conflicting order/,
      })
    );

    if (isServer) {
      const antStyles = /antd\/.*?\/style\/css.*?/
      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',
      })
    }

    // Fixes npm packages that depend on `fs` module
    config.node = {
      fs: 'empty'
    }

    return config
  },
  distDir: "../../dist/client"
})

Just like that warnings are gone!

SolidZORO commented 4 years ago

@maotora In fact, I am very dissatisfied with the plugin ecosystem of next.js, it is like a black box, and there are many bugs. If it is as easy to use as Gatsby's plugin, there will be no problems. So I wrote this part of webpack independently and treat it like normal webpack. (Of course, this is also troublesome for people without webpack configuration experience. Also, you need to pay attention to the css-loader version and pay attention to package.json)

source: https://github.com/SolidZORO/leaa/blob/legacy-www/packages/leaa-www/tools/next/next-webpack.js

bahmannejati commented 4 years ago

Here are the files that works fine for me :

"next": "9.2.2"
"less": "^3.11.1"
"antd": "^4.0.2"

next.config.js

const withLess = require('@zeit/next-less')

module.exports = () => {
    return withLess({
        lessLoaderOptions: {
            modifyVars: {
                'primary-color': '#066',
            },
            javascriptEnabled: true,
        },
        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',
              })
            }
            return config
        },
    })
}

.babelrc

{
    "presets": ["next/babel"],
    "plugins": [
        ["import", { "libraryName": "antd", "style": true }]
    ]
}
nthock commented 4 years ago

@bahmannejati Did you try building the production build and start? It works when running yarn dev but not when yarn build and yarn start.

update: Found out it is due to my postcss config. So this is no longer an issue.

pahaz commented 4 years ago

Thank you. I saw the code but I need to know exactly what causes this problem?

I have a similar problem with @ant-design/layout package. I've slowed the problem by using dynamic imports. Example: https://github.com/8iq/nodejs-hackathon-boilerplate-starter-kit/tree/f3779ff2ffd7b70ed98ad0e998923971372b7907/apps/_example04antpro

Or master branch: https://github.com/8iq/nodejs-hackathon-boilerplate-starter-kit/tree/master/apps/_example04antpro

kavience commented 4 years ago

hello, why I still get the error like this? @SolidZORO ,I make my config like yours, but it did't work when I run build

> Build error occurred
/{PATH}/node_modules/antd/dist/antd.less:1
@import "../lib/style/index.less";
^

SyntaxError: Invalid or unexpected token
    at wrapSafe (internal/modules/cjs/loader.js:1072:16)
    at Module._compile (internal/modules/cjs/loader.js:1122:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
    at Module.load (internal/modules/cjs/loader.js:1002:32)
    at Function.Module._load (internal/modules/cjs/loader.js:901:14)
    at Module.require (internal/modules/cjs/loader.js:1044:19)
    at require (internal/modules/cjs/helpers.js:77:18)
    at Object.<anonymous> (/Users/kevin/lian-med/lian-med-cms/node_modules/lian-med-design/lib/components/index.js:450:1)
    at Module._compile (internal/modules/cjs/loader.js:1158:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) {
  type: 'SyntaxError'
}
error Command failed with exit code 1.
kavience commented 4 years ago

OK, I solved this, thank you guys.

StKostyantin commented 4 years ago

Can I use antd variables and write styles on scss? I use default scss configs next9

millievn commented 4 years ago

Can I use antd variables and write styles on scss? I use default scss configs next9

I prefer to use scss. Did you solve this problem?

StKostyantin commented 4 years ago

I prefer to use scss. Did you solve this problem?

No, I didn't...

I also prefer scss with scss-module. But we can’t use antd without custom next.config, and this in turn does not allow the use of native scss-module from the next9

millievn commented 4 years ago

@bahmannejati @StKostyantin
I replace all scss files to *.module.less. But I still get warning

./src/pages/_app.tsx
Module not found: Can't resolve 'null-loader' 
bahmannejati commented 4 years ago

@qiwang97

Seems you have not null-loader package, install it first using npm:

npm install null-loader --save-dev

Or using yarn:

yarn add --dev null-loader

Consider along with changing .scss to .less, you should change the syntaxes too, less it different by sass

StKostyantin commented 4 years ago

I replace all scss files to *.module.less. But I still get warning

As far as I know, less has not been added to the next9 box yet, and therefore it will not be possible to work with less without configuring the next.config

balazsorban44 commented 2 years ago

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.