elado / next-with-less

Next.js + Less CSS Support
MIT License
143 stars 24 forks source link

Doesn't work with NextJS 13 #28

Open Charismara opened 1 year ago

Charismara commented 1 year ago

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

pdanysz commented 1 year ago

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

Charismara commented 1 year ago

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?

mayrsascha commented 1 year ago

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

nmiddendorff commented 1 year ago

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

hqwlkj commented 1 year ago

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?

sknightq commented 1 year ago

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?

BossBele commented 1 year ago

Not working with app folder

ateix17 commented 10 months ago

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;
  },
Jeysef commented 7 months ago

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