icon 工程化支持

136 阅读1分钟

icon 工程化支持

老文:antd-mobile-icons 不提供源码,想定制 icon 组件,怎么办?

如果我不想要依赖外部平台等,则可通过工程化支持,直接实现 icon svg 的管理和使用。

关于 icon 自定义

讨论 Issue 4: github.com/ant-design/…

  1. 可以用 svgr playground 手动转:react-svgr.com/playground/
    1. webpack 配置文档 react-svgr.com/docs/webpac…
  2. 使用 Umi 内置的 svgr 功能把 svg 文件引入为 React 组件
    1. umijs.org/docs/api/co…
// webpack 配置
module.exports = {
  module: {
    rules: [
      // 示例 import Svg from './star.svg'
      {
        test: /\.svg$/i,
        issuer: /\.[jt]sx?$/,
        use: ['@svgr/webpack'],
      },
    ],
  },
}

module.exports = {
  module: {
    rules: [
      // 示例 import svg from './star.svg?url'
      // {
      //   test: /\.svg$/i,
      //   type: 'asset',
      //   resourceQuery: /url/, // *.svg?url
      // },

      // 示例 import Svg from './star.svg'
      // {
      //   test: /\.svg$/i,
      //   issuer: /\.[jt]sx?$/, // 限定 svgr 适用文件类型的范围
      //   resourceQuery: { not: [/url/] }, // exclude react component if *.svg?url
      //   use: ['@svgr/webpack'],
      // },
    ],
  },
}

// 与 url-loader 一起使用
// import starUrl, { ReactComponent as Star } from './star.svg'
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/i,
        issuer: /\.[jt]sx?$/,
        use: ['@svgr/webpack', 'url-loader'],
      },
    ],
  },
}

svgr 支持如下方式使用 React svg 组件

import starUrl, { ReactComponent as Star } from './star.svg'

const App = () => (
  <div>
    <img src={starUrl} alt="star" />
    <Star />
  </div>
)

命令行

通过命令行自定义 antd-mobile-icons 组件

图标在 iconfont 平台做管理,可以选中需要的图标,批量下载到本地,然后通过工具自动转换为 React 组件

npm install @svgr/cli --save-dev
./node_modules/.bin/svgr -h
./node_modules/.bin/svgr ./source -d ./dist

svgr ./source -d ./dist
{
  "scripts": {
    "svgr": "svgr ./source -d ./dist",
    "start": "webpack serve --config ./webpack.config.js --mode development"
  }
}

默认 iconfont 下载的图标,有可能 fill="currentColor" 属性不规范,通过 template 无法批量完成处理,此问题只能制作图标时注意规范。

以下为命令行批量将 svg 转为 React 组件模板

// my-template.js 示例
// npx @svgr/cli --template my-template.js -- my-icon.svg
const template = (variables, context) => {
  const { imports, interfaces, componentName, props, jsx, exports } = variables
  const { tpl, options } = context

  // console.log(jsx)

  return tpl`
${imports}

${interfaces}

const ${componentName} = (${props}) => {
  props = { ...props, fill: 'currentColor' };
  return ${jsx};
};

export default ${componentName};
`
}

module.exports = template

使用 webpack

npm install @svgr/webpack --save-dev

webpack 配置

const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: path.resolve(__dirname, './src/index.js'),
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      },
    ],
  },
  // ...
};