写点什么

携程机票 Sketch 插件开发实践

  • 2020 年 2 月 15 日
  • 本文字数:5361 字

    阅读完需:约 18 分钟

携程机票Sketch插件开发实践

Sketch 是伴随移动应用程序崛起而流行的 UI 设计工具。2014 年 Sketch V3 增加 Symbols 功能,在 UI 设计工具领域的优势越来越大。它持续改进和增强功能,不断加强对插件社区的建设,吸引越来越多的开发者进入。




随着 Design System 的普及和流行,许多大公司都在设计插件领域有所投入,如 Google,Airbnb 等,同时诞生了一系列提供设计管理的初创企业,如 Abstract,UXPIN 等。中国很多大中型互联网企业也开始研制自己的设计系统和插件工具,例如 Dapllo,Kitchen,Fusion,Anto。


2016 年,携程机票 UED 团队主力生产工具完全切换到 Sketch。与此同时,机票前端研发技术团队也关注到设计系统和插件工具规范化自动化对业务交付工作流程的加速作用。于是设计团队与前端技术团队开始携手探索设计语言升级,从业务需求项目实践中提炼通用规范,落地插件工具系统,并输出一整套设计资源管理规范和流程。


一、设计资源管理

产品的设计语言是一家公司留给消费者最直观的形象,通常包含品牌 Logo,颜色,文字,符号,插画,动画和文案话术等。而 Design System 是为了让设计语言落地执行而构建的解决方案,包括设计指导文档,设计资源,组件代码和工具等。


设计资源的共享和版本管理一直困扰着设计师们。Sketch 通过引入 Symbols,Library 等功能解决了共享组件问题,但在颜色,文字排版,图标管理等问题上依然缺少足够好的解决方案,需要各家公司针对自身的特点开发插件和服务去解决这些问题。



二、Kirby - Sketch Plugin

Kirby 是携程机票前端团队的 Sketch Plugin 系统代号,故事源于一次 Sketch 版本升级引起的标注导出功能失效问题。


Sketch 社区著名插件 Sketch Measure,它将设计稿和数据参数导出 HTML 网页,供技术人员查看,节省从设计到开发过程的沟通成本。但 Sketch 的版本升级经常致其无法正常使用,维护者也无暇快速修复问题,设计师们若继续使用,将被迫使用一个低版本 Sketch。


为了让设计师能够使用 Sketch 最新版本,并修复 Sketch Measure 缺陷功能,Kirby 诞生。


之后我们陆续添加更多功能,从 Design Token,到 Icon System,再到 Component,以及 Template,一步步接近成熟和完整。


Kirby 目前已交付若干重要特性:


2.1 设计语言规范约束

Color Pallete



Typography



Shadow



2.2 设计稿静态扫描检查

方便设计师查找和修正问题。



字体与图标系统



在线版设计资源模版库



三、Sketch Plugin 开发技术

在插件开发实现过程中,我们遇到许多交叉技术领域的问题,也因此进行了多次技术重构。


3.1 基础知识

Sketch 官方技术文档提供了简单介绍:


1)Sketch 插件是按照特定方式管理的一个文件夹,包含一个或多个 scripts,每个 script 含有若干扩展 Sketch 用途的命令。


2)插件主要使用 Javascript 语言编写,支持 ES6 语法,但运行环境既不是浏览器也不是 Nodejs,而是 Hybrid SketchAPI for macOS Native 运行环境。


从最简单的部分看起:


打开一个 Sketch 文件,control + shift + k 快捷键开启 Run Script 面板,输入:


const sketch = require('sketch')sketch.UI.message('Hello, world!')
复制代码


运行以上代码,将在 Sketch 文件下方区域显示 Toast:Hello, world,该 Script 面板常用于快速测试脚本 API。


3.2 API 概述

The plugin system in Sketch gives you full access to the app’s internals and the core frameworks in macOS. So you have an immense power to build almost anything.


Sketch 插件系统开放了几乎所有权限,让许多天马行空的想法可以实现。但是插件开发者需要及时关注 Sketch 版本升级,其向下兼容性较差,或者说官方团队并不重视这部分。典型案例例如,著名插件 Paddy,在开发 V2.0 版本过程中,因 Sktech API 大量变更,原插件无法兼容,作者最终无力修复而放弃开发,非常可惜。


官方 API 有两个: Actions API, Javascript API。


3.3 Actions API

用于监听用户操作行为和触发的事件。据社区消息,该 API 未来会被新的 Events API 替代。它代表了 Sketch App 内部触发的事件,例如 CloseDocument, TogglePresentationMode 等, 细节详见官网:


https://developer.sketch.com/reference/action/


1)订阅 Actions


manifest.json 文件,配置相应 handlers。


示例:当 OpenDocument 事件被触发时调用 onOpenDocument handler 。


"commands" : [  ...  {    "script" : "my-action-listener.js",    "name" : "My Action Listener",    "handlers" : {      "actions": {        "OpenDocument": "onOpenDocument"      }    },    "identifier" : "my-action-listener-identifier"  }  ...],
复制代码


my-action-listener.js


export function onOpenDocument(context) {  context.actionContext.document.showMessage('Document Opened')}
复制代码


2)Action Context


Action 事件会将 context.actionContext 传递给 handler。有些 Action 包含两个状态,begin 和 finished,例如 SelectionChanged 。需分别订阅 SelectionChanged.begin 和 SelectionChanged.finished,否则会触发两次事件。


当我们不知道应该订阅哪个 Action 时,可以使用通配符。但运行时性能开销很大,建议仅在开发阶段使用。


示例:Terminal 打开通配符支持。


defaults write com.bohemiancoding.sketch3 actionWildcardsAllowed -bool YES
复制代码


manifest.json 文件配置通配符。


{  ...  "handlers": {    "actions": {      "*": "onActionHandler"    }  }  ...}
复制代码


3.4 Javascript API

它是针对 Native API 的封装,目前还未涵盖所有场景,官方承诺未来将覆盖 90%。细节详见官网和 GitHub:


https://developer.sketch.com/reference/api/


https://github.com/BohemianCoding/SketchAPI/blob/develop/CHANGELOG.json



3.5 开发环境

官方提供了一个打包工具 skpm, 用于快速上手插件开发。它基于 webpack,项目根目录下存放 webpack.skpm.config.js, 用于工程配置修改。


安装示例


npm install -g skpmskpm create my-plugincd my-pluginnpm run build# 然后在 Plugins -> my-plugin -> MyCommand 中运行插件命令
复制代码


典型的插件开发工程的目录结构示例


├── .gitignore├── README.md├── src                         // sources│   ├── manifest.json           // plugin's manifest│   └── my-command.js           // source code of the command├── node_modules│   └── skpm                    // the sketch plugin developer toolchain├── my-plugin.sketchplugin      // compilation output, the actual plugin│   └── Contents│       ├── Resources│       └── Sketch│           ├── manifest.json│           └── my-command.js└── package.json
复制代码


3.6 崩溃保护

当 Sketch 运行发生崩溃,它会停用所有插件以避免循环崩溃。对于使用者,每次崩溃重启后手动在菜单栏启用所需插件非常繁琐。因此可以通过如下命令禁用该特性。


defaults write com.bohemiancoding.sketch3 disableAutomaticSafeMode true
复制代码


3.7 插件缓存

通过配置启用或禁用缓存机制:


defaults write com.bohemiancoding.sketch3 AlwaysReloadScript -bool YES
复制代码


但是该方法对于某些场景不适用。例如当正在使用一个 long-running 脚本时,即 Javascript Context 不变,并存储在内存中,那么则需要重启 Sketch 或通过 coscript.setShouldKeepAround(false) 使改动生效。


3.8 WebView 调试

如果插件实现方案使用 WebView 做界面,可通过以下配置开启调试功能。


defaults write com.bohemiancoding.sketch3 WebKitDeveloperExtras -bool true
复制代码


3.9 打印输出日志

Sketch 运行环境 JavascriptCore 的日志输出方式:


1)macOS console.app 中搜索 与 sketch 相关的 Filter。


2)查看 ~/Library/Logs/com.bohemiancoding.sketch3/Plugin Output.log。


3)运行 skpm log 查看上述文件,-f 参数使用 stream 方式查看。


4)使用 skpm 开发的插件,可以使用 console.log 语法,需安装 sketch-dev-tools。


3.10 代码调试

Safari 浏览器开发工具可用于插件的 Javascript 代码调试。


Developer > name of your machine > Automatically Show Web Inspector for JSContexts

同时启用选项 Automatically Pause Connecting to JSContext


3.11 Objective-C Classes

Sketch 对外暴露了全部内部方法的调用权限,其 Objective-C 类 通过 Bridge 提供 Javascript API 调用。


3.12 插件 GUI 的实现

用户(设计师)可以通过以下几种方式使用插件:


1)菜单 -> 插件 -> 选择插件已定义的 Handler


2)Handler 预定义的快捷键


3)插件提供的其他 GUI 方案


其他 GUI 方案有 Native(Appkit) 和 WebView ,以 Kirby 为例,目前大部分 UI 由 WebView 实现。这种方案对于 Web 前端技术人员上手学习成本较低。 skpm 提供了已封装好的基于 WKWebView 的 sketch-module-web-view,其 API 设计接近 Electron,细节详见 GitHub。


https://github.com/skpm/sketch-module-web-view/blob/master/docs/browser-window.md


除此之外,skpm 还提供了一些供 JavaScript 调用的 Native 控件,例如 Dialog:


import dialog from '@skpm/dialog'console.log(  dialog.showOpenDialog({    properties: ['openFile', 'openDirectory', 'multiSelections']  }))
复制代码


3.13 CocoaScript GUI

CocoaScript is built on top of Apple’s JavaScriptCore, the same JavaScript engine that powers Safari. So when you write in CocoaScript, you are really writing JavaScript.

CocoaScript also includes a bridge which lets you access Apple’s Cocoa frameworks from JavaScript. This means you have a ton wonderful classes and functions you can use in addition to the standard JavaScript library.


Sketch 插件通过 Mohca / CocoaScript 连接到 Objective-C / Cocoa。Javascript 调用 Objective-C 方法,需要将方法名的冒号改为下划线(最后一个可选),所有 selector 连接成一个连续的字符串。例如 executeOperation:withObject:error: 将转为 executeOperation_withObject_error()。


示例:


/*打开文件对话框,使用 Appkit NSOpenPanel。https://developer.apple.com/documentation/appkit/nsopenpanel?language=objc*/var openPanel = NSOpenPanel.openPanel()openPanel.setCanChooseDirectories(false)openPanel.setCanChooseFiles(true)openPanel.setCanCreateDirectories(false)openPanel.setDirectoryURL(NSURL.fileURLWithPath('~/Documents/'))openPanel.setTitle('Choose a file')openPanel.setPrompt('Choose')openPanel.runModal()

//设置异步操作不被 Sketch GC回收COScript.currentCOScript().shouldKeepAround = true//异步执行完成后,释放COScript.currentCOScript().shouldKeepAround = false
复制代码


3.14 Native GUI

实现 Native GUI 的难点在于“合适的时机”找到“正确的实例”。Actions API 用于解决“合适的时机”问题。而寻找“正确的实例”相对复杂一些。首先从 Sketch-Headers 入手,搜索与事件有关的方法。


例如,当我们需要扩展 “创建组件“ 对话框,该对话框在 “创建组件” 事件发生时才会出现,因此在 Actions API 中搜索与 symbol 有关的事件,找到名为 Create Symbol 的 Action。然后继续搜索关键字 CreateSymbol,可找到如下结果。



code 能够以黑盒方式分析系统当前运行的应用程序界面,提取对于插件开发有用的信息。使用 Xcode 分析 Sketch 可知,MSCreateSymbolNamingSheet 继承自 NSWindowController,如下示例代码可获取其调用对象。


const doc = context.actionContext.document;const docData = doc.documentData();const window = doc.window();const sheetWindow = window.attachedSheet();const createSymbolNameingSheet = sheetWindow.windowController();
复制代码



3.15 Webview GUI

Webview 与 Plugin 之间需要实现双向通讯互操作。Webview 可通过 WKWebView delegates 向 Plugin 发送消息,Plugin 则通过 webView.evaluateJavaScript_completionHandler() 触发 Webview 执行 Javascript 代码。


export function createPopoverWKHandler () {    return new MochaJSDelegate({        'userContentController:didReceiveScriptMessage:': (function (controller, message) {            let body = Utils.toJSON(message.body()),                { key, value } = body            switch (key) {                case 'setTypography':                    Utils.setTextStyle(value)                    break            }        })    })}
复制代码


四、Milestone One

一个功能完整易用性佳的 Sketch 插件系统,除了上述技术实现细节,还有很多需要思考兼顾的方面。例如,设计文件版本管理,Sketch 版本兼容性,用户配置文件,云同步协作,用户(企业内网)鉴权认证接入。


Kirby 每一个新增功能都是围绕着从设计到研发再到交付的一致性和复用性,这也正是设计系统所要解决的核心问题。


我们 hack 的不仅是一个软件,而是完整的 DesignOps 工作流程。


作者介绍


尹正波,携程机票研发部前端工程师,专注设计和开发的交叉领域,用系统和工具改进设计体验和交付。


本文转载自公众号携程技术(ID:ctriptech)。


原文链接


https://mp.weixin.qq.com/s/b0jPTft4nKhVFraJl6H3_A


2020 年 2 月 15 日 17:46603

评论 1 条评论

发布
用户头像
模版库这边,插件展示模板是怎么个方案实现的呢?去读了Sketch文件的JSON数据解析出来后去渲染的?
2020 年 06 月 30 日 11:36
回复
没有更多了
发现更多内容

开发者必看,面试官心中的最佳数据库人才模型是什么样?

华为云开发者社区

面试 开发者 华为云数据库 数据库人才

只会重装系统的运维,不是好运维

运维研习社

Linux 5月日更 系统修复

【欢乐叫地主流程】需求分析/用例设计+游戏测试工作流程/测试计划

程序员阿沐

软件测试 需求分析 测试用例 游戏测试 测试计划

网页视频下载教程(腾讯, B站, 优酷, 爱奇艺)

科技猫

经验分享 教程 视频处理 工具分享 网页视频下载

腾讯T6大牛体系化带你学习Java面向对象,网友:这详解,太清晰了

牛哄哄的java大师

Java 面向对象 面向对象编程

大部分两三年经验的程序员水平是怎样的?

Java架构师迁哥

XML 文件解析

xcbeyond

XML配置 5月日更

SICP 习题2.6之丘奇数

程序员历小冰

函数式编程 SICP 5月日更

使用docker compose快速部署前后端分离项目案例

皮特王

nginx Docker Vue Docker-compose

精选Hive高频面试题11道,附答案详细解析

五分钟学大数据

大数据 hive 5月日更

技术干货|7个 React 性能提升技巧

拍乐云Pano

React

工商银行分布式服务 C10K 场景解决方案

阿里巴巴云原生

容器 微服务 云原生 监控 应用服务中间件

华为云PB级数据库GaussDB(for Redis)揭秘第九期:与HBase的对比

华为云开发者社区

HBase 华为云 开源数据库 NoSQL数据库 数据库GaussDB(for Redis)

七面阿里险幸上岸,入职就是40*16K。网友:Java 面经交出来

Java 程序员 架构 面试 计算机

腾讯云大神亲码“redis深度笔记”,从基础到源码,应有尽有

Java 编程 程序员 架构

大数据实战:网站流量日志数据分析

大数据技术指南

大数据 5月日更

5月,腾讯最新职级技术要求曝光,Linux炸了。

linux大本营

c++ Linux 后台开发 架构师 服务器开发

两年半,50W的offer,三本,普通前端如何打好自己的牌

月哥

面试

整天用对象,你知道Java中对象的内存布局吗?

码农参上

Java JVM 签约计划第二季

恍然大悟丨Java 中 RMI 的使用

Java架构师迁哥

高德 Serverless 平台建设及实践

阿里巴巴云原生

Serverless 运维 云原生 监控 中间件

详解百度富媒体检索比对系统的关键技术

百度Geek说

大数据 后端 检索 #富媒体#

自己动手丰衣足食——自定义下拉框vue组件

空城机

vue.js 大前端 vue cli 5月日更 编写组件

微服务的灾难

Xargin

微服务 microservice 架构·

Python OOP-5

若尘

oop Python编程 5月日更

jmeter命令行执行测试并对测试报表进行初步分析

行者AI

测试 Jmeter

一个朋友学会Java泛型后直接薪资翻倍!

北游学Java

Java 泛型

打破思维定式(六)

Changing Lin

5月日更

lowcode 和 nocode 没有穿衣服

Xargin

lowcode nocode

携程机票Sketch插件开发实践_技术管理_尹正波_InfoQ精选文章