next-with-less icon indicating copy to clipboard operation
next-with-less copied to clipboard

Doesn't work with NextJS 13

Open Charismara opened this issue 2 years ago • 9 comments

Versions

next-with-less: 2.0.5 less-loader: 11.1.0 less: 4.1.3 (dev dependency) next: 13.0.0 antd: 4.23.6

next.config.js

const withLess = require('next-with-less');

module.exports = withLess({
  reactStrictMode: true,
  swcMinify: true,
  experimental: {
    appDir: true,
  }
});

Error Message

image

I'm importing the antd.less in my app/layout.tsx file

Charismara avatar Oct 26 '22 07:10 Charismara

Versions

next-with-less: 2.0.5 less-loader: 11.1.0 less: 4.1.3 (dev dependency) next: 13.0.0 antd: 4.23.6

next.config.js

const withLess = require('next-with-less');

module.exports = withLess({
  reactStrictMode: true,
  swcMinify: true,
  experimental: {
    appDir: true,
  }
});

Error Message

image

I'm importing the antd.less in my app/layout.tsx file

You can switch to this repo. Is working for me for /app dir :) https://github.com/SolidZORO/next-plugin-antd-less

pdanysz avatar Nov 08 '22 19:11 pdanysz

You can switch to this repo. Is working for me for /app dir :) https://github.com/SolidZORO/next-plugin-antd-less

I kinda struggle on setting up the plugin with typescript: image

Does anyone happen to have a working nextjs 13 (with app dir), typescript project on GitHub where I can take a look?

Charismara avatar Nov 09 '22 09:11 Charismara

You can switch to this repo. Is working for me for /app dir :) https://github.com/SolidZORO/next-plugin-antd-less

Unfortunately this one doesn't work with SWC, so again not really working for me with Next 13...

mayrsascha avatar Nov 11 '22 09:11 mayrsascha

I don't know which commit fixed the issue but next-with-less is working in 13.1.1 now.

nmiddendorff avatar Jan 06 '23 23:01 nmiddendorff

I don't know which commit fixed the issue but next-with-less is working in 13.1.1 now.

Although it is configured to use less in 13.1.1, the configuration of nextjs itself does not take effect.

Is there any recommended way to deal with it?

hqwlkj avatar Jan 12 '23 10:01 hqwlkj

You can switch to this repo. Is working for me for /app dir :) https://github.com/SolidZORO/next-plugin-antd-less

Unfortunately this one doesn't work with SWC, so again not really working for me with Next 13...

Do you find the solution for nextjs 13 with app fold and SWC?

sknightq avatar Jun 21 '23 03:06 sknightq

Not working with app folder

BossBele avatar Jul 17 '23 07:07 BossBele

I had trouble getting this plugin to work with the app folder as well, and ended up extending the webpack config in next.config.js to get LESS support:

  webpack: (config) => {
    config.module.rules.push({
      test: /\.module\.less$/,
      use: [
        {
          loader: require.resolve('style-loader'),
        },
        {
          loader: require.resolve('css-loader'),
          options: {
            sourceMap: true,
            modules: true,
          },
        },
        {
          loader: require.resolve('postcss-loader'),
          options: {
            postcssOptions: {
              sourceMap: true,
            },
          },
        },
        {
          loader: require.resolve('less-loader'),
          },
        },
      ],
    });

    return config;
  },

ateix17 avatar Sep 08 '23 16:09 ateix17

I edited the code to this and now it works for me. The code:

/** 
 * @function withLess
 * @param {import('next').NextConfig} nextConfig
 * @returns {import('next').NextConfig}
 * */
function withLess(nextConfig) {
    return Object.assign({}, nextConfig, {
        /** 
         * @function webpack
         * @type {import('next').NextConfig["webpack"]}
         * @param {import('webpack').Configuration} config
         * @returns {import('webpack').Configuration}
        * */
        webpack(config, opts) {
            // there are 2 relevant sass rules in next.js - css modules and global css
            let sassModuleRules = [];
            // global sass rule (does not exist in server builds)
            let sassGlobalRules = [];

            const cssRule = config.module.rules.find(({ oneOf }) => !!oneOf).oneOf

            const addLessToRuleTest = (test) => {
                if (Array.isArray(test)) {
                    return test.map((rx) => addLessToRegExp(rx));
                } else {
                    return addLessToRegExp(test);
                }
            };

            cssRule.forEach((rule, i) => {
                if (rule.use?.loader === 'error-loader') {
                    rule.test = addLessToRuleTest(rule.test);
                } else if (rule.use?.loader?.includes('file-loader')) {
                    rule.issuer = addLessToRuleTest(rule.issuer);
                } else if (rule.use?.includes?.('ignore-loader')) {
                    rule.test = addLessToRuleTest(rule.test);
                } else if (rule.test?.source === '\\.module\\.(scss|sass)$') {
                    sassModuleRules.push(rule);
                } else if (rule.test?.source === '(?<!\\.module)\\.(scss|sass)$') {
                    sassGlobalRules.push(rule);
                } else if (rule.issuer?.source === "\\.(css|scss|sass)$" && rule.type === 'asset/resource') {
                    rule.issuer = addLessToRuleTest(rule.issuer);
                } else if (rule.use?.loader?.includes('next-flight-css-loader')) {
                    rule.test = addLessToRuleTest(rule.test);
                }
            });

            const lessLoader = {
                loader: 'less-loader',
                options: {
                    lessOptions: {
                        javascriptEnabled: true,
                    },
                },
            };

            let lessModuleRules = cloneDeep(sassModuleRules);

            const configureLessRule = (rule) => {
                rule.test = new RegExp(rule.test.source.replace('(scss|sass)', 'less'));
                // replace sass-loader (last entry) with less-loader
                rule.use.splice(-1, 1, lessLoader);
            };

            lessModuleRules.forEach((lessModuleRule, index) => {
                configureLessRule(lessModuleRule);
                cssRule.splice(cssRule.indexOf(sassModuleRules[index]) + 1, 0, lessModuleRule);
            });

            if (sassGlobalRules) {
                let lessGlobalRules = cloneDeep(sassGlobalRules);
                lessGlobalRules.forEach((lessGlobalRule, index) => {
                    configureLessRule(lessGlobalRule);
                    cssRule.splice(cssRule.indexOf(sassGlobalRules[index]) + 1, 0, lessGlobalRule);
                });
            }

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

            return config;
        },
    });
}

Jeysef avatar Nov 22 '23 13:11 Jeysef