背景
为了解决在维护 Web 图标库时所面临的痛苦,期望打造最友好的从设计到研发图标交付方案,我希望它们能让更多的开发者和设计师受益,让网站建设更简单、更快速,更高效。
目前团队没有统一的图标库,对于图标的使用根据业务有两种,针对移动端(H5)设计交付设计稿后研发图片形式集成到项目中使用;对于 Web 端设计同学有在 Iconfont 维护字体图标也就是 IconFont 但是在维护过程比较繁琐。
在移动端场景,开发同学目前都是根据设计交付的设计稿在 Figma 导出图片资源使用,为了解决图片上传问题也开发相应 chrome 插件自动上传。再此场景使用图片也是可以的也是最基础的处理方式,问题就是相同图标无法复用。
Web Font 的发展得益于 CSS3 的 @font-face 属性。我们通常看到的图标都是以图片形式集成到项目中使用,IconFont 是一套字体图标由阿里妈妈(https://www.iconfont.cn/)团队出品,和我们使用自定义字体的方式是一样的,并且它是一种矢量图标,在 Web 端用到 IconFont 相对较多,但是很少移动端很少采用 IconFont;
IconFont 的使用支持 unicode 引用、 font-class 引用和 symbol 引用三种(https://www.iconfont.cn/help/detail?helptype=code),简单总结一下 iconfont 的优缺点。
优点
缩放不会模糊
跨平台一套资源可在 Web、iOS、Android 等多个平台使用
体积小包含几十个图标的字体包比一个 SVG 图标资源的体积还要小
缺点
更新成本高,目前没有特别友好的解决方案这样是本文最重要的原因
毕竟是字体图标在没有目前浏览器还没实现渐进式字体前还是有体验问题
虽然支持了彩色图标,但是无法和单色共存,也是依赖浏览器的彩色字体(COLR)规范的实现
随着我们前端一体化平台建设,我们在开发平台 Icon 库遇到最大的问题组件库的更新,也就是如何和设计协作,针对现有的 Iconfont 的协作方式目前无法满足,尤其针对在后续的更新维护,我们期望有个高效的协作方式,参考了业界 Juuun 开源 和 github icon 的技术方案实现了以下方案。
现在我们采用 Figma + Figma 插件 + gitlab CI 生成 SVG React/Vue 组件库。
对于设计只需要在 Figma Icon 页面运行插件。
由于我们公司当前设计工作都迁移在 Figma ,所以对于设计只需要在 Figma 维护一个 Icon 资源页面,当 Icon 需要更新时运行插件。
2.开发在飞书群收到 MR 通知。
对于研发可以从机器人了解到操作人、修改的内容,我们会根据仓库 ID 配置 MR 同步到多仓库,同时对比当前版本和私服最新版本的差异避免误操作。
3.审核修改内容合并 MR 执行 gitlab CI。
开发根据修改内容决定是否合并,如果合并 CI 会执行三个 Stages 分别是 install 获取依赖;build 通过 Figma API 获取 SVG 图标并构建成 React 和 Vue 版本组件库;publish 推送到 NPM 同时将图标站点推送到静态服务方便查找图标。
4.CI 发布到 npm 仓库、静态站点成功后飞书再次通知完成。
这时候开发界面可以根据版本预览到图标使用。(下图勘误:Reat 改为 React
5.开发使用时只需要更新对应的 npm 包(React、Vue)。
为什么选择 SVG 方案,回看图标演进从雪碧图到 iconfont,再到 SVG 图片,以及内联 SVG 代码的 React/Vue 组件,组件无疑是目前最方便的模式。参考 Vite 的核心理念就是一切都是按需的,模块只有在被请求时才会被转换。通过将所有图标编译成多个文件并将它们作为 npm 包分发来解决这个问题,因此我们开发 React 和 Vue 两个版本的 npm 包。同时 SVG 也有着以下特点:
SVG 可缩放矢量图形可以无损放大,也不会出现字体渲染锯齿问题表现最好
可着色能力我们可以使用 fill="currentColor" 来为 SVG 着色( CSS filters 和 CSS Mask 也可以)
灵活性 Inline SVG 直接写进 html 特别适合组件化
Inline SVG vs Icon Fonts (https://css-tricks.com/icon-fonts-vs-svg/)也给出了详细的 Inline Svg 与 Icon Fonts 之间的区别。当然 SVG 还有很多可玩比如:张鑫旭的《学习了,CSS 中内联 SVG 图片有比 Base64 更好的形式》等等,这里不过多介绍。
Figma 是一个 基于浏览器 的协作式 UI 设计工具,从推出至今越来越受到 UI 设计师的青睐很多的设计团队投入了 Figma 的怀抱。同时它已经推出的 Web API,通过 API 可以快速轻松地对内部公司工作流程进行脚本改进,或将 Figma 与其他工具集成。也就为我们从 Figma 图标文件生成 React/Vue 组件代码提供了能力。
Figma 插件类似于浏览器插件,使用 Web 技术(HTML/CSS/JS)进行开发。Figma 为插件提供的沙箱环境,可以访问到 Figma 全局变量用于获取文档内容,但是屏蔽了其它的各种全局变量,如 window、document 以及 fetch 等,可以避免恶意插件越权访问未授权的内容或破坏程序运行环境,提升安全性,你可以理解成 main 和 ui,其中 main 代码运行在沙箱之中,ui 部分代码运行在 iframe 之中。编程过程涉及到两个窗口之间的通信用 postMessage,其他详见官方文档(https://www.figma.com/plugin-docs/intro/)。
在设计执行插件通知时,为了避免删除或者重命名 ICON 而造成更新后老版本不兼容,新增了版本对比及时提醒:
通过 Web API 就可以拿到原始的 SVG图标资源,通过脚本对 SVG 图标处理,因此我们和设计定了一些规则:
确保图标基础尺寸是 24*24
每个图标必须编组 create component(Option+Command+K)
如果是彩色图标可以在命名中包含 colr
例如 social-wechatcolr-origin
图标命名请使用英文(不可以含 /)和 -,例如 dewu-logo-original
图标一般有描边(stroke)和填充(fill)两种样式,一个图标只能采用一种形式,不可以混合,默认 fill。想要转为 fill 样式,你可以使用 Outline Stroke(Shift+Command+O) 将图标转换为填充形状。
通过图标命名我们对 SVG 处理成单色(去掉原始颜色设置 fill="currentColor")、彩色(保留原始颜色)。
通过 GitLab API 获取、操作 GitLab 项目,详见官方文档。我们主要用到了 repository 、merge_requests 两个模块:
getPackageContent()
updatePackage()
createBranch()
createMRequest()
在通过 Figma Web Api 获取 SVG 文件并根据规则处理 SVG 文件后,我们需要编码把 SVG icon 转换成 React 和 Vue 的组件库。对于 SVG 文件处理使用了第三方 svgo,svgo 是 SVG Optimizer 的简写,是一个基于 Nodejs 的 SVG 文件优化工具,简单使用:
const Svgo = require('svgo')
const svgo = new Svgo({
plugins: [
{ convertShapeToPath: false },
{ mergePaths: false },
{ removeAttrs: { attrs: '(fill|stroke.*)' } },
{ removeTitle: true },
],
})
svgo.optimize(svg)
这里面的 { removeAttrs: { attrs: '(fill|stroke.*)' } }
是为了都给图标去色,当然对于彩色图标是不要去色。后面就是真的单个 SVG 文件生成组件,过程不再赘述。
GitLab CI 是 GitLab 内置的进行持续集成的工具,只需要在仓库根目录下创建 .gitlab-ci.yml 文件,并配置 GitLab Runner;每次提交的时候,gitlab 将自动识别到.gitlab-ci.yml 文件,并且使用 Gitlab Runner 执行该脚本。公司部署的 Gitlab 已有公共 Runner 所以我们只需编写 .gitlab-ci.yml 文件即可:
image: node:14.13.1
# 定义 stages
stages:
- install
- build
- publish
# 定义 job
install-staging:dep:
stage: install
tags:
- ep-share
only:
- master
script:
- echo "=====start install======"
- yarn
- echo "=====end install======"
artifacts:
expire_in: 60 mins
paths:
- node_modules/
build-staging:dep:
# 省略 build 代码
publish-staging:dep:
# 省略 publish 代码
我们设置 master 变化是执行:
我们通过把构建后的静态站点和组件包同步到 npm 私服上,由于我们内网部署了 unpkg 的 CDN 服务,所以我们只需要根据版本就能访问到相应的文档,例如:https://unpkg.shizhuang-inc.com/poizon-react-icon@1.0.6/docs/index.htmlpoizon-react-icon
的 1.0.6
版本文档,这样好处是不用再关心文档部署,同时也提供了文档版本管理的能力。
我们再来回顾完整交付更新流程,设计和研发整个过程只需要在自己工作流中简单操作即可完成图标交付,非常高效!当然任何技术方案都有它的优劣,最重要的还是根据需求取舍,未来渐进式字体和彩色字体的推进我们也可能会拥抱 font 同时也会有新的交付方案,但是对于我们目前阶段最合适的还是这套。
参考链接:
https://github.com/leadream/Figma-icon-automation
https://www.Figma.com/plugin-docs/intro/
https://www.iconfont.cn/help/detail?helptype=code
https://gist.github.com/banyudu/f7472f935897adfbb54cc8eb38dc5373
https://github.blog/2018-04-12-driving-changes-from-designs/
*文/揣歪