CRA 配置 less-loader 和 devServer

本文讲述了在使用create-react-app和定制工具如customize-cra或craco时,如何解决less-loader与postcss-loader版本更新带来的配置冲突,包括调整styleLoaders和创建craco.config.js文件以确保less文件正确加载。
摘要由CSDN通过智能技术生成
前言

eject 不可逆,想试不 eject 情况下改 webpack 配置。

主要介绍的是配置 less-loader 遇到的坑。


正文
1. react-app-rewired + customize-cra

一开始按照 customize-cra - api.md 在 config-overrides.js 中配置 less-loader,然后报错 options has an unknown property 'plugins'. These properties are valid: object { postcssOptions?, execute?, sourceMap?, implementation? }

原因:postcss-loader 版本原因,有新的配置写法。


源码 customize-cra 1.0.0 addLessLoader 中

// addLessLoader - getStyleLoaders
{
  loader: require.resolve('postcss-loader'),
  options: {
    ident: 'postcss',
    plugins: () => [
      require('postcss-flexbugs-fixes'),
      require('postcss-preset-env')({
        autoprefixer: {
          flexbox: 'no-2009',
        },
        stage: 3,
      }),
      postcssNormalize(),
    ],
    sourceMap: isEnvProduction && shouldUseSourceMap,
  },
}

 看了 postcss-loader 8.1.1

{
  loader: 'postcss-loader',
  options: {
    postcssOptions: {
      plugins: [
        [
          'postcss-preset-env',
          {
            // Options
          },
        ],
      ],
    },
  },
}

不难看出少了 postcssOptions。当然,在报错信息中是有提及到 postcssOptions,但是一开始只关注到 options has an unknown property 'plugins' ,后面是试了源码才知道的。

解决方案:

Incompatible with Create-React-App 5.0: Invalid Options for PostCSS Loader · Issue #315 · arackaf/customize-cra · GitHub

① 315#issuecomment-1035698591

adjustStyleLoaders(({ use: [, , postcss] }) => {
  const postcssOptions = postcss.options;
  postcss.options = { postcssOptions };
})

试过可以解决,但发现部分 options 已包含 postcssOptions,如果使用可以自己做下判断兼容。

 315#issuecomment-1009628736

// config-overrides.js
config.module.rules.forEach(item => {
  if (item.oneOf) {
    item.oneOf.forEach(item => {
      item.use?.forEach(item => {
        if (
          item.loader?.includes('postcss-loader') &&
          !item?.options?.postcssOptions
        ) {
          const postcssOptions = item.options;
          item.options = { postcssOptions };
        }
      });
    });
  }
})

③ 315#issuecomment-1120775809

module.exports = {
  webpack: override(
    addWebpackModuleRule({
      test: [/\.css$/, /\.less$/],
      use: ['style-loader', 'css-loader', 'postcss-loader', { loader: 'less-loader' }]
    })
  )
}

本地包版本:

css-loader "^6.5.1"
mini-css-extract-plugin "^2.4.5"
postcss "^8.4.4"
postcss-flexbugs-fixes "^5.0.2"
postcss-loader "^6.2.1"
postcss-normalize "^10.0.1"
postcss-preset-env "^7.0.1"
style-loader "^3.3.1"
// 自个安装
less-loader@^12.2.0
less@^4.2.0

值得注意的是:用 config-overrides.js 覆写 webpack.config.js 配置,在反复测验解决方案时,已经解决了的配置代码注释掉再启动,这时是不会复现已解决的问题的,是因为 webpack 缓存 的原因,手动删除缓存文件 node_modules/.cache 就可以了。

最后贴个配置:

// config-overrides.js
const {
  addLessLoader,
  override,
  addWebpackAlias,
  adjustStyleLoaders,
} = require('customize-cra');
const path = require('path');

module.exports = {
  webpack: override(
    addWebpackAlias({
      ['@']: path.resolve(__dirname, 'src'),
    }),
    addLessLoader({
      lessOptions: {
        javascriptEnabled: true,
      },
      additionalData: `@import './src/assets/css/values.less';`,
    }),
    adjustStyleLoaders(({ use: [, , postcss] }) => {
      if (!postcss.options.postcssOptions) {
        const postcssOptions = postcss.options;
        postcss.options = { postcssOptions };
      }
    })
  ),
  devServer: overrideDevServer((config) => ({
    ...config,
    compress: true,
    proxy: {
      '/api': {
        target: 'http://localhost:3000', // 服务器地址
        changeOrigin: true,
        pathRewrite: {
          '^/api': '',
        },
      },
    },
  })),
};

2. @crao/craco

参照 craco.js 文档,在根目录创建 craco.config.js

设置别名:

const path = require('path');

module.exports = {
  webpack: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
};

或者

const path = require('path');

module.exports = {
  webpack: {
    configure: {
      resolve: {
        alias: {
          '@': path.resolve(__dirname, 'src'),
        },
      },
    },
  },
};

配置 less-loader 时发现官方的 style 中并没有提及 less。然后尝试用官方提供的 webpack.configure 可以写 module.rules,也就是

// 无效
module.exports = {
  webpack: {
    configure: {
      module: {
        rules: [
          {
            test: [/\.less$/i],
            use: ['style-loader', 'css-loader', 'less-loader'],
          },
        ],
      },
    },
  },
};

但是无效,原因是 craco 本身对 webpack 配置的 modules.rules 中写了一个 oneOf,属性值是数组,此规则将对所有文件进行解析,末尾数组项是

而在 craco.config.js 中续写了对 less 文件的解析规则排在上面规则之后,导致 less 文件解析无法使用正确的 loader

解决方案:

① 将规则提前

module.exports = {
  plugins: [
    {
      plugin: {
        overrideWebpackConfig: ({ webpackConfig }) => {
          const { module } = webpackConfig;
          const index = module.rules.findIndex((i) => i.oneOf);
          if (index !== -1) {
            module.rules[index].oneOf.unshift({
              test: [/\.less$/i],
              use: ['style-loader', 'css-loader', 'less-loader'],
            });
          }
          return webpackConfig;
        },
      },
    },
  ],
};

② 社区插件 craco-less

const CracoLessPlugin = require('craco-less');

module.exports = {
  plugins: [
    {
      plugin: CracoLessPlugin,
    },
  ],
};

最后贴个:

// craco.config.js
const CracoLessPlugin = require('craco-less');
const path = require('path');

module.exports = {
  webpack: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
  plugins: [
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          additionalData: `@import './src/assets/css/values.less';`,
        },
      },
    },
  ],
  devServer: {
    proxy: [
      {
        context: ['/api'],
        target: 'http://localhost:3000', // 服务器地址
        pathRewrite: { '^/api': '' },
      },
    ],
  },
};

注:如有侵权,告知即删。如有错漏之处,敬请指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值