编写自己的 SVG 图标库

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:在做按需加载,不引入 runtime 和额外配置,从一个组件库来说,关乎其易用性,这样下来上述三种方案都各有优缺点。思来想去,最好是每个组件都是一个纯粹的 React 组件,其 render 返回 SVG 的 XML,也就是把 SVG icon 改写成一个 React 组件。类似这种:

在做 one-react 组件库时,思考如何对组件库各组件中用到的图标作统一管理。在这之前,都是直接 「hard code」 写入 SVG code,一旦出现同一个图标在不同组件中引入时,本质上是在反复复制一段代码,后续图标更新时会产生不小的工作量,独立的图标库势在必行。

调研了几种社区常见方案:

iconfont

  • 这种方案在 SVG 图标文件的基础上,利用脚本生成几种不同格式的字体文件(ttf/woff/eot),亦可通过 iconfont.cn 管理图标文件,然后通过 @font-face 加载字体文件,最后在伪元素的 content 中填写对应图标的编码渲染出图标。
  • 兼容性好,理论上能兼容到 IE6。
  • 繁琐之处在于处理 SVG 生成多个字体文件,编写生成多个图标字体编码的 className 样式表,字体文件要按需加载会比较麻烦。

SVG Sprite

  • 通过将 SVG 文件合并成一个 SVG sprite 并加载到一个 display: none 的元素中,使用时则通过 SVG 的 use 传入图标 id 后渲染出图标。
  • 在 webpack 配置中引入 svg-sprite-loader 即可,配置简单,可按需加载和打包。
  • 若在组件库中使用该方案,组件库的用户在使用时,需自行在 webpack 配置中引入对应 loader,处理对应 node_modules 下组件库里的 SVG 文件。
  • svg-sprite-loader 有自己的 runtime(svg-baker-runtime)。

SVG to React

  • 可使用如 svg-react-loader ,直接 require 一个 SVG 转换成 React 组件。
  • 同上一个方案,组件库若引入,用户也得额外配置 svg-react-loader
  • 可按需引入。

按需加载,不引入 runtime 和额外配置,从一个组件库来说,关乎其易用性,这样下来上述三种方案都各有优缺点。思来想去,最好是每个组件都是一个纯粹的 React 组件,其 render 返回 SVG 的 XML,也就是把 SVG icon 改写成一个 React 组件。类似这种:

编写自己的 SVG 图标库

重新梳理下思路,明确要做的事情:

Semantic Release

将 SVG 转化成 React 组件

上面提到了一个步骤「将 SVG 的 XML 写入对应 React 组件的 render 函数中」,最初验证整体方案可行性时,是手动复制粘贴的,但是我们现在要把这一步变成自动化的,即每次增加一个新图标,跑一个脚本即可生成对应的 React 组件。

刚好之前 star 过 svgr 这个项目,这个项目能基于 h2x 将 HTML 编译成 JSX,支持 custom template,支持 svgo 压缩 SVG,支持 Prettier,有个在线的 REPL 可以体验。

注意:本文初次整理时 svgr@v4 尚未发布,因此下方提到的 svgr 相关都是基于 svgr@v3 的,后续笔者考虑将本文的内容和关联的项目升级到最新版本的 svgr。

将从 Sketch 中导出的 SVG 文件放到 src/assets 目录下,通过 svgr 将 SVG 编译成 tsx 文件,并输出到 src/icons 目录中。

编写自己的 SVG 图标库

不得不提,svgr 的配置参数十分神奇,比如它支持 config 文件,但是 out-dir , ext 等参数必须通过命令行参数传进去。

其中用到的 custom template 如下:

编写自己的 SVG 图标库

svgr.config.js 文件中定义好 SVG 标签上的 props,包括默认样式、 sizefill 等。如下所示:

编写自己的 SVG 图标库

执行对应的 npm scripts,将 SVG 编译成 React 组件。如下示例:

编写自己的 SVG 图标库

将编译好的 React 组件统一 export

通过脚本,读取 src/icons 目录下的所有 tsx 文件,以 export { SvgAbc } from './icons/abc' 的形式写入 src/index.ts 中。

脚本代码如下:

编写自己的 SVG 图标库

在 CI 阶段执行编译

我们期望的是每次新增或修改了 SVG 文件,无需本地手动执行脚本编译成 React 组件并 export,直接 commit 并 push,让 CI 把编译好的结果提交回来并执行发布流程。

  • build 之前先执行 npm run getIcons 命令,将 SVG 文件转化成 React 组件并统一导出。
  • 使用 @semantic-release/git 自动提交在 CI 上编译生成的 .ts/.tsx 文件。
  • 发布到 NPM。

对应的 .travis.yml 配置如下:

编写自己的 SVG 图标库

通过 release.config.js 文件配置 semantic-release

编写自己的 SVG 图标库

semantic-release 默认的 plugins 有四个:

  • @semantic-release/commit-analyzer :基于 conventional-changelog 分析 commit 信息。
  • @semantic-release/release-notes-generator :基于 conventional-changelog 生成 release 日志的内容。
  • @semantic-release/npm :发布 NPM 包。
  • @semantic-release/github : 发布 GitHub release 并且写入 release 日志。

要注意的是需要将 @semantic-release/git 插件放在 @semantic-release/npm 之前执行,因为要保证 release 的版本对应的是已完成编译的代码,即基于 @semantic-release/git 自动 commit 后的最新版本。

配置好的 semantic-release 流程如下:

编写自己的 SVG 图标库

完成上述配置后, @semantic-release/git 会在 CI 流程中,将生成新的组件代码 commit 回来:

编写自己的 SVG 图标库

在 GitHub 上也能看到 bot 自动提交回来的 commit:

编写自己的 SVG 图标库

上图中合并 mr 时会触发一次 Travis CI build,而这个 build 中,若 bot 提交一个新的 commit 回来的话,会再产生一个新的 build,但这个 build 并不会发布代码,因为上一个 build 中的 release 已经是基于最新代码(包含这个 commit的),这个 build 看起来有点「浪费」。

至此,我们达到了目的,只需要将 SVG 文件放到 src/assets 目录下并提交到远程,其他的事就交给 CI 处理即可。

使用示例

编写自己的 SVG 图标库

完整的项目代码请见我的 GitHub Repo

0


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

构建可扩展的Web站点

构建可扩展的Web站点

Cal Henderson / 徐宁 / 电子工业出版社 / 2008 / 58.00元

随着Web 2.0网站的蓬勃发展,如何成功地构建可扩展的Web站点成为网站开发人员必备的技能。本书是Flickr.com的主力开发人员讲解构建可扩展的Web站点的经典之作。本书主要介绍了Web应用程序的概念、体系结构、硬件需求、开发环境的原则及国际化、本地化和Unicode等基本内容,并为解决Web应用程序的数据安全、电子邮件整合、远程服务交互、应用程序优化、扩展、监测和预警、开放API等问题提供......一起来看看 《构建可扩展的Web站点》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具