ant-design / ant-design-icons

⭐ Ant Design SVG Icons
https://ant.design/components/icon/
MIT License
964 stars 582 forks source link

Refactor icons-svg@4.x with gulp #104

Closed HeskeyBaozi closed 4 years ago

HeskeyBaozi commented 5 years ago

React/React-Native/Vue/Angular各自社区实现对应支持tree shaking的图标组件或指令,分支在仓库ant-design-icons下的next-v4分支

各自社区支持tree shaking的图标组件或指令实现后,即可去掉WIP:前缀。 同时原来的icons-svg-legacy可以考虑删除。 之后将next-v4分支合并到master分支上。

HeskeyBaozi commented 5 years ago

之前pr #100

包相关变动

packages/icons 中的包名由 @ant-design/icons-svg 修改为 @ant-design/icons-svg-legacy。包名 @ant-design/icons-svg 由项目下的目录重写的 packages/icons-svg 继承。

新的 @ant-design/icons-svg 包和原来的版本 ( 4.0.0-alpha.0@ant-design/icons <= 2.1.1 ) 相比,有如下改动:

最终用户得到的目录如下:

es
inline-svg # 此为处理后存放的svg图标
lib
package.json
ReadMe.md

这些改动的原则都是倾向于按需引入,保证主入口文件只有图标的导出,使得 import * as allIcons from '@ant-design/icons-svg' 只会导出图标信息。

此PR来源于

https://github.com/ant-design/ant-design-icons/pull/90 @ant-design/icon-kit 这个脚手架已自我废弃

目前图标

查看当前全部图标

为什么

Before icon-kit (rxjs) gulp
old-generate-use-15s new after
15.42s 6.88s 9.55s
HeskeyBaozi commented 5 years ago

各个社区在开发时,可以先构建一次@ant-design/icons-svg(未发包),该包位于packages/icons-svg。之后可使用 lerna link 到对应社区的组件包进行开发。

开发思路可以分为两个阶段:

思路示例:

Angular (仅供参考)

// generate.ts
// $ node --require ts-node/register/transpile-only generate.ts
import * as allIconDefs from '@ant-design/icons-svg';
import { renderIconDefinitionToSVGElement } from '@ant-design/icons-svg/es/helpers';
import { IconDefinition } from '@ant-design/icons-svg/es/types';
import * as path from 'path';
import { writeFile, emptyDir } from 'fs-extra';

export interface IconDefinitionNg extends Omit<IconDefinition, 'icon'> {
  identifier: string;
  icon: string;
}

export function walk<T>(fn: (iconDef: IconDefinitionNg) => Promise<T>) {
  return Promise.all(
    Object.keys(allIconDefs).map((identifier) => {
      const iconDef = (allIconDefs as { [id: string]: IconDefinition })[
        identifier
      ];
      const { name, theme } = iconDef;
      const inlineSvg = renderIconDefinitionToSVGElement(iconDef, {
        // the options only affect the two-tone icons.
        placeholders: { primaryColor: '#333', secondaryColor: '#E6E6E6' }
      });

      return fn({ name, theme, icon: inlineSvg, identifier });
    })
  );
}

(async () => {
  await emptyDir(path.resolve(__dirname, `../lib/icons/defs`));

  const publicApiRows = await walk(async ({ identifier, ...iconDef }) => {
    await writeFile(
      path.resolve(__dirname, `../lib/icons/defs/${identifier}.ts`),
      `export const ${identifier} = ${JSON.stringify(iconDef)};`,
      'utf8'
    );

    return `export { ${identifier} } from './defs/${identifier}';`;
  });

  await writeFile(
    path.resolve(__dirname, `../lib/icons/public_api.ts`),
    publicApiRows.join('\n'),
    'utf8'
  );
})();

生成效果: 002

React (仅供参考)

// generate.ts
// $ node --require ts-node/register/transpile-only generate.ts

import * as allIconDefs from '@ant-design/icons-svg';
import { IconDefinition } from '@ant-design/icons-svg/es/types';
import * as path from 'path';
import { writeFile, emptyDir } from 'fs-extra';
import { template } from 'lodash';

export interface IconDefinitionWithIdentifier extends IconDefinition {
  identifier: string;
}

export function walk<T>(
  fn: (iconDef: IconDefinitionWithIdentifier) => Promise<T>
) {
  return Promise.all(
    Object.keys(allIconDefs).map((identifier) => {
      const iconDef = (allIconDefs as { [id: string]: IconDefinition })[
        identifier
      ];
      return fn({ identifier, ...iconDef });
    })
  );
}

(async () => {
  await emptyDir(path.resolve(__dirname, `../src/icons`));

  const render = template(`
  import React from 'react';
  import <%= identifier %> from '@ant-design/icons-svg/es/<%= identifier %>';
  import AntdIcon, { AntdIconProps } from '../components/AntdIcon';

  const <%= _identifier %> = (props: AntdIconProps) => <AntdIcon {...props} icon={<%= identifier %>} />;
  export default <%= _identifier %>;
`);

  await walk(async ({ identifier }) => {
    // It will be better if an react antd icon component has theme suffix.
    // or use outline as default theme like this:
    const _identifier = identifier
      .replace(/Outline$/, '')
      .replace(/Fill$/, 'Filled')
      .replace(/TwoTone$/, 'TwoTone');

    await writeFile(
      path.resolve(__dirname, `../src/icons/${_identifier}.ts`),
      render({
        identifier,
        _identifier
      }),
      'utf8'
    );
  });
})();

效果: image

Vue (仅供参考)

// generate.ts
// $ node --require ts-node/register/transpile-only generate.ts

import * as allIconDefs from '@ant-design/icons-svg';
import { IconDefinition } from '@ant-design/icons-svg/es/types';
import * as path from 'path';
import { writeFile, emptyDir } from 'fs-extra';
import { template } from 'lodash';

export interface IconDefinitionWithIdentifier extends IconDefinition {
  identifier: string;
}

export function walk<T>(
  fn: (iconDef: IconDefinitionWithIdentifier) => Promise<T>
) {
  return Promise.all(
    Object.keys(allIconDefs).map((identifier) => {
      const iconDef = (allIconDefs as { [id: string]: IconDefinition })[
        identifier
      ];
      return fn({ identifier, ...iconDef });
    })
  );
}

(async () => {
  await emptyDir(path.resolve(__dirname, `../src/icons`));

  const render = template(`
  import Vue from 'vue';
  import Icon from '../components/Icon';
  import <%= identifier %> from '@ant-design/icons-svg/es/<%= identifier %>';

  export default Vue.component('<%= kebabCaseIdentifier %>', {
    functional: true,
    render: (h, { data, children }) => h(Icon, { ...data, type: <%= identifier %> }, children)
  });
`);

  await walk(async ({ identifier, ...iconDef }) => {
    const { name, theme } = iconDef;
    await writeFile(
      path.resolve(__dirname, `../src/icons/${identifier}.ts`),
      render({
        identifier,
        kebabCaseIdentifier: `${name}-${theme}`
      }),
      'utf8'
    );
  });
})();
wzhudev commented 5 years ago

赞赞赞

vagusX commented 5 years ago

@HeskeyBaozi 我有个想法就是 icons-svg 这边 theme 也统一改成 Filled/Outlined/TwoTone 避免从 fill/outline/twoTone 转换,这里显得有点没有必要

HeskeyBaozi commented 5 years ago

@HeskeyBaozi 我有个想法就是 icons-svg 这边 theme 也统一改成 Filled/Outlined/TwoTone 避免从 fill/outline/twoTone 转换,这里显得有点没有必要

这个可以的。做好和其他开发者的沟通工作即可。我会尽快完成。

HeskeyBaozi commented 5 years ago

确认一下命名风格:

// 以 account-book 为例
// @ant-design/icons-svg/es/asn/AccountBookFilled
var AccountBookFilled = {
  "name": "account-book",
  "theme": "filled",
  "icon": {
    "tag": "svg",
    "attrs": {
      "viewBox": "64 64 896 896",
      "focusable": "false"
    },
    "children": [{
      "tag": "path",
      "attrs": {
        "d": "M880 184..."
      }
    }]
  }
};

// @ant-design/icons-svg/es/asn/AccountBookOutlined
var AccountBookOutlined = {
  "name": "account-book",
  "theme": "outlined",
  "icon": {
    "tag": "svg",
    "attrs": {
      "viewBox": "64 64 896 896",
      "focusable": "false"
    },
    "children": [{
      "tag": "path",
      "attrs": {
        "d": "M880 184..."
      }
    }]
  }
};

// @ant-design/icons-svg/es/asn/AccountBookTwoTone
var AccountBookTwoTone = {
  "name": "account-book",
  "theme": "twotone",
  "icon": function icon(primaryColor, secondaryColor) {
    return {
      "tag": "svg",
      "attrs": {
        "viewBox": "64 64 896 896",
        "focusable": "false"
      },
      "children": [{
        "tag": "path",
        "attrs": {
          "d": "M712 304...",
          "fill": secondaryColor
        }
      }, {
        "tag": "path",
        "attrs": {
          "d": "M639.5 414...",
          "fill": primaryColor
        }
      }, {
        "tag": "path",
        "attrs": {
          "d": "M880 18...",
          "fill": primaryColor
        }
      }]
    };
  }
};

短横线连字形式可以由name + '-' + theme得到,通常用于Vue组件名称形式中

vagusX commented 5 years ago

icons-react 库已完成对应 更新

zWingz commented 5 years ago

观察了下, 目前使用icons-react是需要逐个icon引入并且使用

我的做法是一次性把需要用到icon引入进来, 然后通过svg-sprite 形式使用, 使用时候只需要用过<icon name='xxxx'/>, 不需要多次import icon

刚完成vue版, 不知道是否有其他坑

tangjinzhou commented 5 years ago

@zWingz Vue版本完成了?可以提pr上来

vagusX commented 5 years ago

@zWingz 欢迎 pr

zWingz commented 5 years ago

目前我开发方案是使用svg-symbol来实现, twotone方案是通过css variable, 可能兼容性上跟ant-design所要求的有点出入

tangjinzhou commented 5 years ago

icons-vue done

HeskeyBaozi commented 4 years ago

目前各个社区的进度跟进方面 Vue 社区已经完成了。

关于合并有一些要注意的点:

AngularReact Native 方面:

https://github.com/ant-design/ant-design-icons/blob/225eafec1e9380d589530b452974c06d249ce6c3/packages/icons-react-native/scripts/index.js#L17

需要修改路径到 icons-svg/svg,同时注意主题风格名字的变化 fill -> filledoutline -> outlined

https://github.com/ant-design/ant-design-icons/blob/225eafec1e9380d589530b452974c06d249ce6c3/packages/icons-angular/build/env.ts#L6

且注意主题风格名字的变化 fill -> filledoutline -> outlined

BANG88 commented 4 years ago

好久没动 卡在 lerna bootstrap 😢

BANG88 commented 4 years ago

@HeskeyBaozi 我的修改太少了。 我直接push到v4了..

vagusX commented 4 years ago

我这边统计了下图标的变化,主要是新增了图标,以及删除了 typo 错误的图标

https://github.com/vagusX/icons-v4-diff/pull/1/files

vagusX commented 4 years ago
  • [x] ant-design-icons 仓库新建 next-v4 分支,之后社区的next-v4分支 将会提pr,该pr包含对原icons-svg的命名和新的icons-svg增加。

React/React-Native/Vue/Angular各自社区实现对应支持tree shaking的图标组件或指令,分支在仓库ant-design-icons下的next-v4分支

  • [x] @ant-design/icons (React) @vagusX #112
  • [x] @ant-design/icons-vue (Vue) @tangjinzhou #153
  • [ ] @ant-design/icons-angular (Angular) @wendzhue
  • [x] @ant-design/icons-react-native (React-Native) @bang88

各自社区支持tree shaking的图标组件或指令实现后,即可去掉WIP:前缀。 同时原来的icons-svg-legacy可以考虑删除。 之后将next-v4分支合并到master分支上。

@wendellhu95 https://github.com/ant-design/ant-design-icons/pull/196 这个 mr 合并了,我理解 ng 的也完成了哈

wzhudev commented 4 years ago

嗯,完成~

在 2019年12月21日,16:47,vagusX notifications@github.com 写道:

 ant-design-icons 仓库新建 next-v4 分支,之后社区的next-v4分支 将会提pr,该pr包含对原icons-svg的命名和新的icons-svg增加。 React/React-Native/Vue/Angular各自社区实现对应支持tree shaking的图标组件或指令,分支在仓库ant-design-icons下的next-v4分支

@ant-design/icons (React) @vagusX #112 @ant-design/icons-vue (Vue) @tangjinzhou #153 @ant-design/icons-angular (Angular) @wendzhue @ant-design/icons-react-native (React-Native) @bang88 各自社区支持tree shaking的图标组件或指令实现后,即可去掉WIP:前缀。 同时原来的icons-svg-legacy可以考虑删除。 之后将next-v4分支合并到master分支上。

@wendellhu95 #196 这个 mr 合并了,我理解 ng 的也完成了哈

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

vagusX commented 4 years ago

后续 actions:

后续原稳定分支的修复都在 legacy 上发布和修复 master 分支用来开发新的分支代码

wzhudev commented 4 years ago

分支不如叫 legacy

vagusX commented 4 years ago

分支不如叫 legacy

有道理

vagusX commented 4 years ago

@HeskeyBaozi 这个 issue 可以先 close 掉?