elado / next-with-less

Next.js + Less CSS Support

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Doesn't work with NextJS 13

Charismara opened this issue · comments

commented

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

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

commented

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?

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...

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

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?

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?

Not working with app folder

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;
  },

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;
        },
    });
}