https://zgq.ink/gq's blog2024-03-19T06:08:13.093Zhttps://github.com/jpmonette/feedzgq354me@zgq.inkhttps://zgq.inkA place to think and write.https://zgq.ink/favicon.pngAll rights reserved 2024, zgq354https://zgq.ink/posts/2023-summary2024-01-06T00:00:00.000Z
工作内容上,延续着在腾讯时的业务导向,算是比较深度地在 React 生态之间完成各种各样的 UI 和交互,相对复杂的表单逻辑,antd form 的各种小细节也踩过一轮。技术的版图上集中在 Web 与 React、RN 这块,写代码上,基本稳定在类似 React Hooks / Jotai 的思维模式,以及 CSS 与 Web API 等,在实现业务逻辑方面,基本没有什么特别障碍。
背后伴随着一些对工作的小迷茫,一点迷茫来自于偏理想主义的技术研究动力与现实的商业需求的冲突。对技术有兴趣的朋友,多少有些将个人的技术情怀寄托于工作的冲动,这在工作的层面也容易走偏。老板更在意的是你能为他解决的问题,工作能带来的影响和改变,带着一个回报方面的预期。在一个相对务实的环境,也促使我去思考一个自我角色定位的话题,写了 Research & Development Engineer,关于一名 R&D Engineer 在团队中究竟在产出什么样的价值,自己领的这份薪水又付在了哪里。
另一点迷茫在于,我过往的经验更侧重于 UI 细节的精细化还原,偏重逻辑的应用经验相对较少。年中逮着了一次做 C 端页面的机会,算是独立负责的一个最大的模块,上线后有许多来自客户和同事们的正反馈,还是挺开心的。也感谢 leader 的支持与引导,下半年的工作状态也比较专注,基本是在独立负责一些 B 侧模块的开发支撑,完整地经历了几轮从需求 Kick-off、方案设计、开发测试到上线运维的过程。某个 feature 在年底肝了俩月,基本把手上最复杂的模块完整撸过一遍,对于工作的信心也增强不少。
今年社区运营的一大重心,在于重修 0xFFFF Wiki 的 入门专题,我希望能把我酝酿已久的关于比较理想的大学学习状态,理想与现实的冲突解决思路等等,再做一次比较系统性的梳理,算是了却我在大学时的一份执念,也希望未来同路人们遗憾可以少一些。同时希望它可以作为社区基本世界观的基础,确立一些基本的原则,更具体的学习方法、资源等,可以基于此再持续延伸。
电影电视剧方面,今年比过往看得多一些,也有不少的感触和感动。受同事的影响,去了几次线下影院多点,年中时候B站重温了下《音乐之声》;在电影院看了理想主义向的《宇宙探索编辑部》,虽然我不太能 get 到男主的执着,我所期待的理想主义,更多是能落地的那种;中间看过主打唐诗三百首的《长安三万里》,还有漫威 / DC 视觉向的《闪电侠》、《碟中谍7》;年底搬家入了个大电视,在晚饭之余看了《无法成为野兽的我们》,还有《肖申克的救赎》。
日常听歌方面,循环的重心从许巍慢慢转向了 伍佰 & China Blue,除了他演唱会常唱的几首,《白鸽》还有《枫叶》我也挺经常循环,还有闽南语的《世界第一等》。越来越喜欢伍佰身上某种历经沧桑后的一点洒脱与浪漫,和我现在心境好像也有些共鸣,虽然我的年龄还不到 25 岁,但好像也经历了不少的无奈与成长。
吉他练习还在继续,相对较挑战的 F / Bm 和弦、以及常用和弦的转换目前初步熟练,可以刷一些简单的和弦走向了。进一步大概得关注一番乐理相关的知识,不过意识到自己的精力有限,且这里不是我主攻投入的领域,所以就先佛系推进吧。
骑车通勤时会听听播客,偏向于技术和商业、投资理财等方面。不知不觉把《内核恐慌》多年的老节目都听过了一轮,听 Rio 和 吴涛 唠嗑各种计算机的各种技术细节等等,带来很多有趣的脑洞发散,一些属于技术宅世界的陪伴感觉;其中顺藤摸瓜听了蛮多期 Rio 的《疯投圈》,聊到消费与品牌营销相关的话题,解锁了一些新的视角。偶尔听听孟岩整的《知行小酒馆》、《无人知晓》,蛮喜欢 E10 让万物穿过自己 聊到的,每个人都有着各自不同的认知与情感的“房子”;在某种抽离的视角去观察人类、反思自己应该是什么样的生活状态,也是一件挺有意思的事情。
DNS 方面我选择 DNSPod,考虑点在于它有中国大陆内的解析节点,并且在专业版可以支持全球服务器的解析,价格还可接受。最关键是它提供了精细化地在不同的地域去做分流解析的能力,这对于部署在海外的站点是非常有利的,可以针对大陆用户去专门部署优化的线路,相比于 Cloudflare、ClouDNS 等会更加灵活。
当前我是用 Vercel 多一些,本博客和 0xFFFF Wiki 都放在这上面,主打一个简单直接方便,push 代码直接就能自动触发构建和部署,非常省心。
静态资源、CDN
浏览器下载 HTML 后,通常需要加载脚本、样式、图片等资源,这会带来一个额外的流量消耗。接入层网关本身的带宽成本相对要贵一些,且访问速度方面不太可控,通常会单独对 HTML 外的资源,去根据访问情况做分布式的缓存。这也是 CDN 的一大作用,CDN 以大带宽低成本的优势,分摊源站点的流量,提升用户的访问体验。
Web 领域已发展得十分庞杂,就知识规模来说已不是你我一个人可以穷尽。从 Web 前后端开发角度来看,前端当下正流行着 Next.js、Remix 等 SSR 方案、以及 React 后续继续开发的 Server Component 等等;后端方面则搞出了“云原生”相关的一整套技术生态,各路轮子百花齐放,一不留神就容易沉迷其中而难以自拔。
Web 诞生于 1991 年,在形态上,它最初被设计为一系列的 HTML 文档组成的资料库,在一个 HTML 文档中通过 URL 来描述与其他 HTML 文档的链接,再进一步产生了「网页」和「网站」的概念,一堆 HTML 文件和对应的图片等资源放在服务器某个文件夹里,在启动一个 Web 服务端程序,指向这个文件夹,一个网站就这么架起来了。
这也为开发者们开启了新的想象空间,开始尝试用程序去生成 HTML 网页,诞生了服务端处理 HTTP 请求的 CGI 标准,并且逐渐有了 Web App 的概念。为更好实现注册、登录等与后端交互的能力,大概从 1994 年开始(参考:HTTP cookie),Netscape 浏览器实现了 cookie 功能,支持在用户的浏览器与服务器的通信的 Header 带上一段特殊的字符串,从而让服务端可以以此比较方便地维护与客户端的状态,而不用将状态反复回传。
也是在这个时期,各类以 HTML 为“渲染层”的方案在逐步涌现,如 1994 年起步的 PHP,96年的 Java Servlet 及后来的 JSP,2002 年的 ASP.NET 等等,各个方案针对 Web App 这样的场景,设计了“MVC架构”,数据对应 Model 层,HTML 模版作为 View 层,用户的操作处理逻辑则是由 Controller 来承载。
在这个时期,Web App 的交互模式,基本上是“用户点击某个链接”、“服务器处理请求”、“生成新的 HTML 页面传回浏览器展示“、”用户在新的页面做点击操作“的循环。显然来回传输页面较为繁琐且会带来较大的流量消耗,但这也为后面更丰富的 Web App 形式打下了一个基础。
这样的一个首页 load 一段 js 问题,在上述说到的涉及到用户体验和 SEO 的场景,显然不是太能被接受,因此 Web 前端圈子也有了一个 “服务端渲染直出页面” 的概念(也叫 Service-Side Rendering,简称 SSR),通过服务器端预先加载好需要的数据,事先输出一部分 HTML,让用户更快看到界面,减少一些等待过程中的烦躁,让这个加载过程看起来更顺畅和丝滑;在 SEO 方面这份 HTML 也针对搜索引擎去做索引,并服务于 Web 站点的互相链接。
这里的 SSR 其实也和当年 PHP / JSP / ASP 等后端语言在做的事类似,只是说在编程语言层面都统一为了 JavaScript。与换一门后端语言写模版不同,这里的服务端渲染,更多是在复用了浏览器端 JS 渲染的组件代码逻辑,实现客户端与服务器端“代码同构”。
至此我们可以发现,此时的 Web 技术,无论是「文档」的视角还是「应用」的视角,在编程语言生态上,正在向最初的 HTML、CSS 和 JavaScript 这”三剑客“收拢,以及周边的各种语言和工具;在平台方面,这三剑客覆盖了浏览器之上的 GUI 交互、以及面向搜索引擎的 HTML 生成方面。
此时我们若将其视作一个共同体,就相当于某个业务系统的一部分,类似一个负责对接浏览器与搜索引擎的 “Web Service”,我们系统内的其他部分,可以约定好 API 与之相互通信。关于这一共同体的实现,我们可以将其收拢到 JavaScript 这一门编程语言,并通过 HTML / CSS 来渲染 UI,再利用浏览器的 fetch API 等 Ajax 能力以及 Node.js / Deno 等 JS 运行时,去对接其他模块的 API。
这样的共同体概念,业界将其称为 Jamstack,Jamstack 最早还叫 JAMstack,代表着 JavaScript / API / Markup 三者的结合,后来社群讨论影响下,开始改名为 Jamstack,意图让开发者把重心放在 JavaScript,以及 JavaScript 生成的 Markup(即 HTML),以及将 Web Page / App 的实现与其他系统解耦合,通过 API 去通信。
有了 Jamstack 这一概念对共同体的定义,也可以让开发者的关注点更加集中,把精力都聚焦于以 JavaScript 为中心的网站构建方案,也如前文提到的,通过一套代码去对接用户与搜索引擎,无论是内容类网页还是 Web App 都能轻松承载。
首先我们需要摸清一整个体系的工作流程。关于 Flarum 的内容渲染逻辑,核心采用了一个类库 s9e/TextFormatter,相比于传统论坛程序的内容渲染而言,它思路相对要特别一些,类似编译器的模式,它把用户输入的内容当作“代码”,解析成一棵“语法树”。帖子数据的存储和处理过程,也是以“语法树”为核心,通过 XML 的形式来表达。
参考 s9e/TextFormatter 的 文档,这里涉及到三种形态的文本(Original text / XML / HTML),对应有三个转化过程(Parsing / Unparsing / Rendering)需要维护,它们的关系如下图所示:
其中 Parsing 过程承担将原文解析为 XML 的角色,类似“编译器前端”,可以对接 Markdown / BBCode 乃至于各种复杂的特殊语法;Unparsing 过程则是负责将解析后 XML 还原回原文。
在作为中间态的 XML 的结构上,每一类内容都有它的一个单独的 Tag,对应内容的基本的元素(图片、视频、链接、各种排版格式等等等等)。类库针对标签的场景,为我们封装了一些工具方法,可以根据需要去改动已有的 Tag,或是定义新的 Tag,也可以对这些 Tag 做一些自定义,考虑安全因素,做一些特殊的规则限定等等。
对于 Rendering 过程,Tag 内部有个 Template 的 概念,Template 基于 XSLT 语言编写,类似一个“样式表”的角色,定义最终的 HTML 应该渲染成什么样子。类库的 Renderer 将每一个 Tag 需要用到的 XSLT 的 template 代码汇总一起,交给 XLST Processor 处理。内容 XML 借助 XSLT 样式表转换,得到最终我们需要的 HTML 结果。