Reading view

There are new articles available, click to refresh the page.

iPhone 上最好的相机 App,是怎么和苹果决裂的?

过去十年,苹果在 iPhone 影像上的投入有目共睹。

从「Shot on iPhone」全球广告企划,到发布会上越来越长的相机环节,再到每年的 Pro 机型都在传感器尺寸、计算摄影和视频规格上不断加码。

▲ 图|WIRED

十九年来,苹果始终都在传递着这样的信息:对绝大多数人来说,他们只需要 iPhone 这一台相机。

但作为「绝大多数人的相机」,就必须能兼顾各种类型的需求才行。而 iPhone 始终有一个缺憾:iOS 的默认相机 app 一直偏向「傻瓜模式」——

对于早期 iPhone 来说,这种「傻瓜模式」可以很好地降低普通用户的心理门槛和使用难度,即使完全不懂摄影,拿着手机也能拍到不错的照片。

▲ iPhone 5 相机广告:Photos Every Day

但是随着 iPhone Pro 系列影像规格的逐年攀升,这种「傻瓜相机」的路径就显得格格不入了:

对于想要手动调整白平衡、对焦,或者需要参考斑马纹和直方图的用户来说,iOS 自带的相机应用无法提供足够的自由度,等于是白白浪费了 Pro 系列的硬件。

iOS 老牌第三方相机 app「Halide」填补的正是这个空缺。

这款由 Lux Optics 开发的相机应用,提供了 RAW 拍摄、手动对焦、直方图、色彩波形、焦峰提示等一整套专业控制,同时保持了极其克制、直觉化的交互设计。

▲ 图|Apple Developer

根据应用分析机构 Appfigures 的数据,Halide Mark II 更是目前 App Store 中最受欢迎的付费相机应用。

况且 Halide Mark II 的定价为 59.99 美元买断,或 19.99 美元/年订阅——在免费应用占绝对主流的 App Store 中,这个价格本身就是品质的证明。

而 Halide 背后的母公司 Lux Optics Incorporated,同样有着一段不寻常的经历。

Lux 的故事始于 2016 年,起点是一条 Twitter 私信。

前 Twitter 工程师 Ben Sandofsky 与前苹果工程师 Sebastiaan de With 因为在社交媒体上聊摄影器材而结识,两个发烧友一拍即合,决定合伙做一款相机应用。

▲ Ben Sandofsky(左)和 Sebastiaan de With(右)|Apple

Sandofsky 此前是 Twitter iOS 客户端的技术负责人,还担任过 HBO《硅谷》剧集的技术顾问。

de With 则参与过苹果 MobileMe、iCloud 和 Find My 的设计工作,也为 Sony、T-Mobile 和 Mozilla 做过设计。

用 de With 自己的话说,他们做的「不是单纯的 app」,而是「一整台相机」——他们希望把传统相机上拨动光圈环和快门拨盘的那种触觉快感,带到 iPhone 的玻璃屏幕上。

这种「有审美、有技术、有想法」的组合,最终让 Halide 成为了 App Store 生态中最具代表性的独立应用之一。

▲ 图|iPhone in Canada

相应的,Apple 对 Lux 的支持力度也远超一般开发者。

Halid 数次获得「年度最佳 iPhone 应用」、App Store 设计大奖,也会常驻应用商城的编辑精选。苹果开发者网站上专门为 Halide 做过两篇深度开发者专访,将该产品作为 App Store 优质开发者的样板展示。

在苹果提供给全球监管机构的报告中,Lux 的应用成为了开发者在 App Store 获得蓬勃发展的代表案例。

▲ 图|Apple Newsroom

相对应的,Lux 也始终忠于苹果生态,从未计划过任何 Android 应用。

正是由于这种「你侬我侬」的状态,当苹果去年找到 Lux 谈收购时,大多数业内人士的第一反应是:这太合理了。

iOS 26虽然对 iPhone 原生相机交互做了较大的调整,但仍然不够。人们期待着 iPhone 相机能够得到一次彻底的升级。而 Halide 团队在近十年里积累的手动控制交互经验、RAW 处理流水线,以及对 iPhone 相机硬件的深度理解,都是现成的财富。

▲ 图|CNET

据外媒报道,年末的 iPhone 18 Pro 系列在部分高级功能上将接近专业相机的水平,苹果正在为此重新设计内置相机应用。

而收购 Lux Optics,再融合 Halide 到系统相机,就是计划的一部分。

但收购没有谈成。

从收购失败到创始人决裂

上周,3 月 20 日,Sandofsky 将一纸诉状提交至加州高等法院——被告,是他的联合创始人。

根据诉讼文件,苹果与 Lux 的收购谈判在去年 9 月终止。没谈成是因为公司正在开发的新产品推高了价格,让苹果无法忍受。

然而根据诉状,实际情况并非如此:苹果发现,根本不用花大价钱买走 Lux,只需要把 de With 招回苹果就够了。

▲ 图|Medienstürmer

收购谈判结束后不久,Sandofsky 在调查 de With 的财务行为时发现:苹果已经开始尝试招募自己的联合创始人,而面试对接人刚好是之前苹果参与收购谈判的人员。

除了指控 de With「自愿被挖墙脚」之外,Sandofsky 还提出了严肃的财务指控:诉讼状闲时,de With 从 2022 年底开始,使用公司信用卡支付个人消费,累计超过 15 万美元。

其中包括用公司账户购买了一张近 7560 美元的机票(法兰克福-巴黎-圣保罗),de With 声称是为之后的商务旅行准备,但无法提供确认邮件。

▲ 图|Peter Peerdeman

de With 还涉嫌用公司资金购买了自己和女友前往法属波利尼西亚的「产前假」机票,以及其他涉及住宿、服装和酒水等与 Lux 公司业务无关的消费。

自从和苹果的收购谈崩之后,Sandofsky 就开始感觉不对劲了,于是去年 10 月雇佣了调查人员进行财务审查。

11 月,他将 de With 带薪停职——然而就是在停职调查期间,de With 开始与苹果沟通入职事宜。

12 月,Sandofsky 主持的内部调查结束,Lux 解雇了 de With,并要求他立即归还所有公司财产,包括存有敏感数据的电脑,并提醒他有义务不得泄露内部信息。

而 Sebastiaan de With 似乎并没有接受这个结果。

今年 1 月 28 日,Sebastiaan de With 在 X 上官宣加入苹果设计团队。

然而诉状中提到,de With 加入苹果时带走了 Lux 的源代码和机密材料,包括前面提到的「未来产品开发」相关的信息。

Lux 于 2022 年获得的 Apple Design Award 奖杯,也被这位苹果老员工带走了。

▲ 图|iMore

面对诉状,被告方律师在声明中全面否认了上述指控。

关于财务问题,备稿律师称这些费用「已记录在册、清晰可见,且在当时从未被质疑」,是对「在一家共同管理、缺少正式管控的小公司里的正常、已披露的业务活动的事后重新定性」。

更关键的是,律师称这场诉讼是 Sandofsky 对 de With 要求查阅公司财务记录的报复——

de With 曾就公司的「财务违规行为」向 Sandofsky 提出质疑并正式要求查账,但相关要求一直未被满足。

▲ 图|Getty Images

关于 Halide 等等一系列 app 的知识产权,律师否认 de With「使用、转移或披露了任何 Lux 知识产权」,并称 de With 已将公司材料归还给 Lux。

一位律师直接表示:

(Sandofsky)试图将苹果(收购 Lux 这件事)拉入这场纠纷,目的是制造杠杆和吸引关注,而不是解决任何实际的不当行为。

被告律师在声明中强调:「此案不是一起欺诈案件,而是长期合作关系破裂,所导致的联合创始人纠纷」

至少在纸面上,Sandofsky 的诉讼的确没有将苹果列为被告,也从未指控苹果在其中有任何不当行为。

开发者社区的复杂情绪

Sebastiaan de With 加入苹果的消息公布时,开发者社区的反应就已经相当复杂,而 Lux 内部诉讼的曝光让这些讨论多了一层新的含义。

de With 去年 6 月发表过一篇设计文章——「Physicality: The New Age of UI」,探讨 Apple 可能的设计语言走向。

当时的语境中,这是一位独立设计师对 iOS 与 Liquid Glass 平台未来的畅想;现在回头看,这篇文章多了一层耐人寻味的含义。

▲ 图|Wallpaper 网站专访苹果设计团队时收到的 visionOS 设计稿细节

有人对 de With 的加入表示祝贺,认为他的设计才华可以给苹果注入新血液——尤其在人机界面主管 Alan Dye 去年底离职前往 Meta 之后。

但也有人感觉事情不对劲。比如,开发者 CM Harrington 就表示,他对 de With 加入苹果的忧虑在于,他只是一个人,而「公司其余的人也得在乎设计,才能让有品味和能力的人真正发挥作用」。

另一位评论者更直接:

我会因为一个人在(苹果)目前这种领导层状态依然选择去苹果工作而判断他。(de With)加入这个系统,是因为认同它,而不是因为感觉自己能改变它。

▲ 图|AppleInsider

而在 Reddit 上,Sandofsky 也在 1 月 25 号当天出面,反复强调 Halide 不会受影响,说自己从 2019 年就全职投入 Lux。

当然,1 月 Sebastiaan de With 表示加入苹果时,还没有人知道两位联合创始人已经撕破脸了。当时大家都以为,一个创始人离开、另一个创始人坚守,直到诉状揭开了故事的背面,是一个长久以来存在,且在苹果生态里经常被提起的问题:

作为一个苹果开发者,如果某一天你的产品/功能,被苹果公司直接做成系统产品/功能,你又该何去何从?

2002 年,苹果在 Mac 内置工具 Sherlock 3(聚焦搜索的前身)中复制了第三方付费应用 Watson 的几乎所有核心功能,Watson 的市场空间被迅速蚕食,最终无奈离场。

这个产品名 Sherlock,也因此直接演化成了这种行为的代名词。

▲ WWDC 2002 乔布斯介绍 Sherlock 3|YouTube @AppleVideoArchive

「被苹果 sherlock」的焦虑,一直在加深。最近的例子,是苹果在 macOS 26 中将剪贴板历史集成到聚焦搜索里,对 Raycast、Alfred、Paste 等第三方应用带来了不小的冲击。

▲ WWDC 2025|Apple

更不用说 iPhone 上的通话录音、夜览、密码 app、Sidecar 等等……一个又一个曾经属于第三方应用的核心功能,陆陆续续被苹果吸纳进了系统,变成了免费功能。

但这一次 Lux 的遭遇,激进程度完全上了一个台阶:不折腾,直接把人招走。

无独有偶,苹果与医疗设备公司 Masimo 之间也曾有过一段类似的摩擦。

2015 年初代 Apple Watch 发布前夕,苹果曾与 Masimo 讨论在血氧传感技术领域进行合作。谈判破裂后,苹果大规模挖走了 Masimo 的员工,这些人随后参与了苹果健康监测技术的开发。

▲ 图|AppleInsider

Masimo 就此提起了两项诉讼。2025 年 11 月,陪审团在其中一项专利侵权案中判决苹果需要赔偿 Masimo 6.34 亿美元,苹果正在就此事提起上诉。

NPR 在报道苹果的「Sherlock 行为」时,援引了 App Store 前高管 Philip Shoemaker 的说法:许多开发者不敢公开批评苹果,因为害怕被从 App Store 里下架。

没有现成的答案

尽管诸事不顺,Lux 并没有放弃自己的产品。正相反,公司还在继续优化 Halide 等产品——甚至其中部分设定,颇有对苹果的挑衅意味。

今年 1 月,Lux 发布了 Halide 第三代公开预览版,Sandofsky 表示他将继续全职运营 Lux,并与知名设计工作室 The Iconfactory 和调色师 Cullen Kelly 合作开发新版本。

▲ 图|Lux

今年 2 月,在接受《Inc.》杂志采访时,Sandofsky 还阐述了一个颇具哲学意味的观点:

现在的 iPhone 照片过于「完美」,以至于变得平庸。

而新版 Halide 将会自带一个「Process Zero」功能,旨在绕过所有 iPhone 预设的相机算法(比如令人深恶痛绝的 Deep Fusion),让用户拍出「不那么完美但更有个性」的照片。

从今往后,Halide 这个产品,不想再给苹果的应用生态唱「样板戏」了。

正相反,它要举起反抗苹果的大旗了。

▲ 图|Halide.cam

而在苹果那边,Sebastiaan de With 和苹果设计部门都在经历一轮深刻变革。人机交互设计副总裁 Alan Dye 离职,资深设计师 Stephen Lemay 接任。

同一时间,苹果还在继续推进从 Liquid Glass 到整个 UI 系统的视觉翻新。de With 的理念能在多大程度上影响这个进程,仍然是未知数。

▲ 图|Wccftech

我们无法预判这场 Lux 创始人之间的纠纷,最终会以何种方式收场。毕竟双方各执一词,诉讼尚未进入审理阶段。但无论结果如何,它都触及到了 App Store 生态中最敏感的神经。

过去二十多年,苹果开发者社区会反复追问自己:「当苹果做了你的功能时,你该怎么办?」

现在,这个问题变成了:「当苹果直接来挖你的好友兼联合创始人时,你又该怎么办?」

没人有现成的答案。

#欢迎关注爱范儿官方微信公众号:爱范儿(微信号:ifanr),更多精彩内容第一时间为您奉上。

在Debian 13上安装Docker

在Debian 13系统上安装Docker,推荐使用官方Docker仓库。

打开终端,并运行以下命令来更新你的包索引:

sudo apt-get update

安装一些必要的系统工具,这些工具让 apt 命令能够通过 HTTPS 使用仓库:

sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

添加 Docker 的官方 GPG 密钥:

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

设置 Docker 的稳定仓库。首先,你需要知道你的 Debian 版本(例如,buster, bullseye 等),你可以通过运行 lsb_release -cs 来获取。然后,运行以下命令:

echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

更新你的包索引(再次),然后安装 Docker Engine:

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

启动 Docker 服务并设置为开机启动:

sudo systemctl start docker
sudo systemctl enable docker

验证 Docker 是否正确安装并运行:

docker --version
docker run hello-world

安装后可通过以下命令操作:

‌拉取镜像‌:使用docker pull从Docker Hub获取镜像,如docker pull nginx。‌‌

‌运行容器‌:使用docker run启动容器,例如docker run -d -p 80:80 nginx后台运行并映射端口。‌‌

‌查看容器‌:docker ps查看运行中的容器,docker ps -a查看所有容器。‌‌

Medium and Message: Panorama

In post-classical European art the great majority of paintings are close to being square, with an aspect ratio (given as width to height) of between 0.75:1 and 1.5:1. Although there’s no generally agreed cut-off for what constitutes a panorama, those with an aspect ratio of 2:1 or greater should qualify.

Anonymous, Flotilla Fresco (before c 1627 BC), fresco, Thera (Santorini, Greece). By pano by smial; modified by Luxo, Wikimedia Commons.
Anonymous, Flotilla Fresco (before c 1627 BC), fresco, Thera (Santorini, Greece). By pano by smial; modified by Luxo, Wikimedia Commons.

Ancient and classical paintings are different, though, and what’s probably the oldest landscape painting (excluding those in caves) is far broader than it is high. This Flotilla Fresco painted at Thera on the island of Santorini in Greece must have been completed before a catastrophic volcanic explosion in about 1627 BCE destroyed the local civilisation.

brilbracciano
Paul Bril (c 1553/4–1626), View of Bracciano (c 1622), oil on canvas, 74.5 x 163.6 cm, Art Gallery of South Australia, Adelaide, South Australia. Wikimedia Commons.

Paul Bril was exceptional in this panoramic View of Bracciano painted in about 1622 with an aspect ratio of 2.2:1. Although strongly Italianate, it’s a painting ahead of its time in other respects, as a fairly accurate depiction of a real place, with all sorts of fascinating little scenes within it, like the young boy doffing his hat to the passing dignitary in his coach with armed guard.

Bartholomeus van der Helst (1613–1670) and Jan Vos (1610–1667), The Celebration of the Peace of Münster, 18 June 1648, in the Headquarters of the Crossbowmen’s Civic Guard (St George Guard), Amsterdam (1648), oil on canvas, 232 x 547 cm, Rijksmuseum, Amsterdam, The Netherlands.

Just over twenty-five years later, the Dutch painters Bartholomeus van der Helst and Jan Vos used a panoramic canvas to accommodate all those in The Celebration of the Peace of Münster, 18 June 1648, in the Headquarters of the Crossbowmen’s Civic Guard (St George Guard), Amsterdam. This has an aspect ratio of 2.4:1, even greater than Bril’s.

wolfpanoramagrindelwald
Caspar Wolf (1735–1783), Panorama of Grindelwald with the Wetterhorn, Mettenberg and Eiger (1774), oil on canvas, 82 x 226 cm, Kunsthaus Zürich, Zürich, Switzerland. Wikimedia Commons.

The Swiss painter Caspar Wolf was another early exponent in his Panorama of Grindelwald with the Wetterhorn, Mettenberg and Eiger painted in 1774, although this couldn’t have been called a panorama at the time. This shows the distortion needed to include the whole of this view on a single canvas, with its remarkably high aspect ratio of 2.75:1. Today we’d envisage this as being painted through a wide-angle lens, although it was a century before such camera lenses came into use.

It’s generally accepted that the idea of a panorama was first formalised in British patent number 1612 of 1787 awarded to Robert Barker, where he coined the word, and the word’s first appearance in print occurred four years later.

Giovanni Battista Lusieri, A View of the Bay of Naples, Looking Southwest from the Pizzofalcone Toward Capo di Posilippo (1791), Watercolor, gouache, graphite, and pen and ink on six sheets of paper, 101.8 x 271.9 cm, The J. Paul Getty Museum, CA. Wikimedia Commons.
Giovanni Battista Lusieri (1755-1821), A View of the Bay of Naples, Looking Southwest from the Pizzofalcone Toward Capo di Posilippo (1791), Watercolor, gouache, graphite, and pen and ink on six sheets of paper, 101.8 x 271.9 cm, The J. Paul Getty Museum, CA. Wikimedia Commons.

A little later, Giovanni Battista Lusieri attained high aspect ratios of around 2.7:1 by assembling multiple supports, in his case sheets of paper, as he worked in watercolour on this View of the Bay of Naples, Looking Southwest from the Pizzofalcone Toward Capo di Posilippo in 1791.

Robert Barker’s panorama wasn’t artistic in the slightest, but pure spectacle and entertainment. His original painting of Edinburgh was on a large roll of paper, and first exhibited in Leicester Square, London, an area now known for its leading movie theatres. Baker either stuck the painted roll on the inside of a large cylinder for rotation about the viewer (also known as a cyclorama), or later he scrolled the roll past the viewers’ eyes.

JMW Turner, Petworth Park: Tillington Church in the Distance (c 1828), oil on canvas, 60 x 145.7 cm, The Tate Gallery, London. Wikimedia Commons.
JMW Turner (1775-1851), Petworth Park: Tillington Church in the Distance (c 1828), oil on canvas, 60 x 145.7 cm, The Tate Gallery, London. Wikimedia Commons.

Many paintings in JMW Turner’s huge output are panoramic in nature if not in form. This example, Petworth Park: Tillington Church in the Distance (c 1828), is viewed from a higher level even though its content has little vertical extent, to emphasise its long cast shadows. It has a high aspect ratio of 2.4:1, and the odd arc of the path in the foreground enhances its wide-angle effect.

Théodore Rousseau, Vue panoramique sur l'Île-de-France (Panoramic View of the Ile-de-France) (c 1830), oil on canvas, 22.1 x 75.9 cm, The National Gallery of Art, Washington, DC. Courtesy National Gallery of Art, via Wikimedia Commons.
Théodore Rousseau (1812-67), Vue panoramique sur l’Île-de-France (Panoramic View of the Ile-de-France) (c 1830), oil on canvas, 22.1 x 75.9 cm, The National Gallery of Art, Washington, DC. Courtesy National Gallery of Art, via Wikimedia Commons.

In about 1830, Théodore Rousseau’s Panoramic View of the Ile-de-France attained the highest aspect ratio yet, of just over 3.7:1, which may have been driven by the growing popularity of panoramas as entertainment. He’s also more conventional in placing the viewer at the level of the rooftops, looking over foreground buildings. The angles of lines of trees and other objects in the foreground appear to show wide-angle lens distortion, although the earliest known photograph wasn’t made until 1838. One possible explanation is that Rousseau used a camera obscura to draw in the view, although I’m not aware of any evidence of that.

Jean-Baptiste-Camille Corot, Avignon from the West (1836), oil on canvas, 34 x 73.2 cm, The National Gallery, London. WikiArt.
Jean-Baptiste-Camille Corot (1796-1875), Avignon from the West (1836), oil on canvas, 34 x 73.2 cm, The National Gallery, London. WikiArt.

Just a few years later, Jean-Baptiste-Camille Corot painted panoramic views en plein air and in his studio. This example of Avignon from the West (1836) shows how well he transferred the skills that he had learned when in the Roman Campagna to the French countryside. Its aspect ratio is more modest at 2.2:1, similar to that of Paul Bril two centuries earlier.

Frederic Edwin Church (1826-1900), Niagara (1857), oil on canvas, 101.6 x 229.9 cm, National Gallery of Art, Washington, DC. Wikimedia Commons.
Frederic Edwin Church (1826-1900), Niagara (1857), oil on canvas, 101.6 x 229.9 cm, National Gallery of Art, Washington, DC. Wikimedia Commons.

Many of Frederic Edwin Church’s epic landscapes were painted far south beyond the US border, but this early panoramic view of Niagara made in 1857 remains one of his most important works, with its aspect ratio of 2.3:1.

harpigniesseinerouen
Henri Harpignies (1819–1916), View of the Seine at Rouen (date not known), watercolour over black chalk, on heavy watercolour paper, 24.7 x 54.5 cm, The Morgan Library & Museum, New York, NY. Wikimedia Commons.

I don’t have a date for Henri Harpignies’ magnificent watercolour panorama of View of the Seine at Rouen, which I believe shows the view from Bonsecours, to the south-east of the city, looking north-west into the summer sunset, with an aspect ratio of 2.2:1.

By the end of the nineteenth century panoramas were attaining aspect ratios over 4:1, requiring custom supports, either being painted on the interior walls of a cylindrical building or rotunda, or on rolls like Robert Barker’s.

Hendrik Willem Mesdag, Panorama Mesdag (1880-1), media not known, 1400 x 12000 cm, Panorama Mesdag, Den Haag. Wikimedia Commons.
Hendrik Willem Mesdag (1831-1915), Panorama Mesdag (1880-81), media not known, 1400 x 12000 cm, Panorama Mesdag, Den Haag. Wikimedia Commons.

Hendrik Willem Mesdag’s staggering Panorama Mesdag from 1880-81 was commissioned as a view of the village of Scheveningen, the Netherlands, from its coastal dunes. It’s 14 metres high and 120 metres long, giving it an aspect ratio of 6.8:1. When tastes changed towards the end of the nineteenth century, the company exhibiting the panorama as an entertainment went bankrupt; Mesdag bought it back, and it remains housed in its dedicated building, an appropriately extreme memorial to this long-lasting fascination.

Over the following decades other huge panoramas were painted to commemorate wars and national history. I show here just two examples.

philippoteauxgettysburg
Paul Dominique Philippoteaux (1846–1923), Gettysburg Cyclorama (1883), oil on canvas panorama, overall 820 x 10940 cm. Gettysburg Museum and Visitor Center, Gettysburg, PA. Wikimedia Commons.

Paul Dominique Philippoteaux’s vast Gettysburg Cyclorama opened to public acclaim just twenty years after the battle, in 1883, and continues to draw attention at the battlefield’s visitor centre. It was commissioned by a group of Chicago investors, rather than anyone interested in its art, and has the highest aspect ratio of 13.3:1.

fesztypanorama
Árpád Feszty (1856–1914), Arrival of the Hungarians (Feszty Panorama) (detail) (1892-4), oil on canvas cyclorama, 1500 x 12000 cm, Ópusztaszer National Heritage Park, Ópusztaszer, Hungary. Wikimedia Commons.

As their popularity was waning at the end of the century, Árpád Feszty and a hoard of assistants depicted the narrative scenes they imagined of a millennium earlier, as the first Hungarians arrived to settle their country. Their whole panorama has an aspect ratio of 8:1.

类比 systemd 的 macOS launchd 使用笔记

现在各大 Linux 发行版很多都变成 systemd 的形状了,连 Synology DSM 7 都开始用 systemd 了,可以说是 Learn once, operate anywhere。不过有时候还是要在 Mac 机器上部署一些服务,需要用到 launchd/launchctl。

本文以一个熟悉 systemd/systemctl 工具的运维视角,整理了常用的 launchd 相关命令备忘。(说实话我每次都会忘记怎么用,然后得去翻手册……而且网上有时候还会教你用 load/unload 子命令,这些其实都已经标记为过时了,有新的命令替代它们)

list 查看所有

launchctl list# 类比 systemctl list-units

status 查看状态

launchctl print gui/501/uploadserver# -> ~/Library/LaunchAgents/uploadserver.plistlaunchctl print system/com.openssh.sshd# -> /System/Library/LaunchDaemons/ssh.plist# 类比 systemctl status uploadserver.service# -> /etc/systemd/system/uploadserver.service

这里的 system/ gui/501/ 叫做 domain-target,com.openssh.sshduploadserver 叫做 service-name,合起来之后叫做 service-target。service-name 一般就是下面 .plist 配置文件中的 Label。

其中 system/ 顾名思义就是系统级的,system domain,需要 root 权限才能修改。而 gui/501/ user/501/ 则是用户级的 user domain,其中 501 就是用户 uid。gui/<uid>/login/<asid>/ 下的服务只有用户登录了才会运行。

通常来说需要 GUI 运行的放在 gui/<uid>/ 下面,不需要的放在其他下面。不过考虑到 macOS 作为桌面操作系统的特性,其实一股脑都放 gui 下面也没啥问题。

start 启动

launchctl bootstrap gui/501 ~/Library/LaunchAgents/uploadserver.plist# 或者系统级的服务,需要 sudo 运行sudo launchctl bootstrap system /Library/LaunchDaemons/com.example.plist# 类比 systemctl start uploadserver.service# 不需要 systemctl daemon-reload

如果 bootstrap 提示下面的报错,就说明很可能是服务器已经在运行了,或者服务被 disable 掉了:

Bootstrap failed: 5: Input/output errorTry re-running the command as root for richer errors.

stop 停止

launchctl bootout gui/501 ~/Library/LaunchAgents/uploadserver.plist# 或者系统级的服务,需要 sudo 运行sudo bootout bootstrap system /Library/LaunchDaemons/com.example.plist# 除了 .plist 文件路径,也可以用 label 指定launchctl bootout gui/501/uploadserver# 类比 systemctl stop uploadserver.service

如果 bootout 提示下面的报错,就说明很可能是服务本来就没有在运行:

Boot-out failed: 3: No such process

restart 重启

launchctl kickstart -k -p gui/501/uploadserver# service spawned with pid: 17247# 参数:# -k       如果服务已经在运行了,先杀死现有的进程再重启# -p       成功后输出进程的 PID# 类比 systemctl restart uploadserver.service

如果 kickstart 提示下面的报错,就说明服务没有 bootstrap:

Could not find service "uploadserver" in domain for user gui: 501

enable 开机启动

一般来说你的 .plist 里配置了 RunAtLoad 的话,bootstrap 了之后默认就是开机启动的,不需要再 enable 一遍。

不过你也可以通过 disable 主动关闭服务的开机启动,这个是否 enable 的状态是 launchd 自己维护的,不会更改 .plist 文件的内容。使用 disable 禁止开机启动之后,想要恢复开机启动就需要用 enable。

launchctl enable gui/501/uploadserver# 类比 systemctl enable uploadserver.service

disable 禁止开机启动

launchctl disable gui/501/uploadserver# 类比 systemctl disable uploadserver.service

config 配置文件

类似于 systemd 的 Unit File,以 .plist/XML 文件的形式存在:

~/Library/LaunchAgents   Per-user agents provided by the user./Library/LaunchAgents    Per-user agents provided by the administrator./Library/LaunchDaemons   System-wide daemons provided by the administrator./System/Library/LaunchAgents   Per-user agents provided by Apple./System/Library/LaunchDaemons  System-wide daemons provided by Apple.

通常来说我们只会用到前三个。Daemon 和 Agent 的区别:

  • Daemon:系统级、单个实例服务多个用户、不应显示 UI、没有用户登录也会运行、可以以 root 权限运行。
  • Agent:每个用户各自运行实例、直接与用户交互、用户不登录则不会运行、以普通用户权限运行。

这里以 ~/Library/LaunchAgents/uploadserver.plist 为例:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict>    <key>KeepAlive</key>    <true/>    <key>Label</key>    <string>uploadserver</string>    <key>LimitLoadToSessionType</key>    <array>        <string>Aqua</string>        <string>Background</string>        <string>LoginWindow</string>        <string>StandardIO</string>        <string>System</string>    </array>    <key>ProcessType</key>    <string>Background</string>    <key>ProgramArguments</key>    <array>        <string>/opt/homebrew/bin/uvx</string>        <string>uploadserver</string>        <string>8888</string>        <string>-d</string>        <string>/tmp/upload</string>    </array>    <key>RunAtLoad</key>    <true/>    <key>EnvironmentVariables</key>    <dict>        <key>FOO</key>        <string>BAR</string>    </dict>    <key>StandardErrorPath</key>    <string>/tmp/uploadserver.log</string>    <key>StandardOutPath</key>    <string>/tmp/uploadserver.log</string>    <key>TimeOut</key>    <integer>5</integer></dict></plist>

类比 /etc/systemd/system/uploadserver.service

[Unit]Description=Upload ServerWants=network-online.targetAfter=network-online.target[Service]ExecStart=/root/.local/bin/uvx uploadserver 8888 -d /tmp/uploadRestart=alwaysRestartSec=5Environment="FOO=BAR"StandardOutput=file:/tmp/uploadserver.logStandardError=file:/tmp/uploadserver.log[Install]WantedBy=multi-user.target

具体怎么写就不多说了,大部分开机自启 + 守护进程需求用上面的模板就够了,有其他需求的直接看文档。

名字基本可以随便取。另外注意有多个命令行参数的话,要拆成多个 <string>

不再推荐使用的 Legacy 命令

现在很多教程里还在用 load/unload,不过在 macOS 10.11 之后,官方手册中已经不再推荐使用这些老的命令,应该使用上面的命令替代。

另外一点需要注意的是,load/unload 通过执行 launchctl 命令时的权限来决定 domain。如果使用 sudo launchctl 执行的,算作 system domain,否则算作 user domain。之前被坑过一次……💩

launchctl load ~/Library/LaunchAgents/uploadserver.plist# 应该替换为 launchctl bootstrap gui/501 ~/Library/LaunchAgents/uploadserver.plistlaunchctl load -w ~/Library/LaunchAgents/uploadserver.plist# 相当于先 enable 再 bootstraplaunchctl unload ~/Library/LaunchAgents/uploadserver.plist# 应该替换为 launchctl bootout gui/501 ~/Library/LaunchAgents/uploadserver.plistsudo launchctl load /Library/LaunchDaemons/com.example.plist# 应该替换为 sudo launchctl bootstrap system /Library/LaunchDaemons/com.example.plistsudo launchctl unload /Library/LaunchDaemons/com.example.plist# 应该替换为 sudo bootout bootstrap system /Library/LaunchDaemons/com.example.plist

可视化管理工具

推荐 Lingon X,有点像以前 Windows 上的那种开机进程管理,可以查看当前系统上有哪些 Agent/Deamon,以及它们的配置,挺方便的。

小尾巴

我记得以前 macOS 设置页面里的启动项管理很垃圾,只能显示部分启动项,但实际上程序想要开机自启有很多种方法:

  • LoginItems (Helper App with SMLoginItemSetEnabled)
  • LaunchAgents (~/Library/LaunchAgents or /Library/LaunchAgents)
  • LaunchDaemons (/Library/LaunchDaemons)
  • 直接拖动到设置页面「登录时打开」列表中

搞得有些流氓软件开机自启了你都不知道,比之 Windows 还不如。当时我还准备写篇博客,在不安装第三方清理软件的情况下如何删除这些启动项,但后来不了了之了。

不过好在后来的 macOS 更新把这块的管理补上了,现在在设置页面就可以直接管理上面那些方式添加的启动项,挺好。

使用 Linux 作为透明网关的最佳实践?

wangweitung:

使用 linux 作为透明网关的最佳实践?

背景:

  1. 最开始用 openwrt (网络编译、自编译都试过)。但是经常崩溃。

最近状态,根据 v 友推荐,已经抛弃了 openwrt ,主要用了以下两种。

  1. 根据 v 友推荐,尝试了 alpine+shellcrash ,比较好用。
  2. 又看到了 sbshell,又根据教程尝试了 debian+sbshell ,但是这个方式会导致 synology 上部署的外网服务没法用,找了半天也没找到原因。

求助 v 友:

适合小白一键设置 linux ( ubuntu/debian/alpine )作为透明网关的是不是就以上两种方式了。有没有其他推荐的方式,最好附教程,谢谢了~

使用 Linux 作为透明网关的最佳实践?

wangweitung:

使用 linux 作为透明网关的最佳实践?

背景:

  1. 最开始用 openwrt (网络编译、自编译都试过)。但是经常崩溃。

最近状态,根据 v 友推荐,已经抛弃了 openwrt ,主要用了以下两种。

  1. 根据 v 友推荐,尝试了 alpine+shellcrash ,比较好用。
  2. 又看到了 sbshell,又根据教程尝试了 debian+sbshell ,但是这个方式会导致 synology 上部署的外网服务没法用,找了半天也没找到原因。

求助 v 友:

适合小白一键设置 linux ( ubuntu/debian/alpine )作为透明网关的是不是就以上两种方式了。有没有其他推荐的方式,最好附教程,谢谢了~

Debian安装多个PHP版本并使用Virtualmin为网站配置相应的PHP版本

在Debian服务器中可以安装多个PHP版本,Virtualmin/Webmin允许您给每个网站甚至每个目录指定相应的PHP版本。

在Debian中安装

安装Sury/PHP repository:

apt-get -y install apt-transport-https lsb-release ca-certificates curl && curl -sSL -o /usr/share/keyrings/debsuryorg-archive-keyring.gpg https://packages.sury.org/php/apt.gpg && sh -c 'echo "deb [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/sury-debian-php-$(lsb_release -sc).list' && apt-get update

安装PHP extensions:

apt-get install php8.4-{cgi,cli,fpm,pdo,gd,mbstring,mysqlnd,opcache,curl,xml,zip,imagick,intl}

说明:根据自己实际需要,选择php版本,如php8.4。

在Virtualmin/Webmin中配置第二个PHP版本(适用于所有新虚拟服务器)

在服务器上完成第二个PHP版本的安装后,您可以登录Virtualmin并单击System Settings -> Re-Check Config。你应该看到这样的:

The following PHP execution modes are available : fpm
The following PHP-FPM versions are available : 8.2.28 (php-fpm) 8.4.10 (php84-php-fpm)

您可以选择其中一个PHP版本作为新虚拟服务器上使用的默认PHP版本。缺省PHP版本为最低可用版本。您可以在System Settings – >服务器模板 – > Default – > PHP Options中更改默认值。

在Virtualmin/Webmin中配置单个虚拟服务器(适用于原有虚拟服务器)

您可以通过选择Virtualmin – > Server Configuration → PHP Options,来配置用于特定虚拟服务器的PHP版本。

第一行“缺省HTML目录”指定默认使用什么PHP版本。

如果愿意,您可以指定要用于特定目录的其他PHP版本。

英文原文:https://www.virtualmin.com/docs/server-components/configuring-multiple-php-versions/

【读书笔记】UX for Business

最近看了一本名为 UX for Business 的书,这本书主要在讲设计师如何做有价值的事情。让我们跳出设计画板,在更高的层面理解日常工作。理解做什么,怎么做,怎么做到极致。但个人认为作者写得有些口语化,且不必要的内容重复过多。很多地方讲得比较浅,没有太多案例,推荐指数3颗星吧。

VDP 框架

作者强力推荐了 “VDP 框架” 来确保我们时刻在做正确、有效且对公司有价值的事情。

V for Value 价值

当你的设计同时满足了用户和公司的需求,你就在创造价值。

作者将用户需求分为两类,一类是效率类需求(Efficiency),另一类是娱乐类需求(Entertainment)。当设计师在面对效率优先的场景时,需要帮助用户用更少的时间、精力和钱来做事情,而不是更多。总的来说,就是让用户用更少的成本完成一件事。

举个例子:在烘培店里,如果一个新的烘培配方可以让烘培师用更少的鸡蛋做到和以前一样好吃,那么这就是一个好的配方设计。

聚焦能为用户/公司创造价值的地方:新增、购买、下载等流程。

D for Diagnosis 分析

指的是系统性地收集和分析问题,确保我们在做正确的事。作者在书中分享了做从设计分析到实施方案的思路。

1.了解背景

作者指出 UX 设计师的工作实际上是基于当前的信息和限制(如:业务指标、用户诉求、产品目标、、问题反馈、时间/资源限制等等)来产出解决方案来改进产品。

就像医生在看病时,会问病人有什么症状、有什么感觉、最近吃过什么、有没有对什么过敏等等,通过多种角度来下结论。

UX 设计师也要通过类似的方式来设计,想做出一个好的方案,就需要更多的信息。5W就是一个好的方法:

  • Who:用户是谁?他们的特征和需求是什么?
  • When:什么时候会有这个问题?
  • Where:在哪里会遇到这个问题?
  • What:能解决什么问题?
  • Why:为什么用户需要它?

2.发掘+分析问题

有时候我们收到一些产品体验的反馈,这可能只是一个问题的表象,仅仅解决它只是在打补丁,没有从根源性解决问题。

某个新功能的使用情况不理想,可能并非是该功能设计得不好,而是在上一层的漏斗出现问题。所以想要挖掘到深层次的根源问题,需要通过在多个问题之间来回推敲。

收集足够多的问题,为下一步做准备

3.找到问题共同点

将同类的问题归类好,利用前面的 5W 分析,比如将属于同一个 When 的问题归在一类,同一个 Who 的问题在另一类。

这种做法有时候会让我们不仅仅在做当前需求,还能帮助我们发掘到其他带改进的点。

4.规划改进问题

这一步就是将我们观察、收集到的信息转化为行动了。

前几步我们列出了问题的表象,并将其分类。这一步需要去思考什么引发了这一连串有关联性问题。比如一个页面的 Like 按钮点击量很少,但用户反馈中他们都很喜欢这里的内容,那我们就会假设是 Like 按钮做得不够明显,解决方案随之而来。

我们会进行不止一次的假设,按照可能性的高低来按顺序尝试解决方案。

5.验证结果

最后,将我们觉得可行的解决方案推进上线,基于效果决定是在当前解决方案下改进,还是换一个解决思路,甚至收集更多信息后再次进行设计。

P for Probability 可能性

利用 “可能性” 来优化设计,将价值最大化。作者通过分享了以下观点来阐述可能性在设计中的应用。

1.越靠前、越明显的内容具有更多的可能性。比如一组选项,第一个选项通常来说都是更大概率被选择的。所以,把重要的、能创造价值的内容做得更靠前和明显;

2.事情是线性发展的。你不能在完成第一件事之前完成第二件事,就好比我们在浏览一个导航的时候,如果我们找到了可能合适的跳转入口,我们就会直接点击,不会尝试去看后面的内容了;

3.用户在准备好做决定时才会去做决定。就好比电商场景,用户都会在足够了解产品之后,才决定是否购买,那么“购买”按钮通常就不会是页面上的第一个元素。

4.默认值能影响可能性。默认的值通常是最多人进行选择的,所以要思考怎么设计默认值才能提高用户使用效率,或者对公司有价值。

为内部系统做设计

为公司的内部系统有一个明显的特点:我们的用户不会流失。因为公司的雇员必须按照公司要求用某个系统完成工作,比如登记工作任务的工单系统、用于请假、报销的 OA 系统等等。

我们不需要考虑所谓的参与度、忠诚度,所以在用户价值/公司价值的取舍中,我们可以更多地倾向公司价值。

内部系统对效率的关注度会更高,因为不需要靠这个产品来赚钱。找到流程中的障碍并解决,是内部工具设计师的关键能力。

提升效率不光是对使用内部工具的员工有益,对公司的降低成本这种目标也是有价值的。高效率的工具可以让公司少雇佣一些雇员,帮助公司减少人力成本。作者甚至提到,如果内部工具能让小团队的生产效率提升得足够多,小公司也能和大公司竞争。

为商业化 SaaS 产品做设计

本书中提到一类产品属于 Sales-Driven 销售导向产品,对应到国内常用术语应该叫做商业化 SaaS 产品。

通常来说,做 SaaS 业务的公司通过卖这些获得收入:

  1. 席位:使用该产品的人数;
  2. 数据:使用服务的次数;
  3. 功能/模块:使用更强大功能的能力;

设计师需要清楚自己所负责的 SaaS 产品的收入来源,为公司所出售的服务进行设计。

共鸣片段

To improve conversion (i.e., get more people to finish your flow), think about everything you request from the user like a cost. Every question is a cost. Every minute is a cost

流程优化时,尝试将用户的每一步操作成本降到最低。鼠标移动、点击、鼠标滚轮、视线移动等等,都是操作成本。作者还提到一个观点,可以从最后一步开始优化,从后往前改进。因为在最后一步才导致转化失败会显得之前的努力都是徒劳。

UX is not what you do in Figma or a ticket in agile planning or the contrast of your button labels.
UX is a general process of designing things for humans.

我认为 UX 设计并不仅是 Figma 里一个个连接起来的页面,这只是表达清楚了页面/功能之间的跳转逻辑。UX 设计师是在为用户进行工作,需考虑到用户在流程中的使用所有体验,包括:

  • 浏览页面过程中的体验,比如信息层级设计,内容排版策略(例:恰当地设定文本换行规则);
  • 用户行为与系统交互中的体验,比如在进行增删改查时的功能引导、交互逻辑、操作反馈(例:校验表单的时机)、使用帮助、边缘场景闭环体验等;
  • 利用原生浏览器能力进行体验极致化,比如设置给 “版本号” 或 “错误代码” 的字段设置 user-select: all; 用户需要复制时,右键到文字区域就能自动全选该文本块,省去用鼠标框选的步骤;
  • 等等…

所以有时候做 “体验设计” 并不是在 Figma 里画图(这只是其中一种传达解决方案的形式),而是要提供一切能改进用户体验所需要的智慧结晶。

Design is a process, but not just a one-time process. We iterate!

设计是一个迭代过程,前面提到设计师是基于当前已知的信息和限制来提供解决方案。但世界上很多事情每天都在改变,产品目标会变,用户诉求会变,公司战略会变等等,所以每次迭代都是基于新的已知的信息进行改进。

Most importantly, what is the one thing the users should achieve on this page, if they only do one thing?

这句话提醒设计师,时刻将目标记在心头。当设计方案有陷入“既要又要”、“没有重点” 的困境时,拷问自己:在这个场景中,用户最重要的事情是什么?将最重要的事情做好。

sometimes the best design solutions require the designers and developers to do more work so users can do less.

这个深有同感,设计师和开发者费很大劲儿做出来的迭代,有时候只是帮助用户将使用流程更简化。

结语

第一次写读书笔记,改进的地方很多。但我会坚持阅读,纯粹觉得阅读能让我在这浮躁的社会,所谓的快节奏环境里慢下来。

cloudflared 用起来爽歪歪😊

(Abstract)感觉用了 cloudflared 之后,服务器已经没有暴露 SSH 端口的必要了。但是注意 cloudflared 默认会自动更新,更新后需要手动启动才能运行。如果是远程机器且无 root 权限的,注意关闭自动更新功能。

Unraid: 解决 12 版本中网页界面无法打开的问题

最近在 Unraid 升级 6.12.x 版本以后会偶发性的产生一个 Bug,其表现为 Unraid 网页无法打开(这里是指访问 Unraid IP 地址无法访问 Web 管理界面)。这个问题实际上是由于 Unraid 上的 Nginx 服务失去响应导致的。这种情况下我们只需要干掉 Nginx 进程并重启就可以了。

首先通过 ps -aux | grep nginx 找到 Nginx 主进程的 PID,然后通过 kill -9 <PID> 干掉进程。要再次启动 Nginx,可以运行

1
2
cd /etc/rc.d/
./rc.nginx start

注意通过 ./rc.nginx restart 在正常情况下可以重启 Nginx 服务,但是在 Nginx 处于无法响应的状态时,这个脚本无法杀死 Nginx 进程,必须要手动终止。

Ubuntu 中如何彻底删除一个用户

在 Ubuntu 中彻底删除一个用户涉及到几个步骤,不仅仅是删除用户,还可能包括删除与用户相关的数据。以下是步骤指南:

  1. 确保用户未登录: 在删除用户之前,最好确保该用户未登录。你可以使用 who 命令来检查哪些用户当前已登录。

    1
    who
  2. 删除用户: 使用 userdel 命令删除用户。如果你还希望删除用户的主目录和邮件池,可以使用 -r 选项。

    1
    sudo userdel -r username

    其中,username 是你想删除的用户的用户名。

    注意:-r 选项会删除用户的主目录(通常是 /home/username)。确保你已经备份了所有重要的数据!

  3. 检查文件系统: 即使删除了用户和其主目录,可能仍然在文件系统上遗留一些属于该用户的文件。你可以使用 find 命令来搜索这些文件:

    1
    sudo find / -user username

    这将列出所有属于 username 的文件。根据你的需要,你可以手动删除这些文件或更改它们的所有权。

  4. 删除用户的 cron 作业: 如果用户配置了任何 cron 作业,你还需要手动删除它们。检查 /var/spool/cron/crontabs/username 是否存在,如果存在,删除它。

    1
    sudo rm /var/spool/cron/crontabs/username
  5. 其他服务或配置: 如果该用户有其他特定的配置,例如在 /etc/sudoers 中的条目或在其他服务中的特殊访问权限,你需要手动检查并删除它们。

请在进行任何删除操作之前确保备份所有重要数据。确保你明确知道正在执行的操作,避免意外删除重要文件或配置。

Lessons I learned after completing the Google UX Design Professional Certificate

The image is a presentation slide with a dark green background and white text. The text reads “Lessons I learned after completing the Google UX Design Professional Certificate.” The logo “LRD.IM” is also displayed.

Recently, I heard that Coursera has a UX design course developed by Google’s design team. This course covers the entire design process and teaches us how to present our portfolio, prepare interviews, and the like.

It is necessary to enroll in this course even though it is designed primarily for beginners and fresh graduates. It would enhance my English skills on one hand, and deepen my understanding of Western design practices and culture on the other. Since the term “UX design” is called out by Western designers and I am eager to compare Western design cultures with those I’ve experienced in China.

So I enrolled in this online course, trying to spare my time on it. Such as during lunch and dinner breaks on weekdays, or parts of the weekend. I completed the whole certificate within two months. And now I’d like to write down what I learned from this course:

The image shows a dark green presentation slide with four text boxes labeled “New concepts,” “Listening and Reading Proficiency,” “Accessibility and equity,” and “Guidance for Job Hunting.” The text is in white and each box has a rounded edge.
  1. Introducing concepts I had never heard of. Despite my 5+ yoe in a wide range of companies, from startups to large corporations in China, those new concepts opened up a lot of room for me to explore.
  2. Enhancing my listening and reading skills. The course covers plenty of video and reading materials that include industry jargon that translators cannot provide. Moreover, certain phrases and sentence structures are repeatedly used throughout the course. I think my reading skills and speed are slightly improved.
  3. Pointing out concepts like accessibility and equity early throughout the course. I used to think only seasoned designers or well-developed products consider these aspects, however, they are mentioned early on and repeatedly. These concepts resonated with me and will truly influence my work.
  4. Elaborating comprehensive and detailed guidance for designers to prepare their portfolios, resumes, and interviews. They not only tell us what content should be included in our portfolios, but also how to prepare for interviews at different stages. I resonated with these instructions as well, since I did think those details over when looking for a new job.

Table of content

This is a wide banner-like image with a dark green background and the words “New concepts” in large, white text centered across the slide.

New concepts

I have consistently tried to think about and expand design boundaries through different aspects, which requires a breadth of knowledge. Here, I will share several new concepts along with my personal understanding.

Affinity diagram

This is a method of synthesizing that organizes data into groups with common themes or relationships. It can be used in different stages of the design process, such as during brainstorming or after collecting users feedback. The example below focuses on the latter.

After collecting a batch of user feedback, the design team condense each piece of feedback into a single sentence and write it on sticky notes. Then we post them up on a whiteboard or digital tools like Figma. Then the design team look for sticky notes that reference similar ideas, issues, or functionality and collaboratively organizes them into clusters representing different themes.

When I first learned about this approach in the course, I realized that this approach is similar to another method called “Card sorting” that was included in an article I translated earlier named [English to Chinese Translation] How we rebuilt Shopify’s developer docs. Both methods involve clustering sticky notes, naming these groups and summarizing the themes or relationships.

However, card sorting is implemented by external participants and aims to uncover users’ mental models to improve information architecture; Whereas affinity diagramming organizes a large amount of raw data to show the team which problems users are most concerned about and consider high priority.

* This concept is mentioned in Module 3 of Course 4 (Conduct UX Research and Test Early Concepts — Module 3 — Gather, organize, and reflect on data)

Digital literacy

This concept refers to an individual’s ability to gather, communicate, and create content using digital products and the internet. For example, senior adults or those living in areas with poor internet infrastructure may find it difficult to understand interfaces and functionalities, they are considered to have lower digital literacy.

In contrast, young people, especially those working in the information technology industries, are typically familiar with new software and concepts, and can quickly adapt to them.

This course does not dig deeply into this concept, rather, it emphasizes the importance of understanding our users. If our product targets a broad range of users, it is good to consider the needs of users with lower digital literacy. Moreover, this factor should also be considered when recruiting participants for usability tests.

* This concept is mentioned in Module 2 of Course 1 (Foundations of User Experience (UX) Design — Module 2 — Get to know the user)

Deceptive pattern

This concept refers to a group of UX methods that trick users into doing or buying something they wouldn’t otherwise have done or bought.

In the course, instructors clearly point out that this is an unethical and not a good practice. Businesses may lose their clients’ respect and trust once clients realize that they have fallen into deceptive patterns. I will share a few interesting examples that the course provided.

  1. Confirmshaming: Making users feel ashamed of their decision. For example, a subscribe button on a news website usually reads “Subscribe now / No thanks”. BBut if the service provider wants to manipulate readers’ emotions, the text might be changed to: “Subscribe now / No, I don’t care about things around me.”
  2. Urgency: Pushing users to make a decision within a limited time. For example, an e-commerce website might give you a coupon that is only available for 24 hours, prompting you to purchase items without a thoughtful consideration. The course doesn’t judge these marketing strategies or promotions; instead, it suggests that we should avoid putting pressure on users. As designers, we should try our best to balance business promotions and avoid manipulating users’ emotions.
  3. Scarcity: Making users very aware of the limited number of items. For example, a popup or attractive advertisement stating “Only 5 items left in stock.” The course suggests that designers should concentrate on helping users to understand products better, rather than using designs to encourage impulsive buying.

It is really interesting that these deceptive patterns are so common in the Chinese e-commerce industry that it might seem unusual if those strategies were to disappear.

This seems to reflect cultural differences between China and the West. In China, core team members, such as designers, product managers, and operators, collaboratively discuss how to induce and prompt users to make a hasty decision. Also, we regularly hold reflections to discuss and share insights on how to deeply incite users’ motivation.

In 2018, I landed my first job as a UI designer at an e-commerce company. One of my main tasks is designing promotions, such as “claim your vouchers”, “flash sales ending in N hours”, and creating illustrations of red pockets and flying coins, and the like. I didn’t really like these approaches at that time, so I eventually turned to the B2B and SaaS industry, focusing more on UX design.

Although I am not fond of these types of designs, these seem to really help companies grow and generate income. We could stabilize our employment only if our company were earning profits. Perhaps that is an inextricable cycle: obviously, deceptive patterns are unethical and bad as they are inducing and annoying our users, but we must continuously implement these approaches and think about how to make them more effective.

* This concept is mentioned in Module 3 of Course 3 (Build Wireframes and Low-Fidelity Prototypes — Module 3 — Understand ethical and inclusive design)

Biases

The course thoroughly explains a concept called “implicit bias”. It refers to the collection of attitudes and stereotypes associated, influencing our understanding of and decisions for a specific group of people.

For example, imagine you’re designing an app to help parents buy childcare. To personalize your onboarding process, you start by displaying bold text saying, “Welcome, moms. We’re here to help you…”

This is an example of implicit bias, since it excludes every other type of caregiver, like grandparents, guardians, dads and others.

In addition, here are some interesting biases the course introduced:

  1. Confirmation bias. Refers to the tendency to find evidence that supports people’s assumptions when gathering and analyzing information.
  2. Friendliness bias. Refers to the tendency to give more desirable answers or positive comments in order to please interviewers. This usually occurs in usability tests, where participants may not share their honest feedback because they are afraid that real answers or negative comments might offend interviewers and be considered unfriendly.
  3. False-consensus bias. Refers to the tendency that people tend to believe that their personal views or behaviors are more widely accepted than they actually are, and consider others’ opinions to be minor or marginal. For example, an optimist might think that most people around the world are optimistic; or designers can easily understand iconographies and illustrations they created, they might assume other users might easily to understand too.

I was shocked when I was learning this part. I strongly resonated with these biases which I had never perceived before. After all, the course lets us be aware of these biases and provides approaches to help us avoid falling into these pitfalls.

* This concept is mentioned in Module 3 of Course 3 (Build Wireframes and Low-Fidelity Prototypes — Module 3 — Understand ethical and inclusive design)

I listed some concepts above that I had barely encountered in my workspace. Becoming a UX designer appears to require a broad range of knowledge, such as design, the humanities, psychology, and sociology. I am now interested in psychology after completing this course.

This is a wide banner-like image with a dark green background and the words “Listening and Reading Proficiency” in large, white text centered across the slide.

Listening and Reading Proficiency

There are plenty of listening and reading materials involved in the course. Typically, each video lesson is accompanied by an article. If there are additional knowledge points, a single video might be accompanied by two or three articles.

Most instructors in the course speak with American accents. They also speak slowly and clearly, which makes me comfortable and usually allows me to understand without opening closed caption. Sometimes, I need to rewind a few seconds when they are speaking long sentences with many clauses or introducing new concepts, and I will open closed captions if I am still confused.

It is worth pointing out that the course contains lots of industry jargon, and I resonated with this because I used similar approaches or processes in my workspace by using Chinese. As a learner, I created a spreadsheet to record expressions that might be useful, such as:

  1. Above the fold, the content on a web page that doesn’t require scrolling to experience;
  2. Deliverable, final products like mockups or documents that can be handed over to clients or developers to bring designs to life.
  3. Digital real estate, space within the digital interface where designers can arrange visual elements;
  4. Firm parameters, refer to rigid design boundaries or limitations like time, project resources, and budget.

I think it is valuable to collect this industry jargon because it is authentically expressed, which can’t be translated by common translation tools. This will be helpful for me to read design articles and write blogs in English.

This is a wide banner-like image with a dark green background and the words “Accessibility and Equity” in large, white text centered across the slide.

Accessibility and Equity

Accessibility

The course introduces several assistive technologies, such as color modification, voice control, switch devices, and screen readers, which can help people with different types of disabilities to use our products easily.

Instructors also point out that even people who don’t have disabilities, or who do not perceive themselves as having disabilities might benefit from these assistive technologies. The course suggests that we think these factors over throughout the entire design process. For instance:

  1. Supporting color modification. Features that increase the contrast of colors on a screen, like high-contrast mode or dark mode;
  2. Supporting voice control. Allows users to navigate and interact with the elements on their devices using only their voice. They also mention a concept called “Voice User Interface (VUI)”;
  3. Supporting switch devices. This is a one-button device that functions as an alternative to conventional input methods such as the keyboard, mouse, and touch, allowing users to complete common tasks like browsing webpages and typing text;
  4. Supporting screen readers. Allows users with vision impairment to perceive the content. The course suggests that we write alternative text to images, add appropriate aria labels to interactive elements like buttons, and consider the focus order of elements.

Here is a website that demonstrates the color modification feature: HubSpot.com

On the top navigation of this website, it provides a switch for us to toggle a high-contrast mode. Moreover, it also supports reduced motion effects — if I enable the reduced motion setting on my device, this website will minimize motion effects as much as possible.

Equity

The course also introduces a concept called “equity-focused design.”

Instructors clearly define the difference between “equality” and “equity”:

  1. Equality: Providing the same amount of opportunity and support, everyone receives the same thing;
  2. Equity: Providing different amount of opportunity and support according to individual circumstances, ensuring everyone can achieve the same outcomes.

The course also points out that equity-focused design means considering all races, genders, and abilities, especially focusing on groups that have been historically underrepresented or ignored when building products.

They use a survey question as an example: when gathering participants’ demographic information like gender, it is not enough to provide three options: “Male”, “Female” and “Other”. To make our design more inclusive and equitable, we should offer additional choices, including “Male”, “Female”, “Gender-nonconforming”, “nonbinary” and a blank field. The latter provides non-conventional gender options, uplifting those who might be marginalized in conventional surveys. This approach also aims to balance the opportunities for all groups to express themselves, ensuring their voices are treated fairly and heard.

In this lesson, I clearly faced a culture gap from the West. In fact, I don’t really like to dig into this concept deeply, mainly because I can’t determine whether this approach is right. Sometimes I think it is unnecessarily complicated, but at other times, I recognize that there are people with non-traditional genders around us who may truly be eager to be treated fairly.

When I was learning this lesson, I realized that there was an opportunity to incorporate accessibility features into the project I was recently working on. I will write a new post if this project lands successfully.

* This concept is mentioned in Module 2 of Course 1 (Foundations of User Experience (UX) Design — Module 2 — Get to know the user)

This is a wide banner-like image with a dark green background and the words “Guidance for Job Hunting” in large, white text centered across the slide.

Guidance for Job Hunting

In the final course, instructors teach us how to lay out a portfolio and what content should be included. They also inform us the process of interviews and how to thoroughly prepare for interviews.

The guidance they mentioned is for the Western workplace, which may not seamlessly fit in the Chinese workplace. For example:

  1. They point out that designers should have a personal website and case studies regularly. However, Chinese designers prefer to publish their case studies on public platforms like ZCOOL and UI.CN;
  2. They also teach us how to build our digital presence and network through LinkedIn. However, these approaches are not common in the Chinese job market, where the most popular methods are directly submitting resumes and getting recommendations through acquaintances.
  3. They inform us how to handle panel interviews. I have interviewed with a wide range of companies, from startups to corporations, and never encountered panel interviews, which means that the panel interview is not popular in this industry.

I was deeply impressed by how they elaborated on the preparation and important considerations during the interview process. For example:

  1. Research the main business of the company you interview for beforehand, and clearly understand why you are a good fit for the company;
  2. Prepare answers to common interview questions beforehand, such as a personal introduction, your strengths, and descriptions of your case studies;
  3. We should learn how to answer difficult questions using the STAR method, and prepare well before starting an interview;
  4. Adapt the focus and questions according to the interviewer’s role to show you are a professional;
  5. During the interview process, you might be asked to complete a task. Therefore, we should practice the ability to think aloud and clearly define questions, since interviewers might pose vague questions on purpose.

I resonated with the approaches and tricks mentioned in the course that I had previously used, which gave me a strong feeling that I was on the right track.

Additionally, the course also provides detailed instructions on how to pursue freelance design work. For instance:

  1. Clearly identify your target audience and understand why they should choose your service;
  2. Know your competitors, identifying what they can’t provide but you can;
  3. Promote your service and build word-of-mouth by attending online and in-person events, and getting recommended through acquaintances;
  4. Calculate the business expenses, set fair prices for your services, and make financial projections — estimate what your finances will look like in the first month, the first 6 months, and the first year.

* This concept is mentioned in Module 3 of Course 7 (Design a User Experience for Social Good & Prepare for Jobs — Module 3)

To sum it up

Well, above are lessons I’ve learned from the Google UX Design Professional Certificate on Coursera over the past two months. I think that this is an interesting course, although not all content can be applied in my daily work, I’ve also learned the thinking processes and workplace cultures of designers in another part of the world.

I strongly recommend designers reading this post consider to enrolling in the Google UX Design Professional Certificate, by doing this, you might probably gain new insights. The course costs $49 monthly, which is not expensive. It is likely to complete the entire course over two or three months if you have a full-time job.

Things worked as I expected, and I will start my next project in the second half of the year.


Lessons I learned after completing the Google UX Design Professional Certificate was originally published in Bootcamp on Medium, where people are continuing the conversation by highlighting and responding to this story.

在外置硬盘上,加密安装 ubuntu

需求:

  1. 在便携硬盘盒(M.2 SATA/NVME)安装 Linux(Ubuntu/Zorin),以便在不同的电脑上都可以启动使用。
  2. root 级别的系统分区加密(使用 LUKS & LVM)。
  3. 不要把整块硬盘都加密,而是在硬盘上保留一个未加密分区。这样也可以作为普通的移动硬盘使用。

——这篇攻略和是否外置硬盘盒,没多大关系。普通内置硬盘也可以这样加密安装。

最新的 Ubuntu 22.04 之后的版本,在安装界面里自带了 LVM 全盘加密安装的选项。但是并不能满足第 3 条需求。所以还需要一些复杂的手动操作。

安装过程尽量围绕 ubuntu 的图形安装界面,对新人友好。参考并验证了这篇教程。但原文连同 /boot 引导分区也一起加密了,于是在配置上略显繁琐。我觉得加密 /boot 并不是很有必要,做了一些改动。最终的硬盘分区结构为(以 512GB 硬盘为例):

  • 大约 800MB,EFI 引导分区
  • 大约 300GB,LUKS 加密分区。在其中配置 LVM 逻辑分区:
    • 2GB,swap 交换分区
    • 大约 300GB,Ubuntu 系统分区 root /
  • 大约 200GB,普通移动硬盘分区

操作步骤:

下载 Ubuntu,制作 USB 安装盘(过程略)。——然后,强烈建议在整个安装过程之前,在电脑的 BIOS 里,把内置的其它硬盘暂时卸载。

插上移动硬盘和 USB 启动盘。从 U 盘启动电脑,选择 Try Ubuntu。最新的 Ubuntu 22.04 安装程序里,已经内置了所需的 cryptsetup 和 cryptsetup-initramfs 软件包。因此,整个安装过程中,应该不需要连接互联网。

首先,把硬盘预分区。分区软件有很多种,可以用原文的 sgdidk,也可以直接用图形界面下的 Disk 或者 Gparted。在硬盘上创建 GPT 分区表,然后分成:

  • 大约 800MB,EFI 引导分区
  • 大约 300GB,要加密的系统分区
  • 余下的约 200GB 移动硬盘

这些分区都先不用格式化。记住第二个分区的名字,本文假定为 /dev/sda2。

分区成功后,关闭分区软件,打开 Terminal 命令界面,执行 root 权限

sudo -i

将系统分区加密。按提示输入密码,——这个密码,就是以后每次启动时,挂在硬盘用的密码。和安装 Ubuntu 时的用户密码,并不是一回事。

cryptsetup luksFormat --type=luks1 /dev/sda2

解锁刚刚加密的分区:

cryptsetup open /dev/sda2 hd2_crypt

创建逻辑卷组(LVM),然后在其中创建 2GB 的 swap 交换分区,再把剩余的空间创建为系统分区(这两个分区的大小,大家自行调整):

pvcreate /dev/mapper/hd2_crypt

vgcreate ubuntu--vg /dev/mapper/hd2_crypt

lvcreate -L 2G -n swap_1 ubuntu--vg

lvcreate -l 100%FREE -n root ubuntu--vg

然后,运行桌面上的 Ubuntu 安装程序(Terminal 先不要关),在磁盘分区页面,选择 Something else,进行手动分区。

  • 把 /dev/mapper/ubuntu—-vg-root 格式化成 ext4,挂载为系统根目录 /
  • 把 /dev/mapper/ubuntu—-vg-swap_1 设为 swap 交换分区
  • 把 /dev/sda1 设为 EFI 引导分区

点击 Install Now,确认对分区的设置。注意,到了下一步创建用户的界面时,先不要继续。切换回 Terminal 命令行界面,正式安装前,在 GRUB 中启用加密(能看懂下面这些命令的话,也可以直接去编辑相应的文件):

while [ ! -d /target/etc/default/grub.d ]; do sleep 1; done; echo "GRUB_ENABLE_CRYPTODISK=y" > /target/etc/default/grub.d/local.cfg

然后回到创建用户的页面,点击继续,开始安装系统。安装结束后,先不要 restart。而是点击 Continue Testing。

回到 Terminal 命令行界面,chroot 到新装的系统:

mount /dev/mapper/ubuntu----vg-root /target

for n in proc sys dev etc/resolv.conf; do mount --rbind /$n /target/$n; done

chroot /target

mount -a

原文说此时需要(联网)安装 apt install cryptsetup-initramfs;但我用的 ubuntu 安装程序已经自带了,并不需要联网安装软件包。

添加密钥文件相关设置:

echo "KEYFILE_PATTERN=/etc/luks/*.keyfile" >> /etc/cryptsetup-initramfs/conf-hook

echo "UMASK=0077" >> /etc/initramfs-tools/initramfs.conf

创建密钥文件并将其添加到 LUKS

mkdir /etc/luks

dd if=/dev/urandom of=/etc/luks/boot_os.keyfile bs=512 count=1

chmod u=rx,go-rwx /etc/luks

chmod u=r,go-rwx /etc/luks/boot_os.keyfile

将密钥添加到 boot_os.file 和 Crypttab

cryptsetup luksAddKey /dev/sda2 /etc/luks/boot_os.keyfile

echo "hd2_crypt UUID=$(blkid -s UUID -o value /dev/sda2) /etc/luks/boot_os.keyfile luks,discard" >> /etc/crypttab

更新 Initialramfs 内核映像

update-initramfs -u -k all

此时全部结束。可以重启系统啦。


关于这个硬盘密码:

  • 是用来防止,别人拿到这块硬盘时,无法查看硬盘的文件;
  • 并不能防止,当你登入系统后,因为系统漏洞或操作失误,而造成的入侵;
  • 这个密码,如果忘记了,硬盘里的文件,就再也无法看到了!!(有添加 recovery 的操作,但我觉得没必要);
  • 每次开机启动时,都要输入一次这个密码。所以,虽然密码需要足够复杂,但最好选一个,自己能方便记住,日常使用的方式。

如何修改硬盘密码:

最简单的方式,是在已经启动的移动硬盘系统里,先通过 disk 等分区软件,确认加密分区的名字(这里假设仍然是 /dev/sda2,但实际上不一定了),打开 Terminal 界面,

sudo -i

cryptsetup luksChangeKey /dev/sda2

按照提示,输入旧密码,再输入两遍新密码。最后,更新 initramfs,

update-initramfs -u -k all

就可以了。

面向产品设计的 Web 前端分享会(分享会记录)

最近听说部门里面的产品或本地化运营对 Web 前端相关的内容比较感兴趣,正好我有相关的实践经验,所以在公司做了一个 Web 前端相关的分享会。分享内容包含:

  1. 使用 Devtools:介绍 Chrome 浏览器内的模拟、编辑和审查工具;
  2. 网页和部署:介绍 HTML, CSS, JavaScript, React,以及网站的部署和托管;
  3. 网页性能指标:介绍网页性能常用指标和测量工具;
  4. 资源分享:分享浏览器插件、网站和课程推荐。

与以往不同的是,这次分享会中加入了互动环节。我做了一个代码 Playground,尝试帮助观众了解 React,以及 React Props 的概念,并留了两个小任务,给观众尝试去实践对 React 项目进行编码。

完整的分享内容内容请继续浏览本文。

使用 Devtools

这个章节主要介绍 Chrome Devtools 一些可能不为人知的功能,来帮助我们提高日常工作中的效率和解决一些问题。先介绍 Devtool 里面「模拟」相关的功能。

模拟设备和屏幕尺寸

在 Devtool 里打开设备工具栏,在这里除了能够自由调整网页宽高,还能够模拟各种主流设备的屏幕。

甚至还能读取到网页里面的断点样式,提供快捷切换各种断点的方式。

需要注意的是,这里模拟的设备是会带上 UA 的,所以如果想在电脑里调试一些做了移动端特化处理的网站(比如访问主域名时,判断到是手机设备,则会跳到移动端的专门网站),是需要用到这个功能的。

模拟伪类

Devtools 还可以帮助我们排查各种交互状态下的样式问题,最常用的是,比如说我们想仔细排查某个元素的悬停和按下状态的样式,则可以在选中元素之后,勾选对应的伪类选项。

模拟媒体

在渲染面板(需要手动开启,浏览器默认是没有打开这个面板的)能够模拟部分系统设置,比如亮暗模式、打印模式、高对比度和减少动态效果等。

与之对应地,可以扩展一个概念叫做 CSS 的媒体查询,CSS 还可以探测到很多用户设备的属性或者设置,比如设备指针精度、视窗比例、当前是否全屏模式、设备方向等…

能探测的内容很多,但实际能用起来的可能只有寥寥数个,最全面的信息可以取 MDN 上查看。

编辑网页文字样式

Devtools 还提供了一个新的字体编辑器,能够让我们实时更改网页中的字体家族、字体大小、字重等属性。

编辑网页内容

我们在 Devtools 控制台里面执行代码document.designMode = 'on' 后,就可以实时在本地修改网页文字内容了,就跟平常打字一样。很适合用在测试文案长度的场景。最后也会分享一个浏览器插件,能够对网页做更多的编辑。

审查 React 组件

最后介绍一个审查 React 组件的方法,有时候我们想看某个元素是不是用的组件库,或者这个组件包含了什么属性之类的,可以下载 React Developer Tools,然后点选网页中的任意元素,进行审查。

网页和部署

接下来我介绍一下网页构成和网站部署相关的内容。

通常来说,HTML, CSS, JavaScript 是构成网站的三个要素。其中:

  • HTML 用来用于定义网页的结构和内容,可以用来创建网站的各个部分,比如标题、段落、图片、链接等。
  • CSS 用来定义网页的样式和布局,这个可能会是咱们设计师比较熟悉的部分,我们能够利用 CSS 来定义 HTML 元素的各种样式,控制它们的布局和位置。
  • JavaScript 用来实现各种功能逻辑和操作交互。比如响应点击事件、动态修改网页内容,根据条件执行动画效果或展示特定内容等。

CSS 预处理器

上述的三种语言,都有各自对应的语法规则。而 CSS 预处理器,则改进了原有的 CSS 语法,使我们能使用更复杂的逻辑语法,比如使用变量、代码嵌套和继承等。

简单来说,CSS 预处理器能让我们写样式代码的过程更顺畅,使代码有更良好的可读性和扩展性,帮助我们更好地维护代码。

举个简单的例子,比如原本的 CSS 语法中要求我们给每一个元素写样式时,必须以花括号开始和结尾,而且每一条样式规则直接都要以分号隔开,而 Stylus 则能够让我们跳出这个限制。直接用换行和缩进来代替。

CSS 框架

另一个值得一提的概念是 CSS 框架。CSS 框架则提供了一套预设样式,比如颜色板、字体梯度,布局和断点设定等;以及一些常用组件,如导航栏、对话框和页脚等。

简单来说,就是提供了一批开箱即用的样式,便于开发者快速启动项目,同时也会保留高度自定义的空间,用于支持各种各样的需求。通常 CSS 框架都会包含使用某个 CSS 预处理器,甚至内置了一些图标库,主打一个 “开箱即用”。

这里稍微介绍一下一个 CSS 框架:Tailwind CSS。是一个高度定制化的 CSS 框架,通过大量的预定义类名,使开发人员快速构建和设计网页界面。

与其他 CSS 框架相比,有一个显著的特点是 Tailwind CSS 本身不会包装一个组件出来,比如按钮、输入框的样式,没有预设好的。取而代之的是,Tailwind CSS 将各种原子级的 CSS 类名包装起来,比如:

  • 设置左右两边的 Padding,用 px-[...] 类名来实现;
  • 设置一个元素为块级元素, 用block 类名来实现…

如果想要在 TailwindCSS 中,使用打包好的组件,达到开箱即用的效果,可以通过各种官方/非官方的模版或组件生态来进行。比如:

React

接下来介绍另一个概念:React。这是一个用于构建 Web 和原生交互界面的库(是的,它能够用来做 App,不仅仅是网页)。而且引入了 JSX 语法,将 HTML 和 JS 结合起来,以一种更直观和易于理解的方式描述界面的结构和内容。

React 有一点和我们的设计稿很像,就是它的组件思维。在构建用户界面时,React 主张先把内容分解成一个个可以复用的组件(把具体的交互、功能逻辑写在组件里面)。然后在页面中将各个组件连接起来,使数据流经它们。

下图引用了官网中的一个例子,其中:

  1. 完整的应用,可以理解为由多个组件拼接成的完成网页;
  2. 搜索组件,用来获取用户输入;
  3. 数据列表,会根据用户搜索来过滤和展示内容;
  4. 每个列表的表头;
  5. 表格内每条数据。

现在我们用一个具体例子来简单介绍下 React 的组件。

在上图中,展示了一个页面页面 App.jsx 包含了 Profile、Gallery 和 FAQ 组件,以及 Profile.jsx 组件的代码。右侧是输出页面,展示了三个组件拼接而成的页面效果示意图,其中 Profile 组件模块里展示的内容,是和 Profile.jsx 文件内代码一一对应的。

上述的组件只是将一个模块包装起来,使其能够被其他地方复用。但组件内容是固定的。接下来会为大家展示如何向组件传递 Props,实现上文提到的一句话 “使数据流经他们” 。

在上图中,我们先将一些 Props 传递给组件 Profile(比如这里传递了图片的地址、人物姓名和描述),然后在 Profile 组件内接收这些 Props,并在组件代码内使用这些数据。

现在,我们就做出了一个可以复用的组件了,可以根据不同的内容来展示相关的人物信息。

大家有没有觉得这种做法有点熟悉?是的,在 Figma 中,我们的组件里面也有类似的做法。Figma 组件同样同样传递字符串、布尔和组件等内容。

实际上 React 组件可以传递的参数不仅仅只是上面例子中的字符串和布尔值,还能传递数值、函数、对象、Node 类型甚至另一个组件等。

我做了一个简单的 Playground,提前封装好了一个 Profile 组件,会传递一些字符串、布尔值(是否展示网站标签)以及数值(圆角大小),帮助大家更好地理解。

🛝 Playground

我做了一个 🛝 Playground ,大家可以在里面看到这个组件的具体的情况,实际看一遍代码可能会帮助理解 React 的组建和 Props 概念。

同时我也写了两个小任务给到大家去尝试,大家可以在上面的编辑器中自由尝试。

发布网站

到了这里,相信大家对构建一个网站已经有了初步的认识,接下来我为大家介绍下如何将构建好的网站发布的互联网当中,能够真正地被世界各地的人们浏览。

方法一:部署到服务器

这是比较传统的方法,先将项目相关的文件放进服务器里面(比如阿里云 ECS,或轻量服务器等)。然后在服务器内安装 NGINX,索引到项目文件夹,定义好首页、端口、404 等场景,最后将域名解析到服务器 IP。之后我们的网站就能在互联网上被人们访问了。

方法二:托管到服务商

这种是相对省心的方法,将我们项目所在的 GitHub 仓库,链接到服务商的托管服务当中。等于是由服务商来帮我们部署、发布项目,不用自己来配置服务器的各种内容了。下图列举了几种常见的网站托管服务商,分别是:Vercel,Github Pages 和 Netlify。

以 Vercel 来举例,除了能够托管网站之外,对每一次发布进行管理,甚至能够是对不同代码分支进行独立发布,还能收集网站访问数据等。

网页性能

接下来为大家介绍网页性能相关的内容。通常一个网站性能好不好,我们能够在体验时主观地感受到,比如打开时很慢、滚动时卡顿,或者点击按钮后很久才响应等等。但如果要准确地判断到网页的性能到底如何,是需要依赖具体指标的。

下面介绍三个常用的指标,分别是:FCP(首次内容绘制)、LCP(最大内容绘制)以及 CLS(积累布局偏移)。

FCP(首次内容绘制)

FCP 是一个关键指标,用来测量页面从开始加载到第一个页面内容在屏幕上完成渲染的时间。越快的 FCP 时间能够让用户感知到网页有在正常运行,而不是停滞、无响应。

这里提到的 “内容” ,指的是文本、图像(包括背景图像)、<svg>元素或非白色的<canvas>元素。如下图所示,FCP 出现在第二帧。

LCP(最大内容绘制)

LCP 指的从页面开始加载到可视区域内可见的「最大图像」或「文本块」完成渲染的时间。

这里提到的「最大图像」或「文本块」,具体来说是包含<img>元素、内嵌在<svg>元素内的<image>元素、块级文本等。

而测量方式,则是在页面加载过程中,记录视窗内的元素的渲染大小,取尺寸最大的元素,回溯这个元素被完整渲染的时间。注意,如果元素的有一部分在视窗外,在视窗外的部分不会参与到尺寸比较当中。

如下图所示,LCP 发生在第二帧,因为这个时候渲染尺寸最大的文本块被渲染出来了。后续帧当中,可能渲染出了一些图片,但尺寸都比文本块小,所以文本块依然是这个视窗内的最大元素。

CLS(积累布局偏移)

CLS 是指可视区域内发生的最大布局偏移分数。简单来说就是测量页面在加载时,元素的位置出现意外的偏移情况,如果元素尺寸大,而且位置偏移比较远,那么 CLS 分数就会显著增高。

这个指标会跟实际的用户操作或者体验有直接相关,所以应该也会是咱们设计师需要重点关注的内容,因为有时候布局偏移,是会比较影响用户获取信息、或者进行操作,甚至引发一些不可挽回的损失。

然后我来介绍一下测量网页性能的工具吧。我自己用过这两个,发现其实没啥差别,大家看喜好使用即可:

两个工具都能模拟桌面设备或者移动设备,记录多项关键指标的数据,并给出改进建议。

观察页面性能情况,不仅仅是前端技术人员要做的事情,了解到设计师也是可以参与到其中的。

比如 Guillaume Granger,他会比较想控制页面中 JavaScript 的数量,所以它提到,他会将所有用了 JavaScript 相关信息记录在表格当中。之后每次在网页中使用 JavaScript 时,都会跟之前的记录进行比对,判断重要性,决定是否在这个位置上使用 JavaScript。

开发者 Thomas Kelly 则提出了当意识到页面性能出现瓶颈时,需要做的事情,比如:

  • 制定一个目标,团队一起往这个目标前进;
  • 高频收集页面性能数据;
  • 尝试用不同方式来解决同一个问题;
  • 与同伴分享对性能的一些新发现…

资源分享

最后来分享一下相关的资源吧,包含两个插件、三个学习网站以及一个 React 课程。

插件:VisBug

介绍一个谷歌官方出品的插件:VisBug,主要用来帮助用户在浏览网页时进行调试和设计,包括编辑和可视化页面的 CSS,尺寸和字体等元素。

插件:Motion DevTools

Motion DevTools 是一个检查网页动效的插件,可视化和分析用户交互设计中的滚动、动画效果,并支持实时编辑、预览或导出等功能。

网站推荐

接下来介绍三个在国内外拥有较高知名度和影响力的设计师和开发人员。他们的观点、经验分享往往能给我带来一些新的启发。尤其是他们对钻研新技术的热情,是非常强烈的。

课程推荐

最后强烈推荐一门 React 课程——The Joy of React,这个课程我在年初的文章也有提到过,是以互动式课程的形式,由浅入深地讲解 React。从基础的组件 props 和 JSX 知识,到 Hooks、API 设计等等,讲述非常清晰,强烈推荐。

分享会感想

分享完之后感觉效果可能还不错,大家都有各自的收获。而且分享会中也不时有人提出相关问题,我也一一进行解答了。

或者也有对我分享内容的一些补充,比如我在分享完 Devtools 环节的时候,有同事也分享了一个在 Application — Cookie 面板里快速切换网页语言的方法。

后面了解到大家对于 CSS 和 React 那块听的比较迷糊,因为原本没有实践过的话,会对这些没有什么概念。而且大家好像对 🛝Playground 没有什么兴趣,并没有人对里面的内容有什么提问和看法之类的,可能到这一步都比较迷糊?🤔

指标那块倒是有不少同事关心,问了几个问题,比如有哪些方法来去改进几个指标的数据,或者在设计过程中是否可以提前避免性能问题等等。

总体来说和之前的分享会相比,这次分享会的参与度比较不错。

【译文】无障碍设计:三个 Jira 图标的故事

导读:Atlassian UX 团队的设计师 Hannah McKenzie 分享了一个优化图标的小案例。主要目的是使图标对色盲人士也具有良好的可访问性。
Photo by Harry Quan on Unsplash

小细节会产生巨大的影响

你知道世界上有很多种不同类型的色盲吗?在澳洲,有大约 50 万人生活在某种程度的色盲当中。在美国,这个数字接近 1200 万。而在全世界,估计有 3 亿人生活在某种程度的色盲当中,网上的一些资料显示,这个数字甚至接近 3.5 亿。

其中红绿色盲占据了大多数,他们难以区分红色和绿色。

现在 Jira 的 Pull request 的图标是通过用灰色、绿色和红色来区分 Open, Merged, Declined 这三种状态。

原本的图标,灰色代表 Open,绿色代表 Merged,红色代表 Declined。

红绿色盲人士看到的图标就像这样:

在 Jira 的软件项目管理看板当中,这些图标很小,并且与每个缺陷中其他小元素一起出现。比如故事点、负责人头像和缺陷 ID。

这是一个 Jira iOS app 项目看板的例子。其中 Pull request 图标用红色圆圈高亮起来作为示意。

虽然图标很小,但这些图标确实在传达有用的信息。

在 2021 年末,我开始进行优化开发状态图标的工作,并让色盲用户可以访问它们。它开始于一则我在无障碍团队 Slack 频道里的消息:

“我们最近有改进 Jira pull request 图标计划吗?现在这些图标是完全相同的,只能通过颜色来区分。”
Photo by GeoJango Maps on Unsplash

在 2022 年初,几位设计师和研发在 Slack 的讨论中尝试了一个粗略的方案:

设计师开始尝试多种概念,产生了更多的方案:

在几个发散性的讨论和设计环节之后,全新的,具有可访问性的 Pull request 图标诞生了!

虽然这些图标仍然由灰色、绿色和红色来分别代表 Open, Merged 和 Declined,但同时,使用了打勾代表 Merged,打叉代表 Declined。而且 Merged 的图标用线条连接在一起(表示合并到分支),Declined 的图标线条则没有与任何东西连接。

这段经历教会了我…

  • 即使过程很棘手,但也请坚持下去。如果你面向的是比较复杂的产品,或者在大型的机构中,你需要主动去在不同团队去联系到合适的同事;
  • 一些看起来很小的设计往往会涉及到很多不同的人。通常是很多件小事(就像在这个案例当中,有许多交流和发散性会议)汇聚成一件大事,以最终呈现在用户面前;
  • 设计一个支持无障碍的产品对很多人来说是至关重要的,小细节真的很重要。每个人都会受益,包括自认为是并非残障群体的的人士。比如电话和电动牙刷,最开始就是为残障人士而设计的。

Atlassian 里几位没有色盲的设计师和工程师对于新设计图标的看法:

“我不是色盲的,但这些图标让我一眼就能看懂。”
“这简直是宝藏。原本同样的图标,不同的颜色让我感到疑惑。我经常想,这是对应着什么分支状态?这是一个非常惊人的优化。”

所以这篇文章用来提醒大家关注细节 — — 即便是小细节也会产生巨大的影响。

Photo by Balázs Kétyi on Unsplash

探索让新用户更容易上手的产品设计策略

封面图。深蓝色背景,中间有经过模糊处理的蓝紫色渐变,背景有宽松的网格纹理。标题是探索让新用户更易上手的产品设计策略。

背景

今年二月底入职了新公司,主要产品是企业级研发管理 SaaS 软件。这家公司的新员工在参与产品迭代之前需要进行相关的学习和培训:

  • 第一、二周先自己学习使用公司的软件和行业名词,并模拟成销售的角色来参与一次产品演示和场景化配置的考核;
  • 第三周基于自己感兴趣的主题来分析竞品和自身产品的某项特点,并作一次分享会;
  • 第四周才正式开始参与产品设计,进入到迭代当中。

我是比较认同现在这一家公司的入职流程的。毕竟 SaaS 软件是会有点学习成本,自己先把各种功能、场景、配置和行业相关名词学会了之后才能更顺畅地合作。

就在我刚开始学习使用公司软件的时候,会感到有些吃力。比如:

  1. 功能/流程配置。比如我想要做某项配置,但因找不到入口导致无法配置,或被某些逻辑限制导致结果与预期不符时,需要去到帮助文档里搜索相关概念,然后再对照文档里面写的步骤来实现;
  2. 名词释义。有些行业内的名词我之前没接触过,或者不能够直接根据字面意思理解的时候,我需要去文档或者维基百科上查找相关的释义、使用场景和最佳实践。比如「故事点」、「用户故事」、「史诗」等;
  3. 系统概念理解。我需要通过查阅文档、询问导师和自己反复尝试来去了解软件系统内的一些运行机制,比如说多种层级的权限,或者一个叫「池子」的概念…

所以在第三周的分享中我选择了主题是关于产品设计中如何帮助新用户上手使用软件。正好自己也看看其他做的好的产品是怎么做的,之前这方面的实践比较少。

概念学习

橘色的胖猫面对电脑屏幕,该插图由 Midjourney 生成。

在实际进入竞品里体验之前,我先去网上学习点跟帮助系统相关的概念。我通过 NNGroup 的文章了解到帮助会分为两大类:

预防性帮助 (Proactive Help) 指的是系统在用户遇到问题之前提供帮助。常见的方式包括: Onboarding、新功能提示、上下文帮助(Contextual Help) 和向导等。

针对性帮助 (Reactive Help) 指的通过文档、视频、课程等资源来回答和解决用户的具体问题。或者为想要成为专家用户的人提供详细的文档和资源。

而「预防性帮助」,又能分为两种类型:

主动呈现 (Push Revelation): 不考虑用户的任务而提供帮助内容。强调主动提供帮助信息而不考虑用户当前行为。这种方式会可能打断用户进行中的任务并引起用户的不适,需谨慎使用。

被动揭示 (Pull Revelation):与用户当前行为相关的帮助。侧重于与用户当前正在进行的动作、行为和活动等有紧密关联。提供有助于用户完成当前任务的相关建议和信息。

经过梳理后,这些概念的关系图像大概是这样:

帮助概念的关系图。
NNGroup 了解预防性帮助和针对性帮助的概念

接下来就从上述的多个手段中选取几个,结合 Jira、Asana 和 Notion 的做法来做一些观察和分析,并尝试总结出在它们身上能学到什么。

对三个调研对象:Jira、Asana、Notion 的介绍。

新用户旅程

新用户旅程 (Onboarding) 设计有助于引导用户使用产品,让用户发现产品的核心价值,进而推动用户留存、转化和推荐。

我分别体验了 Jira, Asana, Notion 的 Onboarding,发现这三者的流程大致相似,但基于软件本身的功能不同而有些许差异。值得一提的是,他们都做得很细致

流程

走查了三款软件的 Onboarding 流程,并以粗颗粒度来划分步骤。

对 Jira、Asana、Notion 这三个竞品的 Onboarding 流程梳理。都有同样的五个步骤:账号注册、收集信息、创建入门项目、邀请成员、进入主界面。

其中与比较关键的是第二步:

第二步:收集信息。收集用户的角色、工作职能、主要任务、团队规模等信息。用于获取用户的标签,以便后续进行精细化运营。同时影响到后续的配置、预设的数据和界面内提供帮助的程度。

第二步里收集到的信息会影响到创建入门项目、邀请成员和进入系统后的主界面。比如在 Notion 中如果提供了「个人使用」作为用途,则流程中不会出现「邀请成员」的模块。

千人千面

值得一提的是,Onboarding 流程中收集的用户信息,可以为后续的系统预设和默认配置提供参考。

比如在 Jira 中,系统会根据用户填写的团队类型和主要工作类型等因素,推荐对应的模板。如果用于管理软件开发团队,则推荐用敏捷项目模板;如果是管理业务团队,则推荐用项目管理模板。并引导用户使用模板创建第一个入门项目。

Jira 根据团队类型来推荐模板的案例。左侧的截图是当用户选择了 “I am new to Jira” 和 “I am setting up Jira for my software teams” 时,下一步创建项目会推荐使用 Scrum 的模板;而右侧的截图是当用户选择了 “I am new to Jira” 和 “I am setting up Jira for my business teams” 时,下一步创建项目会推荐使用 Project management 的模板。

并且根据用户对 Jira 和敏捷方法论熟练度,决定是否在用户首次进入主界面时提供向导。如果是新手,在进入主界面时会询问是否需要跟随向导了解界面和功能;如果是有经验者,则没有向导提示。

Jira 根据熟练度决定是否出现功能向导的案例。左侧的截图是当用户选择了 “I am new to Jira” 和 “My team is new to agile methodologies” 后,进入主界面会出现向导提示;右侧的截图是当用户选择了 “I am experienced with Jira” 和 “My team is experienced with agile methodologies” 后,进入主界面没有出现向导提示。

再比如在 Asana 新用户旅程中,如果用户选择角色是「高管」,系统内新手引导卡片内的称谓和步骤,都会与「团队成员」的角色不同。

高管的引导卡片添加了「开始成为一名管理人员」的文案,而初始配置的步骤包含「创建报告」和「创建一对一会谈项目」等;而团队成员的引导卡片则是「填写个人资料」、「下载 App」和「查看第三方集成」。

Asana 根据角色定制新手引导的称谓和步骤的案例。左侧的截图是当用户角色选择了高管时,出现相应的称谓和步骤,如添加项目团队和创建一对一会议的项目等;右侧的截图是当用户角色是团队成员时,出现相应步骤,如继续设置项目和下载 App 等。

或者当用户的角色是「经理」,仪表盘卡片也会与「自由职业者」不同。经理的默认仪表盘中有一个卡片是「我指派的任务」,而自由职业者则没有。

Asana 根据角色定制新手引导的称谓和步骤的案例。左侧的截图是当用户角色是经理时,默认仪表盘出现我指派的任务卡片;右侧的截图是当用户角色是自由职业者时,默认仪表盘隐藏我指派的任务卡片。

Notion 也会根据用户选择的工作类型,在邮件中更改相应的称谓。

Notion 根据工作类型定制邮件称谓的案例。左侧的截图是当用户工作类型是销售时,邮件标题是:Notion for sales teams;右侧的截图是当用户角色是工程师时,邮件标题是:Notion for engineering teams。

我们能学到什么

橘色的胖猫面对电脑屏幕,该插图由 Midjourney 生成。

💡 定制个性化的用户旅程。不同的用户有不同的需求和期望,为了更好地满足用户,我们可以根据收集到的信息来提供更符合其所处情境的预设、引导流程和配置等。

💡 合理利用向导来帮助用户上手软件。向导能帮助用户熟悉界面 UI 和功能,但要避免阻碍用户使用软件。所以需要根据用户对软件熟悉程度来决定是否提供向导,并保留跳过的方式。

上下文帮助

本文的最开始提到预防性帮助有两种方式,第一种是主动呈现 (Push Revelations),比如一进入页面就出现的新功能提示,或者界面操作向导等。

两个 Push Revelations 的案例。左侧是飞书在改版后,首次进入主界面会用模态弹窗来推送更新通知;右侧是蓝湖在首次进入主界面时会用气泡卡片来主动引导使用演示项目。

而这里重点介绍的是另一种:被动揭示 (Pull Revelations)。而「被动揭示」有一种做法叫做上下文帮助 (Contextual Help)。这是指根据用户参与的特定活动,展示与此相关的帮助信息。强调要与用户当下的活动密切相关,而不是统一的推送。而具体的做法有很多种,比如:工具提示、向导、输入框提示、内嵌帮助中心等。

使用案例

Jira 的筛选器界面,在用户没有创建过筛选器时,会出现内嵌的帮助中心,呈现与筛选器相关的帮助;而当用户当前已存在筛选器,打算继续创建时,则会默认隐藏内嵌的帮助中心,用户可以手动点击右上角的问号图标打开。

Jira 使用上下文帮助的案例。在 Custom filters 页面中,如果当前列表内无筛选器时,主动弹出帮助中心;如果当前列表已有筛选器时,隐藏帮助内容,只能在右上角帮助中心触发。

相似地,Asana 的 Task 列表中,用户对任务进行多选后,也会在操作栏出现与之相关的工具提示。

Asana 使用上下文帮助的案例。在多选任务时,底部的工具栏出现紫色气泡样式的帮助提示,介绍更新截止时间的方法。

同时也可以看看其他 SaaS 软件的做法,不必局限于竞品。因为这种设计理念是通用的,都是为了帮助用户更好地上手,为用户持续提供价值。比如 Slack 也在这方面下了很多功夫。

Slack 使用上下文帮助的案例。左侧是 Slack 消息列表里滚动距离超过某个值的时候,出现建议使用搜索功能的工具提示;右侧是当侧栏被隐藏时,也会出现一个控制工具栏出现/隐藏的快捷键工具提示。

我们能学到什么

橘色的胖猫面对电脑屏幕,该插图由 Midjourney 生成。

💡 帮助内容保持简洁。使帮助的内容简短并有效,并且在用户要求之前不要呈现过多细节或复杂的内容。

💡 易用且不干扰。上下文帮助可能会干扰已经熟悉界面或者不需要帮助的用户使用。所以在呈现帮助内容时,确保使用轻量的样式,并且允许用户跳过帮助。

💡 使帮助内容可以在其他地方访问。用户可能看到过一些帮助提示,但当时他们忽略了或者忘记了,这在复杂的软件里很常见。所以仍然需要提供其他方式来使用户获取到帮助内容。

模板

模板中心

用户使用 SaaS 软件通常是带着现实情境过来的,比如希望进来做任务追踪,或者是进行多项目的管理和进度追踪等。

所以我观察到这几款应用的模板生态还是比较丰富的,覆盖了多种场景。完善的模板能够帮助用户快速上手,减少学习和操作成本。

Jira 的模板中心以业务为基础,更多地关注具体的业务流程、管理流程和功能的实现。适用于企业内部、管理领域软件行业。并且有详细的模板使用说明和相关模板。

Jira 的模板中心,由前后两张英文界面的截图组成。前一张截图是使用 Scrum 模板的一些提示,正文以展开/收起的方式来展示;后一张是模板中心的首页截图,其中左侧是分类栏,右侧是模板。

Asana 的模板按照团队内不同职能部门来划分,侧重于流程优化。并且有详细的模板使用说明。

Asana 的模板中心,由前后两张繁体中文界面的截图组成。前一张截图是日常站立会议范本的模板详情和使用说明;后一张是范本库的首页,以网格的形式展示多个模板类型。

Notion 的模板中心按照专业领域和个人兴趣分类。适用于个人、自由职业者和信息分享平台等。并且允许用户上传自己做的模板并进行收费,既能够满足用户的个性化需求,又能够为 Notion 和整个社区提供更多的价值和机遇。

Notion 的模板中心,由前后两张英文界面的截图组成。前一张截图是 Task architect 的模板详情页,后一张截图是 Notion 模板中心的首页截图,其中左侧是分类栏,右侧是 Notion Pick 分类下的模板。

本地化

值得一提的是,Notion 和 Asana 的模板中心做了比较细致的本地化处理,切换语言后会呈现更符合用户所在地区的分类和模板。

Notion 针对地区提供不同的模板中心首页示例,由两张截图组成。左侧是日语界面,右侧是英语页面,其中日语界面下,展示的是日语相关的模板分类和模板;而英语界面下,展示的是英语相关的模板分类和模板。
Asana 针对地区提供不同的模板顺序示例,由三张工程分类的模板截图组成。左侧是繁体中文界面,第一个模板是产品蓝图,第二个是日常站会;中间的截图是日语界面,第一个模板是每日站会,第二个是冲刺回顾;右侧的截图是英语界面;右侧的截图是英语界面,第一个模板是缺陷修复,第二个是产品蓝图。

其中 Asana 的模板顺序,「每日站会」在日语和英语中,分别是首位和末位。为此我也有去了解过美国和日本的文化差异,试图去解释为何 Asana 要这么做,这是调研出来的差异:

  1. 文化倾向。日本强调集体主义,注重团队合作和群体利益;美国强调个人自由,注重个人的成就和个人的价值。
  2. 协作模式。日本注重面对面的交流和沟通。在组织中强调员工之间的默契和团队合作精神;而美国更加弹性化,注重个人的私人时间和团队协作效率的平衡,支持远程协作。
  3. 企业文化。日本注重团队合作、持久性和精益求精,对个人规范和职业素养的要求高;美国注重灵活性和创新,注重持续快速发展和快速创造价值。

这些未必是 Asana 做这种本地化差异的理由。但是能反映出来,日本和美国这两个国家在霍夫斯泰德文化维度来看,是有明显差异的。如果之后工作中我有相关的设计机会,也会多多尝试基于两个国家文化差异,而作出不同的设计策略。

我们能学到什么

橘色的胖猫面对电脑屏幕,该插图由 Midjourney 生成。

💡 模板丰富实用。模板对于 SaaS 软件的用户来说是非常重要的,它可以帮助用户快速上手并减少学习成本,并且加深客户对产品定位的印象。

💡 帮助新用户上手。不同 SaaS 软件的模板中心存在一定的差异,它们通常会按照业务场景、职能部门、专业领域和个人兴趣等各种标准进行分类。

💡 关注本地化策略。设计模板时需要考虑到不同地区、不同文化和不同工作习惯的用户的需求和习惯,并且根据实际需要进行调整和优化,以便更好地适应当地市场,吸引更多潜在客户。

帮助中心

产品文档

产品功能文档或开发者文档,是 SaaS 软件帮助中心的标配。我也有去看不同产品的功能文档,看看他们为了帮助用户更好地理解和使用,做了哪方面的努力。

比如 Asana 会标记截图中的行动点,然后在旁边写上相关的步骤操作。标记行动点是用户更容易发现目标,而分步描述则让文字更加简洁易懂。

Asana 的四张帮助文档截图。由两张在中间的清晰截图和两张在边缘的逐渐淡化截图组成。其中在中间靠右的截图里,用绿色方框高亮帮助文档里用有序列表来做步骤的做法。

值得一提的是,Asana 不仅仅提供产品功能文档,还按场景分类,提供多个工作流程的配置方式(最佳实践),比如会议、日历和计划等。试图去引导用户按照 Asana 所推荐的方式来去使用该软件。

Asana 的最佳实践页面截图,由前后两张繁体中文界面的截图组成。其中前一张展示了如何在 Asana 中建立日程的相关步骤和做法;后一张则是最佳实践的页面截图,左侧是类型,右侧是网格排列的关于该类型的最佳实践。

其他资源

调研中发现现在的帮助中心内容丰富,除了常见和必要的产品功能文档/开发者文档之外,还有其他很多提供帮助的资源。比如视频讲解、视频课程、实践案例、社区、博客、公开课等。

Jira 通过社区来加强与用户之间的联系,比如:处理用户反馈、新功能发布的通告和邀请客户参与一些试验性的功能等等。社区内也会常驻社区领袖来响应用户的反馈。

Jira 的社区界面截图,由前后两张英文界面的截图组成。前一张展示了在用户提问的详情页里,有社区领袖来回答用户的问题;后一张是 Jira 社区界面的截图,展示了 Jira 分类下的帖子。

Notion Academy 提供了详尽的视频课程,由浅入深。比如从基础的界面功能、团队管理,到使用数据库和人力资源场景下的大型团队空间配置等。

Notion Academy 的界面截图,由前后两张英文界面的截图组成。前一张展示了 Using data 课程下的课程列表;后一张是 Notion Academy 的主界面截图,左侧是帮助内容的列表,右侧是具体的帮助内容,其中用绿色方框高亮了课程难度由低到高排序的策略,并用紫色方框高亮了最佳实践课程的分类。

Jira 和 Asan 都会比较积极地举办线上公开课 (Webinars)。通过这种方式来提高品牌知名度、建立专业的形象,保持和用户交流,并最终促进销售。

Jira 和 Asana 的 webinar 界面,由前后两张英文界面组成。前一张展示了 Asana 的 webinar 主界面,标题是 “Join a live training webinar”,下方展示了两个 webinar;后一张是 Jira 的 webinar 界面,标题是 “Webinars”,下方展示了两个 webinar。

值得一提的是,我观察到海外的产品,对于视频课程除了直接把视频传上去之外,还能够多做几件事情来提升视频课程的阅读体验,并且在国际化场景更加友好。

  1. 支持 CC 字幕。帮助非视频语言母语的用户更好地理解视频内容,同时也能为听力障碍和不方便使用扬声器/耳机的用户提供便利。
  2. 支持时间轴目录。帮助用户快速了解视频的主要内容,并找到自己需要的信息。与图文教程相比,视频获取信息的效率比较低,但这种做法能弥补缺陷,提高用户的学习效率。
  3. 支持文字稿。帮助用户更好地跟进视频的内容,也方便他们在需要时快速查找相关的信息。并且同样能为听力障碍和不方便使用扬声器/耳机的用户提供便利。
  4. 加入互动元素。提供与视频课程相关的调查、实时聊天室或小测试,能够促进学习效果并增加兴趣和参与度,提升课程质量。
三个平铺的 Asana Academy 内视频课程的英文界面截图。左侧是 Asana 教学视频中打开了 CC 字幕的选择语言菜单,并用绿色方框高亮;中间是 Asana 教学视频中打开了文字稿界面的菜单,并用绿色方框高亮;右侧的是用绿色方框高亮 Asana 教学视频下方的时间轴目录。
两个平铺的英文界面截图。左侧是 Jira webinar 详情页的截图,该截图内中间是视频内容,视频周围被多个模块所包围,按顺时针分别是:Slides、Surey、Banner、Resource list、Q&A,用橙色方框高亮了 Survey 和 Q&A 模块;右侧是 Asana Academy 内视频课程的截图,左侧是课程目录,右侧是课程内容,其中用了橙色方框高亮课程的互动模块。

我们能学到什么

橘色的胖猫面对电脑屏幕,该插图由 Midjourney 生成。

💡 细致易用的用户文档。用户使用文档的场景是明确需要帮助,或者希望成为专家用户,了解产品设计背后的概念。所以文档需要足够的细致、具体和易用。比如像 Asana 帮助文档中提供了步骤图,或者 Asana 线上公开课中为视频提供了段落拆分。

💡 丰富的资源和帮助方式。不同人在解决问题和接收帮助方面都有着自己的特点和偏好。所以需要提供多样化的帮助资源,比如:文档、视频、案例拆解、线上公开课等,持续提供影响力。

💡 强调最佳实践。Jira 的帮助中心里有许多关于敏捷开发概念、实践的文章。Asana 的实践案例也在频繁加入自身对工作流的理解。在帮助中心中强调最佳实践能够帮助用户更好地使用软件和理解背后的理念。

💡 增进用户的参与感。帮助系统可以支持互动和社区功能。比如评论、分享、点赞等。为了进一步提升用户的参与度,还会支持社区、公开课等。

结语

以上就是我对公司几款竞品帮助中心调研后,总结出来能够帮助新用户上手的产品设计。整体感受是「帮助系统」这一块可以做得很大,又能做得很细。

往大了做:包含基础的文档、功能引导;进阶的课程、模板和大学,以及上升到行业影响力的线上公开课、线下 Events 和职业认证。

往细了做:Onboarding 流程规划、上下文帮助的设计、文档/视频课程的细节,模板的本地化方案等等。

所以说越做设计越感到自己个人力量的渺小,世界太大了… 但不管怎样,来到新公司我的目的是取百家之所长,扩展下之前没怎么接触到的领域。

碎碎念

文中部分名词(如:Proactive help, Reactive help, Push revelations, Push revelations…)由于我没有在中文设计圈内找到合适的翻译,于是便自己琢磨着做出了翻译,本身自己不是想「造概念」的,但总得有个名字吧。如果读者有其他更好的翻译方案欢迎交流。

另外这是我第一次尝试用到人工智能来参与博客的创作。使用到了 ChatGPT 3.5 来帮我做资料搜集、文本润色&修正、名词释义和总结提炼。比如文中「我们能学到什么」里面的小标题,有部分是我发一段文字后,ChatGPT 帮我总结的,或者我理解了很久的 Pull revelations 和 Contextual helps 的关系,也是 ChatGPT 帮我梳理的。

另外也用到了 Midjourney 来生成这篇文章的封面图背景,以及「我们能学到什么」的配图。

这两个工具的强大不必过多介绍了,只是中途一件有件小事值得记录一下。起因是我想查找 Reactive Helps 相关的内容,就去阅读了 NNGroup 上面相关的文章,以及询问 ChatGPT。令人惊讶的是 ChatGPT 给了和 NNGroup 相反的理解…

参考文档

App 表单校验时机探索

动机

在我接手 App 这波需求迭代的时候,发现一个很常见的问题却没有在设计规范里提到过(其实原本也没啥设计规范…)。那就是:表单的校验时机。

工作中我发现每个保存到数据库的表单都会有至少一个校验规则,最常见的是字数,其他的有类似格式(邮箱、数量)、上下限(价格、库存数)等。而表单的校验时机通常是在三种方式内选择:

  1. 输入中校验;
  2. 失焦后校验;
  3. 提交时校验。

由于接手时并没有规范或者指引帮助我如何判断使用哪种,工期紧张也没有足够时间去探索,我只能拍脑袋地大部分都采取了「失焦后校验」的方法。

后面我发现这其中的差异还是挺耐人寻味的,有必要探索三者之间的各自优劣势和适用场景,于是乎就有了这篇文章。

三种校验时机的差异

输入中校验

效果:输入过程中(即文本有更改时)校验并反馈报错文案。
优点:实时反馈,出错后立即提示。
缺点:容易误判。即未完成输入就提示出错。

适用场景:
1. 纯前端能满足校验需求时;
2. 校验规则较严苛时,如一个表单多条校验规则,或中途某个错误字符直接影响到表单提交时。

修正错误的成本:低
在手机的的「键盘控件」内重新键入内容即可完成修正。

失焦后校验

效果:失去焦点后校验并反馈报错文案。
优点:输入过程中无干扰,在输入完成后再反馈报错文案。
缺点:失焦后才知道结果,修正成本高。

适用场景:
1. 纯前端能满足校验需求时;
2. 用户对输入框内容格式有预期时,如邮箱、手机号等。

修正错误的成本:高 ★★
需要先「失焦」,再回到原本的输入框「重新聚焦」,并通过「键盘控件」修正。

提交时检验

效果:提交表单时校验并反馈报错文案,通常会伴随着使用 Toast 提示。
优点:后端校验时,不影响性能&体验。
缺点:报错反馈很不及时。

适用场景:
1. 大部分需要后端校验的表单。

修正错误的成本:较高 ★★★
需要先「提交表单」,再「找到」出错的的输入框,并「重新聚焦」原本的输入框,通过「键盘控件」修正。

至此,上面列出了三种校验方式的各自优劣势,对比后不难得出结论。

结论

推荐优先使用「输入中校验」的规则。

原因:
1. 反馈最及时;
2. 修正错误的成本最低;
3. 对研发工作量和 App 性能无影响(前端校验时)。

理论支撑:

“理想情况下,所有验证都应该是内联的…”
“…在字段完成后立即修复错误对用户的交互成本最低…”
—— 来自 Nielsen Norman Group 的《如何反馈表单中的错误:10 条设计指南

通过这次的对比,我决定了之后都将「输入中校验」作为主要的校验方式,当然这种方式也有一些不适用的场景,此时就需要换一种校验方式。举例一些常见的不适合用「输入中校验」的表单:

  1. 容易误判的表单,如校验邮箱、电话、网址的格式时;
  2. 设置了数量下限时,如公司业务里的 B2B 商品设置了起批量时;
  3. 需要后端校验时,如需查重或对比数量上下限时。

其他感悟

对需要后端检验的表单态度

因为涉及到后端检验,意味着需要网络,那就会出现加载中/超时/加载失败/加载成功 的情况,所以这种表单一般是失焦后或提交时检验,这对输入体验会相对友好一些。

但也有例外,比如 Twitter 账号在重命名时,就使用的是输入中校验。可能是因为 Twitter 用户量庞大,特别容易重名。提交后检验反而效率更低。

输入前的体验设计

常言道好的体验设计能减少用户出错,在表单输入之前,实际上我们也可以用多种方式明示暗示文本框的填写规则。

一、输入框长度

输入框长度能过暗示文本框的预期填入内容。比如在填地址和邮编时,通常地址我们会预留比较宽的输入框给用户填写,而邮编则可以相应缩减,因为这两个类型的字段,预期填写的文本长度是有明显不同的。

参考资料:整齐划一?不如错落有致。| Ant Design 4.0 系列分享

二、实时字数显示

在输入框旁边实时展示当前字数和上限是也是比较常见的做法。
优点:避免出错;让用户对表单的规则有一个预期。
缺点:页面出现过多此类提示会使页面臃肿,反而会增加视觉&认知负荷。

所以我对这个做法的态度是:每个表单都会有文字输入的上限,超过上限时也一定会禁止提交、出现提示。但是否将字数提示常驻展示,取决于「用户对长度是否有预期」。

比如在一些备注、描述、说明等大段文字里,用户可能会输入到大段文本,但又对这些输入框的上限没有预期,那我这里判断到是需要出现实时字数提示的。而像比如填写姓名、添加标签这种,字数上限只是一个兜底的判断逻辑,不需要特意暴露出来。

另外可以根据存量数据来决定是否展示实时字数提示。比如让后端同事帮忙导出在数据库里的数据,能知道用户在这个输入框里一般会填写多少个字,如果大部分情况都是接近字数上限的,意味着用户在这个输入框会输入较多的文本,此时就需要展示当前字数上限,甚至或者调整校验规则。这是我在上一家公司(千聊)里做过的事情。

三、占位符(Placeholder)

无论是 NNGROUP 还是 Shopify UX,都对占位符文本持有比较谨慎的态度,甚至会用到 Harmful、Avoid 等贬义词。他们主要批判的是用占位符代替标签的做法,我们在使用时避免这种用法就好了。

实际上占位符和标签共同使用时没什么毛病,占位符确实能起到一定的补充作用,用来提示要输入内容的类型和名称,只是不要用来展示重要内容和代替掉标签就好了。合理使用也是减少用户出错的方式之一。

四、常驻帮助文本(Help text)

帮助文本可以视为占位符的进阶版,具体效果在输入框附近常驻一段简短、必要的说明内容,帮助商家了解输入框所要求的格式,或输入后的内容会怎么处理。甚至还可以链接到 FAQ,有丰富的用法。

一条原则

在文本有上限的输入框里,我们会面临一个选择是:超过字数后是否允许输入?

我在这里的建议是允许继续输入,同时会出现报错的反馈,告知规则。因为翻查了很多 UX 资料,都建议在设计中要避免「打断了用户行为」。下面放出两种方法的优劣对比,各位看官理性抉择:

超上限后允许继续输入
效果:输入的文本超过该文本框校验规则上限时,出现报错反馈,同时也可以继续输入文本。
优点:反馈及时,原因清晰。
缺点:🤔…

到达上限后禁止输入
效果:输入的文本到达该文本框校验规则的上限时,禁止输入更多的文字了。
优点:🤔…
缺点:没有反馈,不知道错误原因。

这么看下来,就体验而言是「超出上限后允许继续输入」要好很多。而且这种方法还照顾到一个场景是:允许用户在输入中发现超出长度后,把当前的单词输入完整后再去删减其他内容。

当然毫无疑问,到达上限后直接不允许输入是对设计和研发来说最省力的做法。这种做法下不用反馈,也就不需要做反馈时机的决策、反馈的文案及多语言、文本的适配、反馈后的布局适配…

我有一段经历是项目工期巨紧张,规范也没相关的指引。当时有很多比制定文本输入规则还重要的事情需要处理,于是乎我就都一拍脑袋用了「达上限后禁止输入」的方法。

后面与其他方式对比发现这种做法应该是体验比较差的做法了。像现在我把规范做法加进 App 设计的指引里面之后,就大多数情况下都会使用「允许继续输入,在输入中反馈」的方式实现。

结语

以上内容就是目前来说我对文本框校验规则的一些认识,包含了各种校验时机的对比,输入前的体验设计,以及不打断用户操作的原则。

这次的总结是我挺久之前就想干的事情了,因为平常工作中一直遇到这种问题,也没有一个明确的设计指引能够参考,现在自己写下来这篇笔记之后,之后的设计方案会考虑得更周全,说服力也更强了(希望是吧)…

同时再浅挖一个坑:之后要探索下表单提交按钮相关知识,比如说什么时候要禁用按钮,什么时候是允许点击但报错等等,这个应该还要复杂一点…

参考资料

【译文】如何冲破设计系统的界限

原文:How to push the limits of a design system · Shopify UX
作者:José Torre
译者:李瑞东
翻译小帮手:李泽嘉 @urcharles7(公司的交互 Intern)

为了跟上需求,设计系统需要不断发展。讽刺的是,设计系统的进化似乎有点像先有鸡还是先有蛋的问题。

如果不知道产品业务需要什么,专门负责设计系统迭代的团队就无法进一步发展。另一方面,大多数业务设计团队只在系统的现有规范和组件内完成工作,这不利于进一步推动系统的发展。这样看上去像是僵住了,大家都在停滞不前。

我们 Polaris 团队(译者注:Polaris 是 Shopify 的设计系统)想打破这种僵局,所以采取了行动……

跨越鸿沟

为了防止 Polaris 变得失去创造力,我们必须更接近产品。因此,我们开始了一项名为 PolarisLab 的计划。在几周的时间里,围绕一个特定的主题,与产品团队发起并参与了一系列工作坊和会议。目标很简单,就是要设计系统团队与产品团队紧密合作,以便:

  1. 帮助团队找到解决问题的最佳方案;
  2. 找到设计系统不断发展迭代的方法。

我们的首先聚焦在 Layout 组件上。因为我们开始注意到越来越多的页面似乎不是专门为解决一个问题设计的。相反,页面的设计来自设定好的多个模板之中(以页面布局组件的形式)。这些模板是相当通用的,但并不总是解决一个单一问题的最佳方案。

Layout 组件中有六种选项

过度使用这样的模板可能会使页面看起来在视觉上一致,但会让用户感觉到没有重点和枯燥乏味。

刻板地遵循设计系统提供的模板,使得会出现让内容来适应页面布局,而不是内容主导布局。这使得浏览一个页面变得困难,需要用户花费大量的精力去弄清楚需要的内容在哪里,以及下一步该做什么。

我们还注意到,由于我们的 Layout 组件过于死板,导致团队经常脱离 Polaris 来做一些细微的布局调整,这就导致了代码层面工作量的增加。

我们已经明确了想要解决问题的,甚至已经有了行动的代号,但我们缺少最重要的部分——团队。

寻找团队

我们希望找到那些有兴趣与我们的团队合作改进 Layout 的团队,而且是热衷于发展 Polaris 设计系统的团队。幸运的是,公司里有很多这类型团队。

我们联系到了 7 个不同的团队,在了解到他们的问题空间和最近的工作排期后,我们决定与做 B2B 客户业务的团队合作,因为他们满足了所有条件:

  1. 能够有效地解决问题 ✅
  2. 该案例有可能对其他团队产生影响和启发 ✅
  3. 能够在紧迫的截止日期前交付 ✅
  4. 对开始工作超级兴奋 ✅

不久后我们明确了项目的目标,并开始了合作。我们设定的工作流程并不复杂:

第一步:了解问题

第二步:发散和探索

第三步:收拢和校准

第四步:重复第二步和第三步,直到满意为止

第五步:推进实现方案!

了解问题

通过一系列的 Workshop 及相关活动,我们对这个问题有了更好的了解。

我们首先要求团队做一个现状收集。简单地把一系列的截图和设计放在 FigJam 上,然后让我们去了解业务设计师当时遇到问题,以及他们做的解决方案。

我们都发现了这个 B2B 客户页面大多是聚合了企业客户有关的所有内容,但它在帮助商家快速了解这个特定客户方面做得并不出色。内容缺乏清晰的层次,所以最终效果不理想。

为了开始了解这个问题,并更好地了解页面里什么最重要。我们写下了这个页面里用户所有可能想要完成的工作。然后我们反复调整排序,以确定优先级和重要程度。这是我们最终得出的的结论:

  1. 观察购买行为;
  2. 手动为客户下订单;
  3. 快速访问到地点和联系人;
  4. 评估不同地点之间的销售情况;
  5. 针对不同地区更改服务条款;
  6. 查看操作日志。

通过小组讨论后,我们都认可了这个优先级排序。然后我们又尝试代入商家的身份去假设他们的目的,以确保我们目标一致,达成共识。然后投票选出了一个最接近目标的假设,那就是:

“如果显示的信息集中在一个页面上,商家将能够更方便地完成任务。我们可以通过完成一项特定任务所花费的时间来衡量。”

商家在页面中要完成的工作

上述这些工作并不意味着产生实际的可交付的方案,而是让每个人都能够:

  1. 更了解业务背景,让每个人都在对这个案例有相同的认识;
  2. 开始对内容进行更细致的的优先级排序。因为我们不能仅通过移动元素来实现更有目的性的布局。我们需要从信息层开始,并在此基础上进行构建。

为了让大家更进一步,接下来是用草图来构思问题可能的解决方案。这里的目标不一定是找到解决方案,而是为今后的探索定下了基调。

来自 Workshop 的草稿图

我们鼓励每个人参与到 Workshop 的同事都尝试去画点草图,不管你是工程师还是设计师。有些人在 Figma 上画,但大多数人只是抓起一张纸和一支笔,一旦完成,就拍张照片,然后贴进 FigJam。

通过让同事们自由地画草图,不受设计工具或 Figma 组件库的限制,我们更有可能创造性地解决这个问题,而不一定要遵循预先存在的模板。

在画了一会儿草图后,每个人都分享了他们的想法,我们发现了一些有趣的事情。在画草图的时候,人们开始把客户在页面里可能想要完成的工作作为一个整体来考虑,而不是把注意力放在个别内容上,然后按照模板把它们组合在一起。

这是一个好的开始,因为商家会体验到整个页面,我们就应该这样去做设计。

在每个人分享之后,我们讨论并投票选出了最有希望的想法,这将是后续工作的基础。

发散和收拢

由于大部分探索是设计先行的,我们后续还通过几次包含一名产品经理和几名工程师的 Workshop 来协调和讨论。我们在会议前花了一些时间完善方案,拿到会议上讨论并一起看看有没有可以做得更好的地方。

一些简单的布局尝试

Workshop 之后,设计师们根据讨论的结果继续细化方案。我们想跳出设计系统的界限,但最终解决方案必须符合 Polaris 风格,这是一个很难去达到平衡的事情。对于我们引入的任何新元素,我们必须再三斟酌,要了解它是否能融入 Shopify 里面,并且可以复用到其他团队里。

当我们探索信息的不同组织方式时,我们意识到拥有一个完善的 Grid 设计基础准则是相当重要的,它可以确保不同页面之间有一定程度的一致性,即使信息的组织方式不同。

我们不仅是把页面作为一个整体来看,为了建立层次结构,我们还必须深入去找到更好地利用颜色、空间和文字排版的方法。我们通过有策略地运用颜色,突破字体规范探索更大的字号,来给最重要的元素增加了视觉权重。使它们与其他元素形成鲜明对比,并吸引人们的眼球。

我们还减少了页面中卡片的数量,更多地依靠空间来分组和分离信息。

随着我们的方案逐渐成熟,我们开始与产品和研发部门讨论方案。最终我们经过讨论和方案对齐后,找到了一个多方都认可的解决方案。

Company 页面改版的前后对比

通过重新设计,我们使商家能够更轻易地快速了解一个 B2B 客户。

与其简单的在网页上堆砌信息,指望着商家费尽力气去获取想要的信息,我们干脆重新梳理了一遍网页的内容。我们强调重要的信息,弱化只需要低频获取的信息。最终,让获取重要的事情变得简单,同时保留获取其他所有信息的触点。

作出妥协

然而方案的推进并没有那么美好。我在开始时提到过 Deadline 迫在眉睫,我们只能将解决方案分步交付。

Company 页面的 MVP 版本和理想中的方案

在推行某个方案时,很少有不需要做出一些妥协的,特别是当 Deadline 很紧迫时。这是产品开发过程中很常见的现象,但这并不意味着要在设计质量上做出妥协。

而为了能够做到这一点,你需要了解技术的限制是什么及其原因。

这正是 B2B 团队所做的。例如,在页面中引入新的数据指标和数据洞察是很难的,但他们没有放弃这个想法,而是争取引入任何可以实现的东西,因为他们知道这对商家来说是非常有用的,可以在未来迭代和改进它。

创建可扩展的解决方案

与此同时,我们已经开始在 Polaris 团队中探索新的 Layout 设计准则。在整个协作过程中,我们了解到我们的原本布局组件限制太多,所以我们构建了一个 Grid 布局组件,让我们更容易地构建自定义布局,同时不会脱离设计系统。

团队想要创新,但设计时需要有一定的规则来约束,有时候甚至要依据设计系统已提供的模板。

这次合作让我看到,我们并不缺乏创新的动力和能力,缺乏的是一个目标。当你不知道该做成什么样子时,通常都会呆在舒适圈内,这是会让人上瘾的。

让系统团队积极探索新方式和与他们合作,能够得到新的做法。但这只是一次性的,不可扩展的。所以我们需要找到方法将这种做法纳入到设计系统中,让其他业务和团队的设计师也能复用。

Grid 布局组件是处理「设计创新」和「遵循规范」之间平衡的的一个很好的例子 — — 能够让设计师在 Polaris 内创新。

适应不同断点的 Grid 布局组件

从技术上讲,团队可以不用 Polaris 来实现任何东西,但这导致了不一致性、不规范的体验设计和许多冗余的代码。这使系统更难维护、更新和扩展。

Polaris 是一个工具。我们利用它来发挥我们的优势,但我们不能忘记维护和发展它。就好比如果一把刀变钝了,你不需要去买一把新的,而是要把它磨利。

这次合作很有趣,同时也很有影响力。因为我们在产品和系统上做了改进。

我们不仅一起发布了一个新的布局,而且我们还确立了从整体上改进设计系统的方法。看到这项工作被刊登在 Shopify Editions 上是特别荣幸的。我真想快点看到 B2B 业务实现完整的设计方案之后的效果,以及其他团队使用我们建立的 Grid 布局组件。

如何开始?

如果像 B2B 团队一样,你想推动你的设计系统向前发展,我可以推荐两种方法中的一种。

选项 A:与设计系统团队合作

如果你正在研究一个问题,希望能突破原有的界限,并看到影响整个产品的设计模式的可能性,请考虑与你的设计系统团队联系。

设计系统团队会想要极力避免出现单一的解决方案,但他们很可能倾向于如何让设计系统更好用。特别是这件事对整个公司内的其他团队有可能存在的好处时。

为了证明这一点,我可以告诉你,我已经与另一个团队合作去解决另一个问题。我希望像这样的合作越来越多,因为这种合作确实能给产品和团队带来很多好处。

可惜的是,我知道一个设计团队未必能和所有人合作。但这不应该阻止你创新,还有另一种方法…

选项 B:动员你的团队

其实在与产品团队合作时,我们设计系统团队的主要工作是启发和支持。

这也是我分享这个研究案例的原因。向你展示我们做了什么,我们是如何做的,以及为什么这样做。希望这能启发你,同时也给出了一些可以复用的方法。

要记住的关键一点是,在孤岛上创新真的很难,所以寻找与你有同样热情的合作伙伴。如果你需要快速尝试,不妨用我创建的模板去实际尝试一下前文描述到的 Workshop。

Figma Community 中获取 Workshop 模板

当你完成后,别忘了为设计系统「赋能」噢!

OpenWrt 定时自动释放内存

openwrt automatic memory release因为我的固件可能有内存泄漏,所以想办法定时释放内存。其实就是用 Linux 的方式。

在管理界面 > 系统 > 计划任务,加入下面代码。每天5点和17点自动释放内存。

0 5,17 * * * sync && echo 1 > /proc/sys/vm/drop_caches

设计优美好看的网站截图——Kali Linux

这是我见过的设计非常好看的一个网站:Kali Linux,无论在布局还是色彩、视觉效果上都给人美的感受。下面截图是桌面版的白色版、暗夜版。由于手机上截图的限制,暂时没有找到截取完整网页的办法。提醒:图片是一张完整的长图(分辨率:2560*19066),并没有做切片处理,因此加载、显示过程可能较为缓慢。1、Kali Linux 白色版2、Kali Linux 暗夜版

如何在Mac OS X上结束一个进程?

刚才看论文做笔记时Evernote突然停止响应了,本打算用Activity Monitor强制关闭,转念一想,不如学下如何用terminal强制关闭程序吧!正好有人对kill的一些写法有疑问,放上来分享一下。

1. 活动监视器(Activity Monitor)

不论是Windows还是Mac OS X,一定有任务管理器或活动监视器可以查看进程。想要强制终止一个进程很简单,只要找到想要终止的程序,然后点击左上角的八边形带×按钮即可。
Screen Shot 2016-03-24 at 20.01.48

2. Mac OS X 终端(Terminal)

在Terminal上输入命令来终止程序也很简单。分两步走:1. 拿到想要关闭的进程的ID(即PID);2. 命令此ID的进程关闭。下面展示下操作过程:

假设我想把Evernote强制关闭,首先打开Terminal,输入:
ps -A | grep Evernote
ps是“process status”的缩写,意思是“进程状态”,“ps -A”会列出所有当前正在运行的程序,如果此时直接回车,那么你会在terminal上看到一长串的进程,想要找到Evernote的PID不是很方便……
Screen Shot 2016-03-24 at 20.22.03
为了更方便找到Evernote所对应的PID,我们要对这些让人看得头晕的输出进行小小的处理。“|”是个pipeline,会把当前输出的文本(也就是上头一大串进程)输入到右边的命令中。“grep”你可以把它理解成“抓取”,它会从前面输入的文本中抓出带有想要搜索的文字的所有行。看下图,是不是很简洁?马上就知道Evernote的PID是945了(另一个是EvernoteHelper,不用理会)。
Screen Shot 2016-03-24 at 20.29.10
接下来进入正题——杀死进程!输入:
kill 945
然后……就结束了……杀进程很简单吧?
来我们复习一遍:
找PID: ps -A|grep [进程名]
杀进程:kill [PID]
======
补充:
  1. 请勿随意使用强制结束进程,这是在程序无法响应时才使用的杀招,如果文件没有保存,强制结束进程可能会让你丢失未保存内容。
  2. kill -9 [PID]”也能结束进程,9其实是SIGKILL对应的号码,自然也可以用“kill -SIGKILL [PID]”来结束。大家可以输入“kill -l”查看各种对应代码。
Screen Shot 2016-03-24 at 20.44.18

不能在中文目录右键打开 Cygwin 的解决方法

Cygwin 是一个 Windows 下的 Linux POSIX 模拟器,通过它我们可以直接运行一个 Linux 终端,非常好用。

网络上关于如何添加一个 “在当前目录打开 Cygwin” 的右键菜单的教程有很多,但是这些方法都有一个问题,那就是不能在中文目录下正常工作,于是研究了一番,修复了这个问题。

探索

既然英文路径可以但中文不行,我最先想到的是使用 Cygwin 自带的 base64 命令,将 encode(path) 后的非中文字符串传给 Cygwin 之后,再 decode 得到包含中文的路径。然而不行,正确的 base64 传递到 Cygwin 之后 decode 却是乱码。

问题的原因很容易想到,那就是编码的问题。经过几次输出中间变量后验证了这个猜想:Windows 采用的是 GB2312 编码,而 Cygwin 采用的是 UTF-8. Windows 将当前路径作为参数传递给 Cygwin 主程序时,Cygwin 不能正确读取路径。

解决

修改 Windows 或者 Cygwin 的默认编码肯定是下下之策。解决该问题最终还是绕不开编码转换。我最终的思路为:

  1. 右键点击后,Windows 将当前路径作为参数 1 传递给 run_by_right_click.bat 入口程序
  2. run_by_right_click.bat 将路径写入 chere.path 文件(GB2312 编码),并运行 Cygwin
  3. Cygwin 运行后,将 chere.path 转换为 UTF-8 编码,读取后 cd

我的 Cygwin 安装目录为 C:\cygwin64,Shell 为 ZSH,如果你使用的是 Bash,有的地方与我的不同。具体步骤如下:

step1. 创建右键按钮

导入注册表文件 cygwin.reg:

Windows Registry Editor Version 5.00
 [HKEY_CLASSES_ROOT\Directory\Background\shell\cygwin64_bash]
 @="打开 Cygwin 终端"
 "icon"="C:\cygwin64\Cygwin.ico"
 [HKEY_CLASSES_ROOT\Directory\Background\shell\cygwin64_bash\command]
 @="C:\cygwin64\run_by_right_click.bat \"%V\""

step2. 编写入口程序

我们的入口程序 C:\cygwin64\run_by_right_click.bat

@echo off
 SET dir=%1
 REM 双引号删除
 SET dir=%dir:"=%

 C:
 chdir C:\cygwin64
 rem del /Q chere.path
 set /p="%dir%">chere.path
 bin\zsh.exe -li

bat 代码是真的难写。。。写这段代码我便踩了无数的坑。

step3. 完成目录跳转

在 Cygwin 内编写 ~/.zshrc,在末尾添加目录跳转命令:

if [ -e /chere.path ];then
     /usr/bin/enca -L zh_CN -x utf-8 /chere.path
     CPWD=/usr/bin/cat /chere.path
     rm /chere.path
     cd /bin/cygpath "$CPWD"
 fi

这里用到了 enca 用于自动编码转换,所以需要在 Cygwin 包管理器中安装这个软件。

over! 现在便可以在中文文件夹中右键打开 Cygwin 了。

为啥我要用 Cygwin

最后最后。你可能会说,为啥都新世纪了,你还在用 Cygwin 这种… 模拟器?原生 Linux/ 虚拟机 不好用嘛?WSL 不香吗?甚至 Powershell 不也不错?

那我还真觉得 Cygwin 秒杀上述所有的方案。首先,我只是想在 Windows 上安装一个代替 cmd 的 Shell 环境用于日常操作,并不需要高性能什么的,所以原生 Linux 系统、虚拟机、Docker 就不是解决同一个问题的东西。

至于 Powershell,虽说是比 cmd 好多了,但毕竟是另一套语法和体系,我不想学它也对它不感兴趣。Bash+GNU tools 那才是世界通用法则。ZSH 作为日常使用的终端也确实美观好用!

而 WSL 这东西确实很吸引人,性能比 Cygwin 强太多,几乎就是原生系统。然而!WSL 运行于内核态,与 Windows 平级,就算有文件系统的映射,WSL 也并不能直接当作 Windows 的 Shell 来使用的。看下面的图你就知道我在说啥了。

Cygwin+ZSH 很好用

图中,npm 和 git 是我在 Windows 中安装的 exe 包,而 ssh、tail、md5sum 是 Cygwin 中提供的 Linux 命令,直接相互调用无压力,这才是 Windows 中我想要的 Shell 的样子。可是 WSL 是不能这么做的,两个系统是隔开的。

❌