react17.0.1 按需引入 antd

1,991 阅读3分钟

安装需要的依赖

默认使用 cnpm

cnpm install babel-plugin-import less-loader --dev
cnpm install antd --save

reject 项目

npm run reject

修改 package.json: 添加 antd 库的样式

 "babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      [
        "import",
        {
          "libraryName": "antd",
          "style": true
        }
      ]
    ]
  }

webpack.config.js 文件修改(重点)

找到 config 文件夹下的 webpack.config.js

1 增加 style 样式正则

大约在 60 行

// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
// 增加的正则
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;

2 配置 1 中添加的正则和 less-loader

在 552 行左右,sass-loader 下方,file-loader 上。

 // 添加如下内容
{
  test: lessRegex,
  exclude: lessModuleRegex,
  use: getStyleLoaders({ importLoaders: 2 }, 'less-loader'),
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
  test: lessModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 2,
      modules: true,
      getLocalIdent: getCSSModuleLocalIdent,
    },
    'less-loader'
  ),
},
{
  test: /\.less$/,
  use: [
    require.resolve('style-loader'),
    {
      loader: require.resolve('css-loader'),
      options: {
        importLoaders: 1,
      },
    },
    {
      loader:require.resolve('less-loader'),
      options: {
        modules: false,
        modifyVars: {
            "@primary-color": "#f9c700"
        }
      }
    }
  ],
},

有些教程在test: /.less$/中会配置浏览器相关的信息。本人在配置后打包会提示不要在这上面配置相关信息。所以删除了,并不影响使用。

3 定义全局样式

在138行左右
原来的配置:

if (preProcessor) {
  loaders.push(
    {
      loader: require.resolve('resolve-url-loader'),
      options: {
        sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
        root: paths.appSrc,
      },
    },
    {
      loader: require.resolve(preProcessor),
      options: {
        sourceMap: true,
      },
    }
  );
}

修改后的配置

if (preProcessor) {
  loaders.push(
    {
      loader: require.resolve('resolve-url-loader'),
      options: {
        sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
        root: paths.appSrc,
      },
    },
    // {
    //   loader: require.resolve(preProcessor),
    //   options: {
    //     sourceMap: true,
    //   },
    // }
  );
  let loader = require.resolve(preProcessor)
  if (preProcessor === "less-loader") {
    loader = {
      loader,
      options: {
        modifyVars: { //自定义主题
          'primary-color':' #1890ff ',
        },
        javascriptEnabled: true,
      }
    }
  }
  loaders.push(loader);
}

这里的resolve-url-loader是和解析url相对路径和sass有关的插件。想深究的同学可以进一步查询资料,我也不懂。所以这里没有注释掉,而是保留了下来,只修改了preProcessor的配置。

4 修改js,添加antd库的样式

404行左右test: /.(js|mjs|jsx|ts|tsx)$/

{
  test: /\.(js|mjs|jsx|ts|tsx)$/,
  include: paths.appSrc,
  loader: require.resolve('babel-loader'),
  options: {
    customize: require.resolve(
      'babel-preset-react-app/webpack-overrides'
    ),
    presets: [
      [
        require.resolve('babel-preset-react-app'),
        {
          runtime: hasJsxRuntime ? 'automatic' : 'classic',
        },
      ],
    ],
    
    plugins: [
      [
        require.resolve('babel-plugin-named-asset-import'),
        {
          loaderMap: {
            svg: {
              ReactComponent:
                '@svgr/webpack?-svgo,+titleProp,+ref![path]',
            },
          },
        },
      ],
      // 添加的样式
      ['import', { libraryName: 'antd', style: true }],  // import less
      isEnvDevelopment &&
        shouldUseReactRefresh &&
        require.resolve('react-refresh/babel'),
    ].filter(Boolean),
    // This is a feature of `babel-loader` for webpack (not Babel itself).
    // It enables caching results in ./node_modules/.cache/babel-loader/
    // directory for faster rebuilds.
    cacheDirectory: true,
    // See #6846 for context on why cacheCompression is disabled
    cacheCompression: false,
    compact: isEnvProduction,
  },
  },

450行左右test: /.(js|mjs)$/

{
  test: /\.(js|mjs)$/,
  exclude: /@babel(?:\/|\\{1,2})runtime/,
  loader: require.resolve('babel-loader'),
  options: {
    babelrc: false,
    configFile: false,
    compact: false,
    presets: [
      [
        require.resolve('babel-preset-react-app/dependencies'),
        { helpers: true },
      ],
    ],
    // 添加plugin
    plugins: [
      ['import', { libraryName: 'antd', style: true }],  // import less
    ],
    cacheDirectory: true,
    // See #6846 for context on why cacheCompression is disabled
    cacheCompression: false,
    
    // Babel sourcemaps are needed for debugging into node_modules
    // code.  Without the options below, debuggers like VSCode
    // show incorrect code and set breakpoints on the wrong lines.
    sourceMaps: shouldUseSourceMap,
    inputSourceMap: shouldUseSourceMap,
  },
}

test: /.(js|mjs)$/中可以不用添加。根据oneof规则和include,我们编写的代码都是在src下的,会匹配到第一个规则。

配置过程中遇到的错误及解决方法

1 can't find module "less"

cnpm i less --dev

2 .plugins[1][1] must be an object, false, or undefined

上面配置plugin的时候参考其他的教程出现的错误。

// 参考教程中数组第二个元素有[]包裹
['import', [{ libraryName: 'antd', style: true }]]

// 去掉[]
['import', { libraryName: 'antd', style: true }]

3 TypeError: this.getOptions is not a function

原因: less-loader安装的版本过高
解决方法:安装5.0.0版本

如果使用npm uninstall less-loader可能会出错。建议使用如下方法:
在package.json中把less-loader的版本改成5.0.0。删除node_modules,重新cnpm i。

参考的教程