开源指北:我为「开往」制作跳转页
有一个项目叫做「开往 Travellings」,它维护了一个站点列表,通过每个站点上的按钮,将加入开往项目的各个独立网站串联起来。比如,在本站的底部,可以找到 𝓣𝓻𝓪𝓿𝓮𝓵𝓵𝓲𝓷𝓰 这个链接,通过它,你就可以随机去往别人的博客。
这个项目会通过一个跳转页面来去往他人的站点,在该项目的文档上,提供了各种各样的页面设计,遗憾的是,没有一个设计能完全使我满意。因此,我为这个项目提供了一个新的跳转页:列车(您也可以直接点击此处来体验这个跳转页面)。
现在这个工程已经完成,是时候谈谈这个项目的经过,并且借此机会,对参与开源项目这件事稍作介绍——也许这可以帮到你(至少在很长一段时间里,我需要有人那么帮我)。
设计制作
先来谈谈这个页面的设计。
一直以来,我对列车相当钟情。这并不是说我像那些火车迷(或者火车站迷)那样对各种车型如数家珍,但是我对于列车这一存在——其形象、体验、相关的生活方式——相当着迷。用一个幻想也许可以说明这一点:我曾幻想自己生活在一辆永无止境的列车上,与我那时的社交圈一起永无止境地生活,恰如雪国列车。
因此,我长久以来都在思考:如何把列车作为一种设计元素,并恰当地融入到我的作品中去。而开往这一项目的图标及其各个要素,恰恰和列车高度相关,于是我当机立断开始设计,再也没有比这更好的机会了。
最终给我以确切的灵感的,是由 Alessandro 为 Moleskine 所制作的一个视频中的一个画面:
其带有的氛围感是如此令我着迷。此时,在我那漫长的童年里,那火车窗外的忽高忽低、连绵不断的电线杆,就像是贯穿我审美体验的一柄矛,直截了当地插中了火车这一形象。两者结合在一起,最终有了如下所示的最终设计:
此外,在这个画面上还有一些要素,主要是字体的发光效果、链接触碰后亮起的动效,它们的灵感来自 lo.cafe 这个网站上的设计。
具体的制作细节不在此多谈,其技术并不困难,有兴趣的读者可以访问源码自行阅读。不过有关那绵延向前的电线杆,其实现倒是值得一提。最初我所设想的,是绘制三到四个首尾相连的电线杆图像,在页面上从左到右移动,并在每个图像移出可视范围以后放回到队列的末尾,就像学校里跳长绳的小学生那样。
不过这一技术实现起来相当繁琐。一方面我的技术审美使我天然排斥这种做法,另一方面,我的耐心也不支持我完成这样的工作。随即,我开始思考新的做法。
这时,两个点子戳中了我:一,是数据结构中循环队列的实现,把重复出现的模式直接转换为一个环形;二,是中学物理老师分析电磁学时展示的一个技术:一段直线可以看作是充分大圆形上的一小段弧。这两个想法进而让我想到了新的实现方案:把几个“粗糙的”圆交叠在一起,让其中一段弧在取景框中显示,然后旋转这个圆,正如下图展示的那样:
为了让电线杆恰如其分地“扭动”,我使用了 Excalidraw 这个项目来绘制。
当然,这样的实现亦有一些不足之处。「开往」这个项目的所有跳转页要求被制作成单 html 文件的形式,这就导致图像只能使用 svg 代码来嵌入,而这样相对复杂的图像,显然不如几条直线那么容易绘制。这最终就导致html代码文件里硬生生地塞进了一大串 svg,使程序编写的可读性在很大程度上下降了(甚至 Vscode 无法正常处理 svg 之后的代码内容)。
开源流程
就像大多数开源项目一样,开往是基于 Github 开展的。鉴于本文的读者也许并非技术出身,我们将从 Git 开始,简要地进行介绍。读者可以在这一节自行选读。
Git
Git 本质上是一个用来管理“文件夹内部”的程序。对于电脑上的一个文件夹,通过 Git 可以记录其中的几乎所有变化,并统一的进行管理。为了便于初识这一概念的读者理解,下面会用一个编辑部的例子来说明:
想象你是编辑部的一个编辑,现在正在为下一期刊物撰写文章。你的桌面,我们称之为「工作区」,你可以在上面处理文件、书写、修改,它们不会收到任何干扰。但此时,如果你把文件放到桌子下的小抽屉里,我们就说将它放进了「暂存区」,在暂存区里,我们就默认不再对文件进行更多修改了,这就成为你要交的稿件的一个「版本」。
当你的觉得时机成熟时,你可以把文件从暂存区里拿出来,交到刊物的总编辑那里,我们成这个过程为「commit」,这时,你的稿件基本上就不能再修改了(就一般论而言,在 Git 中其实仍然可以实现修改,就像你从总编那里拿回你的稿件)。如果你要再修改,那么你就要复印一份,修改完再交给总编,那么总编那里就有了两个版本——换言之,你过去 commit 的每一个版本,都被记录在总编那里了。
假设你所在的编辑部只是一个分部,而还有总部和其它的分部,我们就称把每个编辑部叫做一个「分支」,在不同的分支里,你们的改动互相之间不影响。而总部这个分支被标记为「main」,所有的分支最终会汇总起来,由总部筛选,挑选更好的、解决各个版本之间的冲突(当然,在 Git 的观点中,没有绝对的总部,你随时可以把其他分支作为主分支)。
这基本就是 Git 的工作流程。在实际的项目里,我们之所以使用 Git,核心的需求就是版本管理。比如,假如两个人修改了同一份文件,过去要进行对比、控制是相当困难的。但在使用 Git 以后,由于你们提交的文件夹中都有 Git 文件,就自然地记录了你们所提交的所有版本,两份文件会被看成是同一个项目的两个分支,通过现代化的应用,可以很容易地审阅分之间的差异,进行合并和处理——这就像是把两个平行时空的编辑部放到一起,看成是同一家编辑部的两个分部,然后把两家的内容进行合并。
GitHub
GitHub 是一个网站,之所以如此称呼,就是由于它的运作逻辑是基于 Git 的。正如前文所说:一个大型项目可能需要许多人一起合作,并由组织者进行协调,那么 Git 就成为了最好的工具。而如果来到开源项目,就不仅仅是合作那么简单,这还涉及到大家互相之间使用什么平台、如何通信、谁来审阅和组织的问题,而 GitHub 就提供了这样一个空间,大家可以很方便的通过 Github 来通信:交流想法、修复 Bug、增改代码。
就以开往这个项目为例,当我有一个想法以后,我会先在官网上阅读文档,确定这个项目的要求。然后我会从官方的仓库,也就是 GitHub 页面中进行 Fork,把官方的文件夹复制一份到我自己的名下,这样,我就可以把代码通过 Git 拉取到本地,并对这个项目的内容进行修改。
在我将我的代码文件放入整个项目的文件夹以后,我再通过 Git 重新把项目推回 GitHub 上我的仓库里。接着,GitHub 就会提示我:你可以提交一个 Pull Request。
所谓 Pull Request,简单地说就是,告诉这个项目的发布者:你已经创造了一个新的平行宇宙,并完成了你的修改,请求他把两个平行宇宙的编辑部放到一起,进行审阅。此时,他的项目会被看成是总编辑部,你 Fork 出的仓库则会被看成是分部——当然,更好的策略是,你直接在修改项目时在你的仓库里创建 Git 分支,这就像是在你的平行世界开一家分部,这样在合并的时候,就更不容易造成混乱,它可以很容易地知道哪个世界的是总部、哪个是分部。
维护者接着会对你的项目进行审阅,并做出一些新的修改要求,比如在这个项目里,一开始是没有显示站点名称的功能的,维护者告知我该项目中有显示名称的接口,希望我可以调用后添加此功能,于是我再做了改动。当维护者认为这个项目大体上已经完成,不需要再做什么改动的时候,他就会把两个平行世界的刊物进行合并,使你的代码成为原有项目的一部分,并且发表新一期的刊物——这样,一个新的功能就上线了。
我们如何看待开源
也许你没有意识到,但我们所有人都正广泛的受益于开源,比如承载我们浏览的网页的大多数服务器、以及你的许多家用设备所依赖的的底层系统 Linux,就是由开源社区持续建设并维护的(恰恰它与 Git 是同一个开发者的产物)。而还有很多你用过的软件、网站,可能都广泛地使用着开源技术。可以说,整个现代科技都是基于开源社区建立起来的。它一方面为用户提供了一个非常开放的平台、提供了许多免费好用(甚至超过许多付费者)的产品,另一方面,也给开发者提供了一个自由的、同时又可以相当好地发挥个人能力的平台。
此时我会说,我们要感谢开源精神,但这是就一般论而言。但在我看来,开源的意义绝不仅仅是开放源码、自由下载,更重要的是:在开源社区内部,开发者和用户并不存在明确的区分,而庞大的公共协作可以充分地推动产品的发展。因此,更重要的是——我们如何把开源变成一种全新的生活方式——我们如何让用户和开发者交融起来,如何做出更开放的产品环境。
让我们举一个例子:今天的媒体尽管发展到自媒体当道的状态,但社区并没有真正产生协作,观众和博主相当程度地被割裂开。但假如,一个媒体可以使用上开源社区的模式呢?比如博主发布视频以后,观众不是在视频下方留言,而是去提出点子、创作脚本、甚至制作一些视频素材,通过 Pull Request 提交给创作者。这些通过博主整合起来、并通过专业技能优化,最终形成新的一期视频。
那么这样,我们就既没有去到原先由媒体独立把控内容的时代,也没有在自媒体时代中,在繁复的影音流中沉沦、在虚假信息中迷失。
如果更进一步的说,社会呢?国家呢?以至于我们所有的制度和与之相关的生活方式呢?波普尔给我们指明了开放社会这条道路,而开源,也许可以成为开放社会具体工作的全新形态。