create-react-app 按需引入 antd 组件, 更改主题配置

create-react-app 创建一个 react 项目. 然后引入 antd . antd 官网的流程需要自行写配置文件. 与 webpack 相结合. 当然这种做法也无不妥. 但是如果你也想一观背后别有洞天的代码. 那就看下去!

商业互捧

前端发展日新月异. 为了不使诸位同仁在看本文是产生疑惑. 在此罗列出此次项目中使用到的环境及库的版本

  1. node (v12.16.2)
  2. npm (v6.14.4)
  3. react (v16.13.1)
  4. antd (v4.1.4)
  5. less (v3.11.1)
  6. less-loader (v5.0.0)
  7. babel-plugin-import (v1.13.0)
  8. webpack (v4.42.0)

如果, 在配置过程中遇到问题, 可参照对应版本查找解决方案.

推荐使用 yarn

安装依赖项

安装 antd

# npm 
npm install antd --save

# yarn
yarn add antd

安装 less, less-loader

由于 antd 是由 less 开发的样式组件, 所以我们也需要引入 lessless-loader

# npm
npm install less less-loader --save

# yarn
yarn add less less-loader

安装 babel-plugin-import

按需加载组件库, 我们还需要一个插件 babel-plugin-import

更改配置项时注意图中区别

在使用 create-react-app 创建了 react 项目时. 我们在项目目录中是看不到关于 webpack 的配置项的. 而 create-react-app 也为我们提供了能看到它的方式.

暴露配置文件

我们需要在项目终端运行一行命令:

# npm
npm run eject

# yarn
yarn eject

此时, 我们就可以看到项目中多了两个文件夹 configscripts . 再打开 package.json 发现它也是大变样. 不过我们关注的重点主要在 config 文件中的 webpack.config.js

更改配置项

// webpack.config.js

...
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;

// 此处添加: 自定义添加less配置
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
// 添加结束
...

file-loader 上面引入规则 顺序不可变更. 当配置多个 loader 时, loader 的执行顺序是从右到左, 从下到上

...
{
  test: sassModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 3,
      sourceMap: isEnvProduction && shouldUseSourceMap,
      modules: {
        getLocalIdent: getCSSModuleLocalIdent,
      },
    },
    'sass-loader'
  ),
},

// 此处添加: 自定义添加 less
{
  test: lessRegex,
  exclude: lessModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 3,
      sourceMap: isEnvProduction && shouldUseSourceMap,
    },
    'less-loader'
  ),
  sideEffects: true,
},
{
  test: lessModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 3,
      sourceMap: isEnvProduction && shouldUseSourceMap,
      modules: {
        getLocalIdent: getCSSModuleLocalIdent,
      },
    },
    'less-loader'
  ),
},
// 添加结束!

{
  loader: require.resolve('file-loader'),
  // Exclude `js` files to keep "css" loader working as it injects
  // its runtime that would otherwise be processed through "file" loader.
  // Also exclude `html` and `json` extensions so they get processed
  // by webpacks internal loaders.
  exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
  options: {
    name: 'static/media/[name].[hash:8].[ext]',
  },
},
// ** STOP ** Are you adding a new loader?
...

按需加载

...
plugins: [
  [
    require.resolve('babel-plugin-named-asset-import'),
    {
      loaderMap: {
        svg: {
          ReactComponent:
            '@svgr/webpack?-svgo,+titleProp,+ref![path]',
        },
      },
    },
  ],
  // 此处添加: 按需引入 antd
  [
    require.resolve('babel-plugin-import'),
    {
      libraryName: 'antd',
      "libraryDirectory": "es",
      style: true
    }
  ]
  // 添加结束
],
...

自定义主题

...
if (preProcessor) {
  loaders.push(
    {
      loader: require.resolve('resolve-url-loader'),
      options: {
        sourceMap: isEnvProduction && shouldUseSourceMap,
      },
    },
    {
      loader: require.resolve(preProcessor),
      options: {
        sourceMap: true,
      },
    }
  );
}
// 此处添加: 自定义主题
if (preProcessor && preProcessor === 'less-loader') {
  loaders.push(
    {
      loader: require.resolve('resolve-url-loader'),
      options: {
        sourceMap: isEnvProduction && shouldUseSourceMap
      }
    },
    {
      loader: require.resolve(preProcessor),
      options: {
        sourceMap: true,
        javascriptEnabled: true,
        modifyVars: {
          'primary-color': '#ff4757',
          'link-color': '#ff4757',
          'border-radius-base': '2px',
        }
      }
    }
  );
}
// 添加结束
return loaders;
...

antd 样式变量

此后, 我们无需在任何地方引入 antd 的 css 文件!

配置结束, 运行项目!