Shiina's Blog

所有文章

共 50 篇

在AI时代洪流下的我们该何去何从-我的2025年终日记

写在前面 写这篇文章的原因是今天在搓毕设,其中有一个绘制流程图的环境要自己造轮子: 你可以发现从左往右数第二层中的后两个节点,跨过了第三层,直接连接到了第四层的结束节点。 这两天时间我一直在思考如何设计一个算法,使得所有类似这种跨层节点连线可以进行自动连接,同时又尽可能地保证好看和避免线条冗余。 我的基本思路是在被跨越的层内放置一个虚拟节点,这样跨层连线的问题就退化为了层之间连线的问题。 在此之前我一直不相信 AI 能够做好这件事,所以整个算法理论都是我一人从头思考并设计出来的(代码大部分由 AI 翻译我的思路实现,我负责逻辑审查和细节修改)。今天我打算将这个算法结束收尾,于是在进行了大量的构思后完成了理论流程的构建,下一步就是要将这个流程翻译为代码实现。翻译这个流程到一半时我实在是没有经历去思考和对流程进行抽象了,于是我唤起 cursor agent,用简短的一句话描述了我的问题: 这里的 todo 是这样一句话: 我在这里并没有给出过多的提示,没有说明我的图用的是哪个变量,文字前后也并没有特别完整的逻辑( 所有节点指的是那些虚拟节点吗,连接指的是只连接虚拟节点还是附带上起终点,不同的连接方式有什么不一样的逻辑) 但 AI 花了2分钟将这段文字背后对应的实现一口气翻译完了,而且还补充了新的逻辑(移除跨层节点关联关系,虽然对于我的思路来说这一步可能没有必要)。并且能够跑起来,效果很好,反倒是我自己写的一些逻辑(线条应该被放置在同层节点的上方还是下方)有很多细节与小问题,还得慢慢改。但是我看到效果后有种说不出来的感觉,我很难描述这一刻的感受,是迷茫?亦或者是怅然若失?又或者说是放弃追求目标后所拥有的释然感? 简单思考过后我得出的结论是: 因为我终于把这个硬骨头啃的差不多了从而可以让我开始快速推进各种毫无技术力的地方而感到松了一口气 说笑了,说回正题。AI 给我带来的惊讶感还是很强烈的,我不得不从此刻开始正视 AI 的积极作用。为了梳理好我对 AI 的看法,于是便有了这一篇文章,同时现在也刚好是 26 年年初,我也可以趁这个机会对我的整个 25 年做出一个系统性的总结。 三年内我该如何与 AI 和谐共处,而不是采用敌对和焦虑的眼光看待 注意,以下论点均为个人主观意见,本人资历学识尚浅,对各种学术上的认知未能有较好的理解,敬请见谅。 AI 能快速把我的意思快速弄明白并将其转为代码,这让我意识到 AI 目前对我最大的积极作用就是成为我的 思想翻译器 ,他可以精准的把我的思想翻译成代码实现,而无需关系各种细节和抽象问题,从而提高我的编程效率,这也是我目前所想到的解决方式。 早期的我为什么会抗拒 AI 在此之前我一直很抗拒 AI, 我想应该是我不喜欢那种自己的思考被他人轻松地就想清楚的感觉,即 “你的思考与所谓智慧在我眼里毫无价值,我随手一想就能想清楚你这辈子都想不明白的问题” (现在看来应该是:我的人生价值是通过 + 来实现,但这个过程现在因为被 AI 替代了,从而感到不甘心,因为自己实现价值的过程像是变得没那么有意义了)。虽然我现在依然认为 AI 在某些方面无法战胜人类,或者他依然没法被称为 ,但其生产力与部分问题的解决能力已经可以成为你提高生产力的工具了。 我抗拒的原因是 AI 无法以真正理解的眼光,看待一个问题,并基于理解透彻的知识,为一个问题找到一个解决方案,方案的每个细节都经过严密的证明和推敲,并有合适且客观的理由来告诉你为什么这么做。他只是通过概率计算,以及大量的资料学习,并通过选择最正确的下一个词汇来拼凑出一个你所希望看到的结果。 如果 AI 哪一天真的能够做到理解某一个客观事物的存在,并给他给予合理的解释以及运用它去解决一些问题,这个时候我认为他就真的可以被称为 了,即具备客观事物的结构化认知能力与因果律推导能力。 我在此举一个小例子用来辅助理解上述原因: 为什么早期 AI 做基本的加减乘除数学题时,AI 总是没法做对? 以及顺便解释为什么现有人工智能无法被称为 的原因。此处给出一个个人主观答案(如有意见或疑问欢迎理性友好探讨): AI 本质上并不理解 这个过程,他只是通过大量的训练资料来作为推导论据,并尝试从这些资料里找到一个与你给出的算式最接近的一个答案,然后返还给你 在这一过程中,并不存在 这一真正的思考,这里以1+1举例子: 定义 ,他被用来描述某一样抽象或具体事物的数量 定义数字 0 9,他代表对任何一个抽象或具体事物的数量描述 定义加法 +,他代表将两个数字背后代表的事物摆在一起,摆在一起后他们可以得到一个新数字,这个数字也被上一条定义得到过 从此我们创造了 ,即 AI 并不是真的理解数字是如何定义的,以及他背后所代表的含义,加法这一算符和定义也不理解。他只能从大量的训练资料找出所有类似于 的类似文字,并找出 后面最大概率的数字是什么。同理,对于世界上各种事物的定义和因果律的推导,也依然不是以学习与认知的眼光来看待。 虽然我不知道未来的 AI 是否能够打破这一隔阂,并做到真正的 理解 与思考某一事物。但我觉得3年内也许还没有这个可能性。 写到这里时,我开始思考一个点:我们真的能造得出具备与我们相同思考能力的人工智能吗?现有人工智能到底是怎么去模仿人类进行“思考”的,到这里时我的脑子突然出现了一个词: ,虽然我并不理解为什么会出现,以及他是什么,但我还是搜了一下,并找了一些参考视频来看看: 在看完以上视频并且理解其表述内容后,下文的内容你可能才有办法理解我到底在说啥(笑)。 光看这个参考视频我就觉得最厉害的地方如下: 能对一个token(对于一段话来说就是一个词)采用向量进行表示,并能够通过一个 attention 模块,让每个 token 能够基于这一段话的 token 来更新自己的向量值,使得每个 token 能够明确自己在这一句话中所包含的意思,而不是存在可能的多重意思(Attention 过程直接强化了一个词在一句话中的语义,能够帮助大模型去判断这个词的真实意思是什么) 比如 和 中 一词,通过以上流程,可以使得这一词的向量值在 n 维空间所处的位置更贴近他们所属的意思(第一句话的 会指向 这一区间,而第二句话会更偏向 这种代指人的区间),就像人通过上下文来判断这个词指代的是什么东西 通过对词的高维度抽象化表示,我们可以意外的通过这种方法寻找一个词相对另一个词的类比关系模式。这个过程虽然不像是人类思考的过程,但是结果似乎意外的好? Attention 部分的 Query 和 Key 部分是一个非常神秘的地方,他能通过数学向量来表示人类沟通时的每个词的语义,且这些向量通过一系列的运算能算出哪些词之间相关性更大,哪些则更小甚至。从而得到 tokens 中的哪一些 token 能有助于强化当前 token 的语义,随后再对选中的形容词的 token 乘一个 V 矩阵,得到加权向量,并把其加到当前 token 的向量值去,使得这个词的向量所在的高维度空间位置更偏向于这句话所期望的这个词的意思。 比如 A fluffy blue creature 这句话。这句话通过 Attention 模块计算时,能够得出 fluffy 和 blue 对于 creature 的影响是最大的,然后 Attention 模块会计算这两个词的权重,并且通过 V 矩阵得到一个加权向量,最后再加上当前 token 的向量,使得这个向量在 n 维度的方向上能够指向 这一含义(transformer,很神奇吧)。这一过程被称为单头注意力机制 而多头注意力机制下则有多个单头模块,每个模块都可以计算出一个加权向量,最后把多个单头模块的加权向量加到一起,再加上当前 token 的向量,同样能使得这个 token 在 n 维度所指向得方向更贴近于其原本的含义(相比单头能学到更多改变上下文语义得方式,而不是只有一个 Q K V 来计算,个人认为这种方式可以更加方便地去微调某一个词在某一个领域下改变的权重,相比单头可控性更强) MLP 也是一个很精彩的思想,它用于通过提问 + 事实向量加权,来实现一个词的在 n 维空间的语义调转,他对每一个 token 做出一个提问,如果 token 符合提问提出的内容或相对来说存在一定相关性,则这个提问对应的值会被标记为“是”,然后再用一些事物与这一个提问结果做出关联计算,如果存在关联性,则将这一事物对应的向量值写入这个 token,使得这个 token 附带上这一事物作为他的信息。从而通过事实影响一个 token 所包含的信息以及语义。 想象一个 作为一个 token 输入进 MLP 模块,这个模块首先提问:这个词是 吗,答案是 “是”,则这一提问被标记为回答成功,并进入下一个关联环节,这个环节包含很多事物,并且他们会基于上一个环节做出的提问,将一些事物对应的向量值添加到 token 内。比如打篮球,生于 1963 年,编号为 23 。以上过程只是简单例子,在大模型里其实不存在一个这种特定的特征用来表明这个词是某个指定的东西,更多是一个“类似这方面的特征”的形态去描述提问向量与输入 token 的相关性,然后再根据提问向量带来的值比重来确定要往向量里塞什么信息,以及这些信息的比重。 Transformer 工作流程如下(尽可能地通俗易懂版本): 每一个词都采用一个向量来做表示,这个向量包含 512 个数字,语义越相近的词他们的向量值差距更小 通过一个叫 attention 的过程,可以使得大模型根据输入的这句话不断地更新每个词地向量值,使得每个词更贴合一句话中这个词所代表的含义的向量维度区间,在这个区间内大部分词的含义都与该词含义相近,且此时这个词+该区间内周围的词的意思更加贴近这一句话从人类视角来看时所理解的意思(核心) 这里比较抽象,用视频例子来说就是给出一个词 ,在 n 维向量空间中,处于这个区间内的词还有 (建筑) (摩天大楼) (屋顶) (穹顶) 如果我在这个词前面加了一个 ,那么此时值可能就更加靠近 和 ,而更远离 (屋顶) (穹顶)这俩专门用于表示一个建筑顶部的词。Attention 就是这样一个过程,通过这种机制使得一个词的高维度向量所在位置更贴近于这句话所想让这个词包含的含义 完成向量值更新后,进入 Multilayer preceptron 过程,这个过程就像是对每个词提出一系列问题,然后根据问题的反馈再次调整每个向量的值 重复2,3步骤,直到最后能通过某种方法,结合前面所有的词的向量值,从词库里挑出一个出现概率最大的词,此时就完成了第一个词的生成 将加入了新词的这句话重新输入该模型,重复上面的所有步骤,就得到了生成式的大模型 其次是多模态,基于以上架构,我们可以把任何东西都想象成一句话,或者应该叫做一串 tokens,然后输入这个模型,通过以上机制,得到一串新的 tokens,然后我们就可以把这个 tokens 转为我们任何想要的东西,多模态就这样诞生了(暴论)。 以及我也为什么明白了那篇论文的标题叫做《Attention is all you need》,这个调整向量的过程,就像是人在阅读一篇文章时他们会根据上下文不断地去强化理解某一个单词的意思,从而更好地帮助自己理解这一句话,一段文字所想表达的含义。以及为什么上下文会有长度限制的原因,同理,人脑也不可能直接把一段文字给完全的输入脑子,再彻底理解文字后输出自己想要说的内容。只不过人类似乎还多出记忆 & 总结这一过程,使得人类可以以更高效的方式处理更长的上下文。不过关于这些的实现,似乎基于这套 Attention 架构都能搞定?真是太可怕了。但是,这也能验证目前 transformer 这一架构的实现并不是让 AI 真正具备 “思考” 能力,他只是不断模仿人类说话,让输出的内容“看”起来像是这个意思,深究起来可能不存在任何逻辑贯通性。 用 Transformer 的思考模式来对 做模拟运算! 我们在这里的目标是构建一个属于我们自己的 transformer,使得他可以通过这种模式简单的预测一个四则运算等式后面可能的值是什么,因为它不存在真正的计算这一过程,而是预测答案的可能性,所以不一定总是能够保持正确的计算。真的要自己实现一个 transformer 还是得去详细阅读具体论文并理解思想,然后才是思考理论过程,具体实现代码等有心了再贴出来。 目前的目标是四则运算 + 括号优先级改变运算规则的识别。饼先画在这里了,实现的话看什么时候有心和觉得好玩了就去研读论文搞清楚是怎么个说法。 总结 AI 时代下程序员的职责可能会发生翻天覆地的变化,编码能力可能不再那么重要了,因为这部分 AI 做的可以比人类还好;但是 设计能力,逻辑思维,因果律推导的思考能力 则显得更加可贵。因为 AI 无法去真正的做到 思考和创造 一个东西出来,他只是不断地通过概率预测,去生成下一个可能出现的 token,并让这一串连续的 token 看起来像是创造了一个东西,又或者是像是解释了你的困惑,但是否真的具备逻辑性就不得而知了。此时你该做的就是解放编码时间,让更多的时间投入在思考和设计上,这也更考验你的学科基础水平与知识功底,否则你的设计有一步错了,AI 就会在此基础上开始滚雪球,会错的越来越深,带来的技术债也会越来越重。 软技能,沟通技巧也显得更加重要,因为这直接关系到你能否清晰的告知 AI 自己的目的,让 AI 成为你的助手( 克里斯缇娜 ),高效的沟通技巧能让 AI 更好的把握你想传达的主旨,从而找出更正确的 token 去填充对你疑问的答复。如果没有一个合理的边界把控感,又或者是没有告诉 AI 足够的背景,这就不得不逼迫他自己进行各种 “幻想” 来填补缺失的条件,合理的告知信息可以增强对目的内容的注意力导向,从而让结果更符合自己的想法。 软件开发的各种理念依然不过时,且显得更为重要,AI 不能在一个对话里干多件事情的原因是存在上下文限制,以及记忆清空这一过程,AI所有的记忆都来源于上下文窗口。因此如何让 AI 精准完成任务就显得更为重要,在软件开发中有一些很重要的概念就是 (拆分复杂系统) (避免一个程序做多件事情从而导致的复杂性提升) (将单一职责模块组合起来,构建回复杂系统) 一个非常好的例子就是操作系统的各种内置程序,为什么基于操作系统提供的程序搭建起来的工作流总是能完美的运行而不经常出错,本质上就是一个程序只做一件事,且规定好了自己的输入输出,而不受外界的影响。AI 领域下我们能复用的思想就是一个 Agent 只做一件事情,精准完成后规定好其对应的输入输出,最后再将他们串成一个完整的工作流。从而得到一个完整的功能程序。 推荐阅读的文章 $1 聊聊这一年我到底在做什么 如果要浓缩成一句话,那非常简单:实习,面试,实习,转正,然后开始追求自己热爱的事情。但这里的每一件事情展开说都可以说很久很久,不过既然是年终总结,那就还是好好详细的说一说吧 我面试实习时所用的项目 主要有两个: 一套基于 Astro 的无代码生成 Minecraft Mod 百科网站框架。https://gitee.com/shiinafan/dmv wiki toolkit 插件化核心,支持多模板复用 支持自定义主题,重写页面组件 支持任意自定义页面重写与主题复用 包含一套基础的 VSCode 插件,为 MDX 提供智能提示与检查 包含一套后台管理系统,支持多人协同编辑词条,历史内容查看,撤消重做,回滚等操作 塞壬唱片桌面版封装实现 https://github.com/QingXia Ela/MonsterSirenDesktop 对网页原有内容进行改造,注入了管理代码,使得三方 APP 能够内嵌进网页,并对页面内容数据进行劫持改造 支持 DLL 插件,可以通过插件系统注入三方平台音乐 设计思想为 Core + Plugin 驱动,部分内置功能(本地音乐 + 塞壬唱片原音乐)均为插件注入实现 两个项目都很大很复杂,尤其是第一个,因为这个项目我跟进了2年半了,经历过大重构,经历过分包架构设计,也经历过技术深入探讨。不过要展开讲就是另外一个话题了,这里有机会找时间再详细展开,塞壬唱片桌面版项目可以参考这篇文章:$1。由于我在这些项目里沉溺的个人时间过多,这也导致我后续面试遇到的一些计算机基础的坑没法解决,具体情况就请阅读下文吧。 2024 年年末的焦虑驱动 为什么要提到2年前?因为我觉得2025年的一整年的事情都是从2024的面试开始,粗略统计下来也大概有十几场吧,现在回头看来当时的我就像是一个拼命背题,为了押中面试官想问我的问题拼命的给自己的项目去找各种乱七八糟的细节并进行记忆,就像是一个小镇做题家一样。但我不会怪我自己,因为这取决于家庭教育的认知方式,而完成这个转变也是一个我的必经之路,在这条路走到头破血流时也许才能幡然醒悟,是不是自己的方法错了? 我大概是从 2024 年的 11 月底开始投简历,当时投递的第一家企业就是腾讯,我还很好奇腾讯为什么要出一个如此抽象的综合测评题目。后面隔了几天就来了人生的第一场面试,来自 团队,同团队还调侃说一上来就面微信,有勇气,我一开始并不理解这句话,但我未来马上就理解了。当时面试官还特别好,提前加了我微信,大概聊了一下面试可能要准备的东西。我还记得当时准备开始面试的前一天我就进会议把简历上传了,开始前20分钟就进入会议。我很庆幸我第一场面试遇到的面试官非常尊重我的想法,并且努力倾听和理解我做的事情,还认真的看完了我整个项目的演示。以及最后告诉我你面试表现的非常好,极大的增强了我的自信心。后来就是二面了,二面前一面面试官还提醒我修改简历,讲清楚自己做的事情,在开始面试前的一晚,我把自己关在实验室的小会议室里反复记忆着我每个项目的各种要点难点,就是为了一口气能讲清楚我的所思所想,但现实给了我一巴掌,面试官这一次着重提问了我的基础,从数据结构到操作系统LRU置换算法,再到 tcp udp 各个细节,以及最后http请求头host泄露避免方案,这些地方彻底的暴露了我的基础是如此薄弱 + 常年躬耕于静态网站生成与构建方案所带来的面试劣势。当时面完后我记得我在小会议室哭了十几分钟,可能是恨自己忽略了作为计算机学生最基本的基础学习,也可能是恨自己不懂这些,能力不足,但这些都是后话了。但后来隔了几天三面的通知来了,当时我看到邮件时人都蒙了,明明二面那么差为什么还放我过了,但我当时对自己已经失去了大部分自信,所以这一次面试也是有些摆烂,打算随便讲讲,果然一开始节奏很差,面了半小时面试官就不耐烦了,话里话外透露着“怎么推了个自己做的东西都讲不清楚的人上来”。但还好最后反问时,面试官问了一句“你学到了什么”,我仿佛是找到了一个机会,把我做的东西,细节上的思考,以及对实现的评价清晰的讲了出来,而且在讲这些东西的时候是发自内心的感到自豪与自信,面试官认真听完后留下一句“好好总结做了啥,并清晰的讲清楚”后结束了面试。虽然后续隔了几天收到了流程结束的邮件,但我又恢复了一些自信,因为我终于在失败中摸索到了一些面试的技巧。 与上面这一段微信游戏同期的面试是 ,这一段我觉得没啥好讲的,可能就是二面三面是发生在微信游戏三面结束后,我仿佛获得了一个 buff 和觉悟,二面和三面都是我一个人在疯狂口喷我做的事情,并且讲的非常详细。这里必须提的一点是其实这两面的面试都比较低效,因为我只顾着自己讲故事,而没有把我特别多的精华和细节讲明白,所以节奏并不是特别的紧凑和舒服,但是按照面试评分标准我至少在及格以上,且三面的面试官提到我个人相比于其他同学更有个性,所以优势会更大?接下来按照旮旯给木里的 he 路线,我应该是通过 hr 面后收到背调信息,并在邮箱接受实习 offer 邮件。但非常可惜的是,一周后hr反馈说审批给我挂掉了,然后问了二面的 leader,他说他们也没招到人,非常奇怪。。。但总之就是结束了,我的朋友把这解释为被清北老哥挤掉名额。当时我在实验室得知这个消息时冷汗直冒,有大概十几分钟都觉得整个世界有点恍惚,仿佛这一切都是梦,但恢复过来后我只能告诉自己时间不等人,必须得继续前进,残酷的社会不会给你喘气的时间,要么前进,要么被淘汰。这里还有个小插曲:本来在三面之前有个美团 hr 打电话给我约面,但是三面过了后秒约 hr 面让我一度以为自己稳了,于是便推掉了这场面试,结果等审批挂时,我回头去找 hr 在 boss 上的岗位,结果岗位已经下架了哈哈。 然后就是 12 月初到 12 月底前一周,在此期间有一家外企 给我打电话约面 + 2面技术面,让我觉得很有意思的一点是 hr 似乎也在尝试理解前端各种东西,问了我 20 分钟前端技术,然后给我约面,同期的还有 1面没消息, 1面问了一堆基础 + 做了5题后秒过。这里没什么好讲的,要讲的主要是接下来 团队,这次面试可以说是我有史以来面过难度最高的面试,没有之一。 我记得当时是15号,手机有个电话打来,上面写着腾讯广州研发中心B4咖啡厅,说是捞到我简历了问我愿不愿意面,我说给我一天思考一下吧,然后跟同学讨论了一下,同学觉得有可能是 kpi,毕竟年末了很少有团队说要招人,但我当时想着说就算是 kpi 也要努力的去锻炼和提升自己。我当时并不清楚广州腾讯研发中心意味着啥,因为那里算是微信总部。然后就是面试,面试是晚上7点开始,面试官上来丢了4道题让我自己下去做,我还跟群友调侃说怎么一上来就做题的,从来没见过这种操作,具体的事情见这篇文章吧:$1。但总之接近两个半小时的拷打给了我极大的心灵震撼,但更多是满足与一定的成就感,后续就是提前回家继续准备面试。这里就再提一下二面的一些地方吧,我现在回忆起来感觉就是我和面试官电波可能对不太上,我讲我的,他问他的,一直到最后讨论到浏览器架构时才拼了命的往深处问我,把我的极限逼了出来。那一次面试我觉得我表现并不算好,面试官评价我基础比较差,做的东西不够深入,以及沟通不好,当时已经准备放弃再去看下家了,没想到晚上发了三面的邮件,是电话邀约面试,后面的剧情就是 he 了,成功通过技术 + hr 面并获得 offer。这里有个小插曲是,rightcapital的面试我也面完了,而且发 offer 的日子和腾讯是一样的,不过腾讯的相对早了3分钟,所以我给 rightcapital 点了拒绝,过了一会 hr 就打电话问为啥拒了,声音里似乎有点点委屈(?),这让我有点慌,但我也不想吊着或为难对方,于是就把情况讲完了。我一直觉得二面能通过是比较幸运的,我不清楚二面的面评怎么样,我的同事也因为我在职期间看不到面评,所以没办法剧透(误),但我现在看来我觉得面试官可能是看中了我面对很多东西有各种乱七八糟的想法,而且做的各种玩意相对来说比较亮眼,能让人感觉这不是千篇一律的项目。但具体原因依然不得而知,不过随他去吧,都已经是过去式了(笑)。 总之,到了25年年初,以腾子的一个微信 offer 作为开门红,我开启了新的一年的生活。这一年有玉玉,也有激情和欢乐,有对未来的憧憬,也有对现状的迷茫,如果要用一个颜色来形容这一年的生活,我会描述为 。 焦虑的上半年(2025.01 2025.06) 拿到微信 offer 的时候同校的同学,还有平时聊的很熟的网友都发消息前来祝贺我,有人说我是学校有史以来来第一位加入微信的同学,有人说着第一段实习就是微信,已经乱杀了,也有人对微信小程序这个岗位比较忌惮,原因大家也清楚。但这些都是小问题。这里我要讲的是我的个人心态,我在收到 offer 的时候有一瞬间是欣喜若狂,但随之而来的更多则是 感涌上心头,因为在此之前受到学校 + 招聘网站各种帖子氛围的影响,这里简单举几个例子:我经常能刷到一些实习做的东西没有含金量,要怎么包装的帖子,以及如何偷组里的各种产出;其次是我所在的学校,曾受一位同学的影响,说实习的时候需要多去偷组里的技术,并且把它变为自己的,这样找工作或者下一段实习的时候才能有故事讲(这个影响了我接近一年,现在回想起来虽然说也是人生的必经之路,只有跌倒过了才知道这是不对的,但依然隐约觉得有些难受)以及学长和同届同学还有实验室的学弟学妹,我仿佛套上了“高技术力大厂人设”这一光环,像是被推上了榜样的位置,为了起到带头作用,我不得不让自己保持前进(后来证明其实这都是我在给自己施压,学弟学妹根本不会因为我转正失败什么的就改变对我的看法)。基于以上氛围我认为我在 实习期间必须做出某一些特别有含金量,有说法,以及能从深度上比过我自己个人项目的东西 ,而且是在工作之余与短时间内要做出来,以及对社会规则的无所适从的 ,因为这对于我来说是第一次踏入这个叫 “社会” 的世界,我的脑中还没有能适应这个社会的一套思想与法则,只能花费时间与意识成本去不断适应。基于以上情况,一股强烈的 不自信感 + 焦虑 涌上了我的心头。这种感觉一直萦绕着我,以至于一月在外旅游时我还依然被这种焦虑的感觉所困扰,而这种感觉一直到4月底才有所改变。我还记得当时一面面试官说主要技术栈会有 rust,我还在1月那段时间特地重新看了一下 rust async 的相关内容。以及重新看了一下 xv6 的部分实现。但这些其实都毫无意义,只不过是缓解自己强烈的焦虑与不安感的一个小手段罢了。 旅游 一月的时候家里报了旅游团,去新加坡 + 马来玩了五天,风景还是挺不错的,就是新加坡消费太高了,这里放几张当时的照片 樟宜瀑布 滨海湾花园,环境很不错 黑风洞,据说这是印度人前来参拜的指定地点,路上也能看到很多印度人前来参拜 马来西亚王子居住的地方 上图远方那片海听导游说就是马六甲海峡,高中地理的时候还觉得海峡太小了,现在看来也不小啊 说实话很多游玩的地方并没有给我很多深刻的印象,毕竟是跟团穷游,算是走马观花,没有深入的看看哪些感兴趣的地方,硬要说的话就是飞机餐很好吃很有特色,机场瀑布看起来没有想象的高,但是拍出来却总是显得很高,还有马来到处都是清真寺。以及团友也是一道靓丽的风景线。 实习前的租房插曲(2025.01 2025.02) 然后就是实习前的准备,这里有一个客观条件前提就是,我让我的父母来挑选我在广州租住的房子,这是我今年犯下最大的错误之一,但我依然认为这是必经之路,只不过代价有点太大了。由于这是我第一段实习,他们自然也很重视,但重视所产出的成果却让我吃了四个月的苦头。在旅游开始前(差不多就是开始实习前的一个月)他们就马不停蹄的催促着我看看广州的房子,然后列个清单,我列完后他们就开始挑,说这个房子不行,那个房子看着是骗人的,同时也不忘数落我说怎么这都不会看,短时间内摧残了一下我的精力,我虽然有怨气,但我认为毕竟是第一次进入社会,如果让迷茫的自己来进行选择估计无意识之间就被坑了,所以忍一忍,了解清楚要怎么辨别也没坏处。 后续挑了4个房子,第二天就起身前往广州去实地看看。走完三个房子后他们对每个房子都挑了一大堆缺点,看完后也差不多到中午了,大伙也不想走,于是决定去吃饭,吃完饭后路过一个房地产公司时,他们突然看到了一个 块一个月的房子,一瞬间他们就变得欣喜若狂,甚至非常的激动,不由分说地拉着我进了房地产公司。后续我们去实地看房,房子很小,不到10平,没有阳光直射,窗户一打开就是下水道,味道很难闻,所以常年都是紧闭着。但他们仿佛就是着了迷的说中大奖了,找了个这么好的房子,说实话这个生活空间完全比不上之前所看的所有房子,其他房子至少不压抑,有阳光,而且有个办公桌子。这里只有一张床,而且很长时间都没人住了。不多废话,直接上图。 我本想拒绝,但是一想到我要是拒绝了他们就又要发超大的脾气,搞得整个氛围很压抑,我不希望我弟受到这般影响,因为我知道我现在站在了如此般的位置,那么我弟就要像以前他们压力我一般去压力他了,我希望他能过的不那么难受。所以抗拒的话几乎都到嘴边了,但最后还是咽了下去。接下来就是他们完全进入了 阶段,合同都没签上,就走遍周围的市场去买卫生打扫工具,把整个房子翻了个底朝天,然后再去房产那里签合同,签合同时,他们一条一条的审阅了内容,然后就其中一条问题比较大的条款开始质问,租过房的同学大概都知道是哪一条条款,最后双方协商结果是对本条条款进行补充情况,这件事才在短时间内结束。还没完,随后就是实习开始前几天,房东不同意条款补充内容,于是房地产侧重新拟定合同并重签,在他们审查完合同后就发现合同依然有一条他们认为不合理的条款,当场就开始咒骂中介;当天房东老婆也到场了,就要求她并提供身份证,结婚证明,房产证明原件供审查,且要求房东本人也到场,否则拒绝签字,双方又因为这个吵了一架,最后房东老婆受不了了,决定放弃租房。到这里他们才决定签字,这件事情也算是告了一段落。 写这段文字的时候我依然能回忆起那天各种乱七八糟的场景,想起这些事情的我依然会觉得喘不过气,原因如下: 搞卫生时他们对我说了一句: 审查合同时对我说: 对着这间小房子兴奋的手舞足蹈,仿佛找到了巨大财富一般,但这 在开始前一天对我说: ; 经过如此般的闹剧后也总算是住下来了,我现在还记得自己一个人住的第一个晚上望着,虽然买来的床垫几乎没有起到他应有的作用,因为家里买的说是床垫,更像是软被子,而房子里自带的床的支撑不是一整块木板,而是各种凹凸不平的木条所连接起来的一整个床铺。睡上去是十分的不舒服,但我那一晚依然在畅想未来的各种生活,我可以开始沉迷于吉他,我可以沉迷于个人世界,我还可以在广州找我的同学一起玩,去看看动漫星城,试试喵斯的手台,以及打一下舞萌,成为wmc...但美梦终究是美梦,这个本来住着就不舒服的房子终究成为了一个 破坏我客观生活质量 的存在,也许有人会说我脆弱,不抗压。但我知道我的极限就在这里,我确实过不来这种没苦硬吃的生活,所以随便大家评价吧。 开始实习的两个月 & 转暑期实习失败(2025.02 2025.04) 大概是25年开工后的第二天就是我报到的日子,当时我的 mentor 还在休假,所以是 leader 带我入职,入职前我来到了B4咖啡厅等 leader 来接我,并在等待期间认识了一位产品同学,他很有礼貌,而且学历很高,还有过三段大厂实习。我们聊的很愉快,然后就是 leader 领我去工位,当时组织架构刚刚经过调整,整个组都在 B1,而我还没被分到位置,所以在 B7,不过上班后两周就在 B1 给我找到了新位置。刚入职时给我感受就是很多东西都没有文档,因为大家都不爱写,而且申报okr时文档似乎也不算在内,所以很多东西都靠口口相传。我还记得当时在招聘网站上认识的同学,他在隔壁组,入职的一个月问了我好几次基础库的问题,当时我问他其他公司也这样吗,还是说会好些,他的回复是 。但抛去这些组里的氛围和人文关怀是绝对顶级的,有时 leader 也会单拉一个小群给组里刚加入的同学发 km 上高质量技术文章,组里也经常聚餐,不是庆祝新同学加入就是有同学职级晋升了。 B7 对面就是广州艺术博物馆 小米su7 刚出没几天,就在 TIT 里见到一台了 TIT 创意园的环境真的很好,距离广州塔就几百米,下班和早起如果有时间就可以去珠江边走走看看风景,旁边就是广州市艺术博物馆,展馆中间摆着一台钢琴,在 B 站首页经常能刷到高技术力大佬去做演奏的视频。而且 TIT 基本都是矮房,不需要等电梯就能直达工位,这是在我去杭州上班后才明白的好处。我到现在都很怀念组里的大家每天饭后散步的日子,大家在饭后会聊自己看过的动漫,聊一些技术上的话题,也会聊乱七八糟的日常,还有最近又面试了谁,以及饭堂又吃出了虫子(笑)... 说回正题,我是以日常实习入职的,如果要转暑期实习,需要再加一轮面委。入职前我叠了个比较大的 debuff,就是前文提到的 ,外加 ,使得我的精神与思维没法得到很好的恢复,外加当时开学了,学校的一大堆实验报告蜂拥而来,这使得我在 的状态是比较差的,从而导致了我面委表现得很差,半小时就被干掉了。一周后我的 leader 拉我去 1v1 并告诉了我结果,虽然心里早有准备,但听到这个事实的时候确实还是有些绷不住。我不记得那天 1v1 还说了啥,但是我记得我在会议室里头一次说出了 ,而不是家长的目标,也不是别人的期待的目标: 这也许是我无法将个人意志与工作相平衡的一个侧面体现。1v1 结束后日子还是得继续,虽然焦虑,但还是要不断前进,时间可不会因为你停下就停滞向前,可能是对工作环境的适应,也可能是在乱七八糟的事物一口气向我涌来后我个人的抗压能力变强了,我从 4 月开始对手头上的需求得心应手,开始学会了沟通,开始学会了拉人对齐,讲明白问清楚自己希望得到的信息,需求一个接着一个,生活也算是有了一个基本的正轨,虽然房子依然住的压抑难受,让人喘不过气,但有了音乐(加入了部门的音乐社,跟其他同学一起排练了一首森林,不得不说搞乐队玩音乐也确实是挺快乐的,而且也认识了很多其他组和其他小部门的同学,离职那天还和他们去广州塔下吃了一次饭,以及在B4前拍了一张合照),同组同学的陪伴(这里必须要感谢来自 STU 的同学,他也是实习生,我们每天饭后那会我们都会一起去散步,讨论各种乱七八糟的技术,以及讨论各种基础库遇到的问题,还有番剧和二游。以及就算我离职后我们还保持着联系,11月那会我还去广州找他一起玩。不知道离职前路由给他的问题现在修了没(笑))。 在这段时间里我也去尝试玩了一下新的 galgame(纯白交响曲sana edition)。以及看了川原老贼一部与SAO世界观有些相似的番《加速世界》。我个人评价是整体世界观和剧情走向还是挺吸引人的,就是有很多地方在表达上显得非常生硬,比如有时候男主不自信了说一些丧气话,女主一通嘴炮状态就好起来了。以及有一幕是有人开车撞向两人,女主为了救男主花了 99% 的点数把男主推开后被车撞了。这里最大的问题是动画表现出来的这个过程很生硬,我看的时候感觉女主明明可以在推开男主后保持加速并让自己也逃过一劫,这是总体上来说觉得最别扭的一个地方;以上这些让我觉得 “有时候有很多临场问题都是作者一拍脑袋想出来解决方案的那种感觉,没有一个缓缓铺垫,最终在需要的时候提出来时,让人感觉‘原来这个设定可以在此刻发挥作用’的释然感”。以及做了其他各种乱七八糟的事情尝试去找回一些自己的斗志和生活轨迹,不过都没有太大作用。 最后就是 4 月底的幡然醒悟,具体内容见:$1 写下这篇文章后的我决定去做出点改变,然后时间就来到了 5 月。 寻找突破与收留我的地方 & 学校的顶级抗压(2025.05 2025.06) 虽然说是要做出些改变,但好像也没有什么变化,随后就到 5 月了,因为知道这边想要转正很难了,而且生活状态很难再好起来,我于是决定寻求一点突破,这里的突破除了4月底下定决心的改变,还有一些事情:我家里人得知我转正失败时,第一反应是 ,说让我找个时间回家挑点东西带过去。我先是很震惊,觉得这并不对,而且客观上来说 leader 也没法决定,但最后我开始逐渐意识到,他们的思想以及不是属于这个时代,或者说至少不适用于互联网企业现在的运营模式,他们的思想已经束缚到了我的发展脚步:从一开始的租房;到我回家时我将自己对于工作上的迷茫告诉他们,希望他们能给出一些解法,但换来的是对我的不理解,认为我小题大做与逃避,最后总结都是我的问题;再到此刻说要送礼求情时。因此我下定了决心,我要自己走出去看看这个世界,用自己的角度去尝试理解这个世界,而不是理解成他们所认为的样子,不能因为他们说墙外有巨人就盲目相信,如果不是走出墙外,谁能知道外面还有其他的世界呢? 随后就是开始面试暑期实习,当时只面了 和 ,多维表格三面挂了后转去了 加了一面,最后顺利通过了,工作城市在杭州,虽然当时对出远门有点迟疑,但一想到如果还留在广深,他们的脚步必定会一直追着我不放。所以我狠下心推掉了 tme 后续面试,只身一人前往了杭州。现在回头看来,去杭州真的是今年所做的最正确的选择之一。详细内容留到下文展开讲。5月的面试压力还是不小的,当时算是五月底了,很多暑期也都招满了,留下的岗位寥寥无几,能有约面已经足够幸运,而且加上学校考试/课设答辩/带外包推进事情,每天就是复习速通考试和课设答辩,准备面试,以及带外包,刚回学校的头两天我一直在窜稀,饭也吃不下几口,整个人有点恍惚。我在压力最大那会发出过一句感叹: 。 字节发了 offer 后我和 leader 提了离职,leader 先是拉我到门口快速 1v1 了一下,大致聊了一下我后续是什么安排,以及问我有没有学到真东西。现在这个问题在我看来我可以这么回答: 如果光论技术我几乎没学到啥 但如果论软技能我一定是得到了提升,而且是直接从意识形态和思维习惯扭转了我的认知,让我明白我该如何面对和结构化认知一个事物和去解决一个实际工作遇到的抽象问题 最后我给我的 leader 送了一套伊利克斯的吉他弦,然后他送了我一本《金字塔原理》,我就看了第一章,后续就没看了,因为我已经在未来的工作中获得了自上而下的表述能力和对抽象事物的部分理解能力。以及给我的 mentor 送了我之前买的亚托利手办,我也是在离职那天才知道 mentor 还是画师,画的画很好看。以及在搭上回家的火车时,隔壁组的同学还跑来问我基础库的问题(笑),离职前两天产品还在跟我对需求,隔一天后跟他说我要离职了,他满脸都是震惊的样子我还依然记得。 总之这段旅程就在此告一段落,未来将是一段全新的生活。 mt 给手办的返图,他说这是他第一个手办 Last day 未来微信会不会也是我难以逾越的一座大山?我不知道,但未来的转机让我明白,我将会有一定的自信与底气去面对面试了。 总结这半年 回过头来看这半年,我能想到的关键词就是 , ,以及在黑暗中通过音乐、朋友和同事的关心来找到一些 ,以及我切身体会到了工作不是真的我想的那样,随时都可以把工作给变为自己 ,我也认知到了我其实并不是对前端技术本身感兴趣,而是因为我觉得可以通过这个 去 我各种天马行空的 ,以及前端这个领域下有很多技术 所代表的 是让我最感兴趣的地方。最重要的一点是:用 ,活出属于你自己的模样。不要再受到别人的束缚,只有自己走出的路才是最符合自己想法的路。 成为人类的4个月 & 轻小说般的生活(2025.06 2025.10) 在前往杭州的前一段时间里我在家中稍作休息,看完了笨测的轻小说,重新幻想了一下高中的生活,重温了几部动漫。最后在6月的中下旬只身前往了杭州。 租房 从踏上飞机前好运就降临到了我身上,在我的前端技术群里有一位群友也在杭州字节懂车帝,而且工区跟我是一样的,在我前往杭州那天他刚好要搭飞机回学校考试,而且大概要一周,所以他很大方的把他的房子让出来给我免费住,让我把订好的酒店退掉。在杭州的第一顿晚饭是楼下一家面馆,份量小又不好吃,于是发誓再也不去那家面馆吃饭了。第二天就开始在公司附近找房子,当时的目标是找一个有一大片白墙的地方,这样方便录吉他视频,但是找了很多地方发现都有个问题,就是空间太小没法蹦蹦跳跳的弹。最后去找了公司对面的一个双钥匙公寓,环境真的很好,40平,有灶台,有高级洗衣机,有干净的厕所,还有一个超大的落地窗,而且入住后才发现就在公司对面,甚至能从窗户看到我的工位,就是天花板有点矮,显得有点点压抑,而且隔音不是很好。而且就在看房的第一天,我上午刚看过的一套整租单间下午得出结论的时候再去问,就发现已经被人租走了!于是我只能快马加鞭签下了这套双钥匙的房子,房东人真的很好,沟通起来毫无压力,而且非常配合我提供各种证件的电子版,知道我是学生时还鼓励我说去努力适应这个社会。睡在自己租的房的第一晚的时候,我感觉生活似乎是终于有了个着落,一股从未有过的安心感贯穿了我的全身。 入职 & 日常工作 我是六月底入职的,当时我的 leader 和我的 mentor 一起到办公楼楼下接我,问了我在微信时做的业务,以及带我大致参观了一下整个办公区的结构,leader 读研究生的时候也是去微信实习,他说当时一进去就被关小黑屋搞东西,接触不到实际业务,所以知道我能接触到小程序相关业务时觉得很不错,mentor是一位看起来很年轻的小伙子,我以为他也就大学毕业两年,结果没想到他已经结婚而且有小孩快奔三了,对于我来说是一个极大的震撼。当天配完电脑后 leader 让我暂时坐一下同事的工位,他休了半个月产假,而且 leader 还特别好心的把他的屏幕拿给我用了,这就意味着在同事没有回来之前我可以用两块屏幕,当时朋友还调侃我说一块放代码,竖屏的放一篇论文,就对味了。此外就是字节的福利是真的好,腾在广州的茶水间就是有个茶包什么的,但是字节就有一大堆零食可以随便吃。我基本上每天都要从茶水间拿不少小零食,比如好丽友派,辣牛肉,鱼豆腐来吃。以及字节的三折饮料真的是爽到没边了,几乎每周都要买两三只葡萄气泡水来喝,走之前也带一瓶牛奶回家。而且我觉得最舒服的入职的一点就是,这边文档相对微信是比较完善的,虽然我们组加入新人的频率很低,这就导致很多文档可能都是写给组内自己的同学看的,他们有充足的上下文,能够立刻理解文档的一些黑话或者缩写指的是什么东西,但是我作为一个新人来看待是完全不懂的,因此有些坑都是我自己踩过后,重新梳理成一份文档再补充回组内文档去。但总体上流程是更加清晰的。 然后就是需求给到的频率,这边需求其实不是很多,而且都是做细节上的修修补补,但相对的,我能感受到有很多事情的时间都是花在开会沟通上,我记得我手头有个小需求,就是给一个接口增加能力拓展,这看起来是个小需求,但是在 mentor 和 leader 眼里,他越讨论就变得越来越复杂,最后甚至拉上了 +2 和其他小部门的 +1 一起聊这件事,开了一个小时的会也没讨论出结果,最后初步结论是要继续对,以及拓展成通用能力。从来没遇到过这种大阵仗的我属实是被吓蒙了,因为在微信的时候跟我对接的后端基本都是固定的几个人,而且他们的答复一般就是“能做” “等几天给你测试” “有点复杂,我待会看情况一下然后给你结论”。不过这也算是给我体验到不同的业务与产品与不同的管理风格会有啥不一样的感受。说到开会,字节给我的感觉就是会特别多,有些会其实你理论上是没必要去的,但是你可能作为某一个前端组的成员你就得过去看看了,之前有一个技术评审会就是我没去,我的 mentor 问我为啥不去,我就解释了一下我的想法和看法,因为我不是一个专门负责某某方面的同学,而且资历或者技术认知领域也不够强大,不如在工位上更好的去专注自己的工作和熟悉自己负责业务的架构。这里很感谢 mentor 愿意听我的看法,而不是一定要拉着我去。 当时的工位 最后就是说说我在面对新需求时的改变。我不再像是第一段实习那样找人沟通都要做好几分钟的心理准备,而是直接飞书消息讲明白我的问题与需求,讲不清就语音和投屏快速问清楚。遇到要跨小部门协作时也知道直接拉个群,把对方负责人拉来,然后让他给我路由,并持续推进。以及做我转正答辩用的项目时,遇到了编辑器工作方式与行为不符合预期的问题,也是直接找到要对接的负责人并让他拉人,直到找到当前负责人给我解决这个问题。这真的是自从上了职场以后作用最大的一个思维转变,感觉人都变成熟了几分(误)。 转正答辩 & 焦虑和压力并存的2个月(2025.08 2025.09) 大概是八月初的时候,我的 ld 来找我聊转正答辩,给我下定心丸说hr和+2都很认可你,希望你留下来,答辩通过的概率也很大,我当时其实还有点怂,因为我其实没做多少能够讲自己产出以及能力的事情。所以大概就是从那个时候开始复盘自己有啥东西可以作为答辩素材使用。恰好那个时候加了一个字节实习生小群,里面都是顶级神仙大佬,八月的时候每天都在群里汇报面试成果,今天面了腾明天面了小红书,最早的那个人甚至8月底就拿到了青云提前批意向,我曾经发问除了面试就没别的聊了吗,平时就没有兴趣爱好和想做的事情吗,得到的统一答复“还真的只有面试和薪资能聊”,我知道我自己并不喜欢这个群的氛围,所以就把他塞在了折叠的聊天里。但是还保留的原因是里面的同学很多都是对职场有自己的见解和看法,以及也有多段实习,见识过大厂各种风格,对面试和转正需要什么有更透彻的理解,为了避免掉这一些方面的信息差,所以我依然留在群里。现在看来确实是起到了一定的帮助,比如说改进转正文档,为转正的答辩素材捞苦力来给我做结果验证,认识同部门的同学,吃各种乱七八糟的瓜。当然也发生过一些事情让我彻底明白“有人的地方就有冲突” 这件事是我编写转正答辩文档的那段日子,这里先讲讲我的主要产出是什么: 一个 JSON & JSX 编译器,皆在为业务的空间实现更好的 DSL 编写体验 业务场景是一个表格里的格子,这个格子允许用户自定义编写布局展示内容,编写布局的方法采用的是 JSON 原语言是 JSON,现在可以通过 JSX 编写,且语言之间可以实现无缝转换 支持表达式编写,原 JSON 需要通过 这种方式在 json string 里写计算用的表达式,采用 jsx 后可以直接脱离这种模式编写,就像正常使用 js 一样编写表达式;且实现了语法检查,可以针对不同的表达式系统进行识别适配 实现语法降级,即 a?.b?.c 降级为 a && a.b && a.b.c,且转回 JSX 时也能实现回到高级语法模式 所有转换过程都在前端实现,避免引入后端存储成本 为一个页面得条目实现虚拟列表迁移,并讲解自己得思考与细节处理方式 自行重写组件,相对原有组件优化了重排次数 其次产出就是补充组内新人文档,投稿文章给内部技术平台,以及其他一些软素质的体现。 所以整个转正文档会着重写这个编译器,而且我个人风格就是很喜欢细细的讲清楚自己做了啥,因为我觉得愿意有人倾听和了解我的思路是一件很荣幸而且很高兴的事情。因此我的整个转正文档按我自己的个人风格去写了一次,并拉上 mentor 和 leader 开了个会过了一遍,在写之前 mentor 跟我说你这个转正文档肯定要写个三四遍,我一开始还不信,直到开了这个会拉上他们过了一遍之后,才知道这个文档有特别特别多的缺陷。我的 leader 在结束讨论之前跟我说了一句 “ ”,但非常遗憾的是我并没有任何 PPT 制作汇报经验。因此我只能绞劲脑汁回想起在前司看过的转正 PPT,那个时候最大的印象就是字不是很多,但写清楚了主要做的几件事情,以及配了一些很清晰的示例图片。因此我决定在第二版文档简略我的文字,并且以图片和画图作为主要示例,我依靠讲解来传达我的思想。 写完第二版后我觉得还可以,然后我就把文档发到了实习生小群,希望大家给一些意见。但是让我没想到的是这是一个短期小噩梦的开始,群里大部分同学都是后端+算法,做前端的同学并不多,因此我比较看重前端同学的看法,但是就在这里,前端同学的给出的意见与我想象的大相径庭,这里简单摘录几句: 只看到对一个个需求的思考 没看到对部门业务的思考 没体现owner意识 技术的东西讲的太多,评委如果相关背景了解不多读起来有点吃力,多讲讲做这个难点的收益是啥,解决了什么问题,对产品或者用户或者研发效率有何提升,这个评委爱听 说服力感觉不强,为什么这几点是必要?有什么收益,有没有考虑后续的维护成本多大?能抵消的了吗 为什么这样做,思考过程呢,有调研过其他思路选型吗,直接给结果显得没啥思考,因果关系我没有看懂 整个文档划线评论来了几十条消息,给我看的很懵,然后在我看到这些评论的时候,说实话给我有点不适,这种不适感是一个事物与我主观意识观念强烈排斥时所带来的反应,我当时是头一次感觉到这个氛围与我理想的技术探索氛围是完全相斥的,以及就是被狠狠的打击了自信心,有一刻还觉得自己做的这些东西其实啥也不是,因为没有带来实际效果。直到实在受不了的时候,找了前组饭搭子同学,以及大学朋友的小群吐槽的时候才勉强缓了过来。尤其是跟前饭搭子聊的时候是倾诉了最多的,因为我认为他作为一个热爱技术并且真正去做实践的人,可能更能理解我现在的心情和感受。当时我还调侃自己 。现在看来还真没错,只不过科研的一定是自己感兴趣 & 市场对这些问题有实际需求。不过也是借这一次聊天我坚定了自己的想法,一个 RD 尝试去做某一件事的研发或者探索的初衷不应该是为了 OKR 和绩效去强行搞起来,又或者说不应该是史上雕花,而是觉得有东西后发自内心的去想做,并彻底的完成它 & 达到预期理想的效果,OKR 什么的则是这一过程的副产物和附加奖励。当时说到这里时我特别想念在微信那会一次饭后散步跟同事闲聊技术,我当时聊到自己看了一下 V8 的 turbofan,同事听到这个后突然想起基础库某个地方是不是能用这个条件去做一些提速优化,有空就试试搞一下,他们在谈论这个东西的时候眼里是 的,那一刻我觉得我学各种新的技术与思想就是为了这个瞬间。所以他应该是一个 想去做,并且在做的时候感受到充足动力 & 的一个过程,而不是这样说被人问你这不对那不行,达不到我们的要求的这种氛围。说来也有趣,这个时候饭搭子就问我要不要回来面,我说等答辩完,并且调侃 ,但他并不觉得我有太大问题: 。我真的很感谢有他这一会陪我聊聊天,不然是真的没法找回我的自信。 聊完之后我也懒得再跟他们争到底是技术重要还是收益第一了,我决定去找 mentor 看看文档。mentor 跟我一起把文档快速过了一遍,对一些不清楚的地方做了评论,以及指出整体的表达还差在什么地方。当聊到评论里的 owner 意识时,我其实依然有点不服气,于是便问了一下 mentor,mentor 看完评论后就开导我说 owner 意识是没问题,但它不是你现在这个阶段必须的东西,他可能是拿了他们部门的评判要求来套到了你这里,我们这里没有那么多细则,你现在最重要的事情是把自己做了什么事情,以及他的效果清晰的传达给别人,这就很好了。 这里必须提的一句是自从我开始准备我的转正项目,我的 mentor 就没有给我派需求了,这得以让我专心思考这个项目所面临的各种问题,这些问题就连内部技术平台,飞书文档上都没有相关例子,尤其是表达式识别,基于现有的 AST 工具去做行为限制也是一个全新的突破,就像是踏足了一个从未有人走过的领域一样,成为了这个领域的第一个探索者,可能搞科研的同学们在踏足一个新的学术领域时也是抱有如此热烈与激动的心情吧。 最后就是我重新坚定了自己的内心,开始着手写第三版文档,这一次我转变了思想:“用这一份文档,结合画图,讲清楚我做的事情,以及其中技术思想的精妙之处。同时聊清楚我为什么要这样做,我在做这件事之前我思考了什么,才促使我去搞定这样一件事情,以及这件事未来的发展与计划是什么,我要如何收尾。” 第三版文档是周末加班加点写的,那时刚好还赶上字节跳动开放日最后两天,当时我在 13 号约了好友一起去,20 号那天加一天班用来写文档,也顺便体验一下新工区工作环境。这里放几张当时的活动图片。 字节开放日发的东西真的多啊,把乱七八糟的玩意拿回家时跟从漫展满载而归没啥区别。 pjsk 展台。13 号去要求歌曲评价打到 B 可以领手环,但是账号都是初始号,没多少角色。隔一周去后就说要打 fc,不限难度,然后就挑了个 ez 难度拿了个手环 新工区座位。颜色越粉,打架越狠 除了甲醛有点重,其他什么都好,饭是真的好吃,目前吃的窗口还没有感觉有难吃的东西 最后终于赶在答辩的前一天把文档写完,给 mentor 过了一下, mentor 很满意,说各种东西都写得很清楚,看的也能理解个大概,然后剩下的时间就是约了工位旁边的主题会议室,花了两个小时过了几遍答辩演说流程,然后就回家休息了。 最后就是聊聊答辩前对于我编译器的一个理论证明过程存在的瑕疵,还有我在这一过程对 AI 的误解,与思考,还有对抗,以及我在答辩结束后终于在某一天想清楚自己要怎么跟别人解释这件事的方法。以及我个人认为答辩的一些要点。由于涉及到内部技术方案,我就只简单讲讲一个粗浅的过程: 我做的东西一直无法在理论上完成一个完整证明,走投无路的我就让ai去想一个解决方法 ai 想完后我并没有深刻思考 ai 这样做是否真的是正确的,只是沿着 ai 的方向直接去探索,浪费了很多时间也没得出一个让人信服的证明结论 直到有一天我洗澡时突然想到了之前学的编译原理知识,结合一部分图的思想,我终于想到了一个正确的证明方法,非常浅显易懂而且让人信服 现在回过头来看事我对编译知识的一些理念没有深刻的掌握,如果让我重新选我还是会直接选我最早实现的那个解法,因为简单,而且好使 同时我也总结了 ai 解决方法的问题:ai 的思想没有错,也能搞定这个问题,但是缺点在于验证过程成本非常高,因为他的本质和一般的验证模式是反着来的,相当于逆路径去做一件事情,其中带来的验证成本就非常高昂 然后就是转正答辩,我这里唯一能讲的事情就是 。其次我认为这2段实习+答辩所给我带来的最大的认知就是: 理论虽然易懂,但实践 & 改变思维习惯后才方可出真知,请各位还未在职场就职或实习过的读者请在未来切身体会这一过程。 答辩完那天我选择吃完饭就光速跑路,只记得吃了4F的湘遇,那天是小炒黄牛肉,鸡肉,还有猪肝,太好吃了,我现在都还想回去吃一次。答辩完的每一天我基本都要上去看看状态,结果隔了两天后 hr 系统就流转状态为 offer 沟通了,当时那是一个喜极而泣啊,由于还在上班所以拼了命的不发出声音,但确实很激动,差点哭出来了。跟群友对了一下这个状态,就是稳了的意思,一周内会发意向。果然5天后 hr 就给我发了意向,紧接着就是愉快的国庆假期了。 等待Offer & 打通一个 happy end(2025.10 2025.12) 后续我并不打算继续留在部门赚钱,虽然一天400确实很爽,但主要问题是我想把更多的时间留给自己,我有很长时间没有去做自己真正感兴趣且长期主动想做的事情了,很多事情都是短时间内一个短期的兴趣和研究。我想去找回我发自内心且长期觉得有意思的事情,于是在国庆假期提了10月11号的离职,15号离开了这个梦一般的城市。在国庆期间面基了一个网友,带他走了西湖,暴雪国内首家旗舰店,玩了胡闹厨房,参观字节新工区,还有浙江大学,为我的QQ机器人实现新功能,而且还刚好赶上了gbc快闪,于是狠狠买了一波东西。 不登校 虽然不清楚败犬女主本作好看在哪,但不可否认的是老八确实很可爱 ZJU 柴郡粘土人可爱 离开的当天我给 mentor 和 leader 各送了一本高木直子的漫画,原则上字节不鼓励送礼,但是我确实有一份心意想要传达,就把这本小时候沉迷的漫画送给了他们。然后就是去给机器退库。最后就是退卡,退卡前我趁这个机会去饮料机薅了几瓶气泡水,还买了一瓶酸奶。以及最后来到天台,留下了几张照片用作纪念。 对面就是钉钉的新大楼,感觉环境挺好的 楼很高,到高层区基本都是用高速电梯,第一次坐的时候直接被吓哭了 回家后我没有停止学习,而是开始去研究单片机和嵌入式相关的东西,因为我的认知里嵌入式这一行比较吃经验,而且不像软件行业存在所谓的 35 岁危机(虽然更大概率是你干不到 35 就被迫离开这一行了)。所以我买了一块51回来玩,虽然我的朋友都劝我搞 stm32 就是了。然后我就回学校开始处理各种实验报告,课程,甚至是考试。。。这段时间玩的还算开心,51 也学到了系统中断,其实中断实现没什么,但是我一直觉得中断思想简直就是天才的神来一笔,从学习操作系统那一会就一直这么认为。然后,然后,然后就没学了。。。因为发现热情会不断消退,而且总是有各种乱七八糟的事情在打扰我的专注力。尤其是体测,我是在本学期体测截止的前一天才知道这学期补测早就开始了,于是就马上趁着最后一天加紧时间测完了所有项目,其中很痛苦的一件事就是拉引体向上的时候,我跟别人站错位置了,我拉的11个全算到别人那里,而别人就给我拉了两个。老师知道后也没让他们回来,而是让我想我测。。。随后我又拼了命拉了9个,代价就是未来的一周我的手臂都抬不起来,疼的要让人昏过去。不过都过去了,赶紧毕业就好。 考完试之后我依然留在学校,因为我想着是等到跟我正式谈薪了我再回家,这一等就是等到了12月,在此期间认识的好多人都开奖了,我也被拉进了字节那会的实习生微信小群,群里天天都在对开奖,比哪一家薪资要高。我也忘了大体是啥情况了,只知道有人能开到起飞的薪资。有时候我也感叹无论你怎么前进,总有人会走在你的更前面,认知到比你多得多的东西。我唯一能做的就是不去看这些东西,把注意力转移到自己所期望的事情,不然搞得是心态,没得是精神。从 11 月一直等到 12 月初,HR 终于打电话来跟我谈薪资了。简单来说就是开了个我无法拒绝的条件,所以当场爽快的接了,随后就是整理收拾东西准备回家。 回家后也差不多是年底了,这个时候着手就开始写毕设,我的毕设就是实习时用过的一个产品,这套产品我觉得挺有意思,而且也不知道有什么其他产品可以做了,因此我把这个项目作为了我的毕设选题,而在攻克最难的部分(实现一个算法,该算法可以将一个包含起终点的有向图绘制成一个流程图)时,激起了我对 AI 的思考,随后便想着趁这个机会写成年终总结,因此便有了这一篇文章。 校招礼盒 未来的计划 26 年我的计划是在上班前产出我的毕设流程图绘制的算法实现过程博客解析文章。然后年后就开始上班实习三个月,6月回校答辩,并完成属于我自己的个人或团队旅行。实习期间我希望我能对一些数字图像处理方式,相关业务部分做出一些思考与研究,并且将其以文档文字的形式写下来作为我的个人技术积累。还有就是继续学习单片机吧,因为我当时学单片机就列出了几个目标: 基于 LED 做一个世界线变动率探测仪 做一个世界线窥探仪,简单来说就是个小相机,相机上可以调整世界线的变动率,然后通过相机可以看到在该变动率下世界是什么样子的 做一个电钢琴灯,网络上的电钢琴灯价格基本都在几百,我不清楚这一部分的成本在哪,所以我想亲自做一下看看成本大头在什么地方 做一个自平衡方块,不过我对这个没有特别特别大的兴趣 年后就是入职上班了,到时候一切的目标就都得看公司怎么安排了,但我希望我在这个过程不要失掉自己的斗志与兴趣,而是依然能做那个纯粹的自我。我依然记得我大二的时候沉溺于为自己设计一个音乐播放器的日子,那个时候我每天都在想 UI 要怎么画,架构要怎么设计,多线程下载要怎么做,我能不能用 rust 手搓一个玩玩。最纯粹的日子莫过于那段时间,此后我就再也没有体验过这种感觉,可能最接近的时候就是做编译器了,但根本没有说一直能坚持保持下去做纯粹的思考。这也是说我希望我入职后能依然保持那个纯粹的自己的原因,当然我也对新入职的部门做的产品有一定的想法,不过这都是后话了,基本上得有个2年起步,这个想法才有机会去真正的落地。 致谢 感谢许多与我一起合作过的同学,感谢遇到的两位 mentor,他们都是很好的人,还有两位 leader,无论是我还是同事以及对接部门的同学,对他们的评价都非常高,没有让我在职场觉得过的一点都不开心。感谢我对接过的所有同事与同学,大家都特别好沟通,也特别友善。还有我认识的网友们,每天都能通过网友看到一个不同的世界,有时就会觉得原来世界不止有计算机,还有各种各样的生活方式。感谢技术群群友,大家都很默契的不聊技术,只有吹水与看乐子,以此保证聊天记录的纯粹性,有时不开心了就回看一下聊天记录,玉玉症都能被马上治好。以及感谢在杭州遇见的邻家天使,现在虽然终于看清楚了自己的想法,也明白了自己什么做的是对的什么是错的。但不可否认的是那段时间所带来的快乐和能量是客观存在且切实的给我提供了足够的动力去面对工作与生活。 以及最后送给所有读者的一句话: Do what you love and Love what you do 做你所热爱的事情

2026-01-04 - Shiina

更换证书至Let's Encrypt踩坑记录

前言 大概是几天前我的学弟过来提醒我证书到期该更换了,上来自己的博客看了一眼,发现是在 2025/11/19 号到期,一想到又要上腾讯云官网去挨个申请证书再挨个放到服务器里就觉得麻烦,又听说 Let's Encrypted 允许申请二级域名通配符证书,于是打算趁换证书这个机会一起研究一下。 最终成效 & 一图流指南 我最后没有去申请通配符证书,简单来说就是要做一个 DNS 验证,详细原因可以在下文找到,我嫌麻烦就不搞了。 我为主站 http://shiinafan.top 和博客 http://blog.shiinafan.top 进行了 Let's Encrypted 的证书申请,每次申请成功后会自动将证书生成到指定目录,且会在到期前一段时间进行自动更新。 快速指南 采用前提: 服务器是 Windows Server,nginx 是手动启动 + 手动指明证书路径,且不需要通配符证书。 网站已在 80 端口部署(nginx启动且已配置到可以正常访问你的网站) 操作步骤: 前往 https://certifytheweb.com/ 下载可视化管理软件 根据提示安装 安装完毕后打开软件,并点击左上角 注:第一次新建可能会提示你填一个邮箱,填写常用的即可,不需要做验证 根据你的需求填写你需要申请证书的网站 点击 选择验证类型为 ,并设置你的网站文件存放路径 可以点击测试来确定你的网站路径是否正确 点击 ,添加一个 ,并选择 ,在任务参数中设置你存放 和 文件的位置 最后申请证书,全流程跑通了应该就能看到证书已经成功申请 & 自动部署更新文件了。 自动更新默认开启,具体可以阅读 https://docs.certifytheweb.com/docs/renewals 根据自己的需要修改更新设置 By default, Certify will attempt to auto renew your certificates and tell you if something goes wrong 踩坑记录 神秘的 Certbot 官网 首先是 google 找到了 Let's Encrypt 官网,并根据提示前往 Certbot 页面下载他的管理软件: 根据首页指南进入了该页面:https://certbot.eff.org/instructions?ws=nginx&os=windows 根据步骤一步步走,发现他给出的 GitHub 下载链接是 404。 怎么回事呢?去社区搜了一下发现也有人提问,最后在回复里看到说上文的页面已经提示说 windows 不再被支持了: Certbot has discontinued support for Windows as of February 2024. You can find alternatives listed on our community announcement here 然后去看了一下$1,其中给出了几个解法,我选择了第一个,也就是上文中的这个自动管理软件。 整个软件还是比较好操作的,就是通配符证书不能选用 http 验证方式,这种验证方式是在你的网站目录下面放一个 acme 的验证文件,acme 服务器会访问你的网站并确定文件是否存在,验证通过了就会给你发放 ssl 证书。 而通配符验证需要你用 dns 进行操作,看了一下似乎是需要指定你用的 dns 是谁,且每家 dns 验证的配置还不一样。我暂时还没有那么多网站需要去使用 https,因此就放弃研究了。 自动更新失败时会采用你在一开始提供的电子邮件地址并发送邮件,来告知更新失败。 总结 整个流程通过软件自动化后就方便很多很多了,以前每次访问网站提示证书过期的时候心里总是来一句“wc,怎么又过期了”。因为刚买服务器那会还不存在 90days 过期这一说法,一般都是一年一换。自从 90days 政策生效后自动化管理流程也成为了一个必需品,还好有很多无偿免费的软件默默在背后进行支持。衷心感谢所有无偿的开源开发者为互联网事业做出无私而又巨大的奉献。

2025-11-22 - Shiina

文字尾部展开按钮解决方案一览

文字尾部展开按钮解决方案一览 前言 这是之前做需求时遇到的一个问题,抖音 semi ui Typography 下的 Paragraph 组件在被大量使用时产生了性能问题,具体场景是在列表使用时发生的。为了解决这个问题将组件改成了自己的实现,同时把列表换成了虚拟列表。 这次优化是虚拟列表立了大功,但是个人在探索了 semi ui 的方案后发现了门道也有不少,于是打算做个总结 css 实现 这种方式比较简单,参考文章:https://juejin.cn/post/6963904955262435336 comment 这里简单讲解一下思路: 使用浮动让展开按钮悬浮起来,并通过 float: right; 将其移动到右侧 使用另一个隐藏元素,同样浮动到右侧,并且把高度设置为隐藏时元素的高度 按钮的高度 对按钮清除浮动(浮动的作用就是用来移动到上一个浮动元素的下面) 当文字行数不够时,在文字尾部用一个足够长宽的元素挡住展开按钮 https://juejin.cn/post/6963904955262435336 heading 6 方案的优缺点: 纯 css 计算,性能会比 js 要好 使用到相对现代的 css 实现 (calc, webkit box, line clamp) 目前主流浏览器已全部兼容 默认浮动到右下角,如果样式需要精细调整会有点麻烦 js 实现 这种方式适合兼容老式浏览器,因为不需要特殊 css 处理 个人的思路如下: 先测量当前文字是否超出容器指定文字行数 是,进入以下步骤 采用二分法截断文字,直到测出截断后文字能够同时塞入结尾省略内容 + 展开按钮 否,直接展示文字 semi ui 为什么会存在性能瓶颈 原因 源码实现里在全局放置了一个公用 dom,专门用来测量文字高度 当页面上有多个组件一次性渲染出来时,就需要多次替换文字 + 父元素样式进行测量,间接导致触发多次重排 其中一次测量本身就会有多次重排: 获取容器原样式替换到测量容器时会有一次重排重绘 测量文字截断到哪里才能容下所有自定义元素(ologn),每一次截断计算也都要重排 所以页面阻塞的时间长度为 onlogn n 为平均重排占用时长 优化? 除了 canvas,核心思路都是推迟/减少一次性计算量来避免页面卡顿 canvas 测量文字 实现:https://github.com/QingXia Ela/semi design/blob/typography pref/packages/semi ui/typography/util.tsx L41 可以说效果显著,平均一次测量的时间下降到了微秒级别,但是有几个问题: 文字截断截少了 这里采用的逻辑是测量出文字在 canvas 上渲染后的长度,并且用原元素宽度将计算宽度相除得到的占用行数,问题就出在这里,dom 的文字排版中,假如一行剩余的空间塞不下一个字,就排到下一行,而这里的计算没有考虑这种情况,就相当于我把一个字截断了塞到了剩下的空间,再把截断后剩下的文字排到第二行(最大限度利用空间说是)。这就导致了计算出的文字数量比通过 dom 计算的要多 解决办法是遍历文字,并计算出到哪个文字就会发生一行内空间不够的情况,并将这个宽度记录累加到一个记录上,再最后计算占用行数时,把这个累加值也加上,就能得到真实占用行数(即模拟排版系统的计算过程)(真好奇 chrome 的排版系统是怎么做到高效计算的喵) 自己的实现是通过 获取原 element font 属性,这里依然会触发一次回流,如果从 element.style 获取的话是只能拿到通过 style 设置的样式 大量渲染的场景一般来说不可能会有每一样 item 样式都一致的情况,可以考虑基于此给每个 item 做样式分类,以避免重复计算 font style 用 intersection observer 这种优化思路主要是避免不可见区域的计算,可以预见的缺点: 该观察器的任务优先级很低,回调会等到浏览器空闲时才执行,因此有可能出现页面渲染出来了但是没有进行文字缩略的计算 中断计算 类似 react 中断,但是这个涉及到 dom,由于可能会影响用户体验所以不建议使用 对于组件优化原文的思考 scrollWidth 属性获取缓存 这个实测出来浏览器有缓存,多次获取不会重排,但是实际情况可能得再看看 fragment 减少重绘 这种方法我觉得只能降低重绘时间,开发的成本可能会更高,因为存在样式隔离的问题,通过 getComputedStyle 获取样式的开销是不会少的 参考文献 https://bytedance.larkoffice.com/docx/AHcRdimGtohQ64xVW4PcJsqDnKg

2025-07-16 - Shiina

在微信的三个月

其实本来打算等lastday的时候再写的,但是现在提笔写下这篇总结完全是出于自己的想法,今天上午自己被学校发的签到吵醒时才突然想明白了很多事情,遂决定写下本文进行总结,虽然现在顶多算2.5个月,但也大差不差喵。 回看这段时间的日常实习,我的关键词是:遗憾,焦虑。当然也有快乐的时候,不过大部分时间都是前面这两种情绪主导。为了避免后人再次踩坑,我将在本文详细解释我遇到的困难 + 产生的原因 + 应对的措施。同时总结新人实习时除了业务本身,还有如何处理生活与工作上的平衡,调控自身的情绪,让自己恢复到最好的工作状态。本文不会教你实习怎么去做产出,因为有产出的前提是你的心态足够健康,且在工作之余还有时间去思考自己感兴趣或者想要了解的方向,而且这种文章牛客比比皆是。但是相对的,我基本上没刷到几篇关于如何调控自身心态的文章,因此我想要补充一下这一方面的空白。 lz的背景:双非,第一段实习,学校很多课+作业+点名,实习前的心态是:我要做出思考,并做出实质性的产出 先说结论,后续针对结论的详细解释在后文展开,如果你时间紧迫,看完这几点,牢牢记住并切身实践即可: 入职后不要立刻想着做什么产出,做什么沉淀与思考,先体验工作,不要想其他事情,入职后你唯一的任务确定好份内工作搞定后有多少时间是属于自己的。然后在有余力的时候才去做自己感兴趣的思考或产出 对于需求,尝试对需求进行分解尝试,如果有余力或认为需求有价值,则可以对他结构化并清晰的刻在脑子里。对不了解的点自己查查资料或问问mt,一步步推进 沟通技能不是一朝一夕可以锻炼出来的,尤其是从0开始的时候最为艰辛。基于第二点,分解完需求后你就知道哪些点是真不懂,可以去问,问的时候也能准确地表达出自己疑惑的点,避免浪费时间。不熟悉项目时多点沟通反而是好事,避免踩坑 如果你是处于很迷茫的状态,又或者很焦虑前途,此时你最重要的是转变心态,即第一点的 “体验工作,不要想其他事情”。只有心态转变了和有空闲时间了才能以更积极的心态去处理更难的事情。其次,不要想着做什么产出或者见证、理解智慧结晶,也不要觉得少看一点东西就是亏了,原因我会在后面解释 接下来我会一条条解释我为什么这么总结要点: 第一条是我认为最重要的点。回想起刚入职的时候,电脑还没装完环境就拼了命找内部平台的各种文章,探索自己想要了解的各种领域,随后给自己列出了一个目标文档,是实习期间打算完成的各种事情。现在回过头来几乎是一件都没有完成,因为我没有平衡好工作与生活,每天都在内耗中度过,为了自己心中的产出和证明自己的思考,对 mt 下发的需求也是从头到尾问了一遍,现在回过头来看这其实作用不大,刚开始实习,环境还不适应,对于开发流程也不熟悉,就拼了命给自己上压力,这无疑是在降低工作效率。其次,需求里并没有什么真的去值得深入研究的地方,就算真有,也不是前端的领域,了解了虽然可以拓展知识面,但是对工作本身帮助不大。lz 当初入职就是想着要把所有的时间都用在工作和思考上,只想着要思考,要做产出,而忽略了思考本身的意义是什么,能给我带来什么,以及思考前我应该先搞好工作。由于每天上班手头的事情没搞好的时候就想着要怎么去做价值更高的产出,导致我开始内耗,让我实习的头两个月精神都很差,生活规律也变得混乱,工作也做的不好,有几次做的东西出现了各种问题,还是那种很低级的错误,都是mt给我擦屁股,甚至情绪调控能力也发生了退化。最严重的时候甚至几度怀疑自己的能力,产生了 招我进来算不算招聘事故/我其实很笨,只不过运气好混进来了等念头,外加在内耗状态下导致面委挂了的事实彻底的打击了我的自信心。直到两个月过去了才发现自己的观念可能有问题,此时终于意识到这个念头不仅没给自己带来所谓的“产出”(其实还是有一些,但是并没有真正落地,现在看来也是得不偿失),反而让自己连正常的工作都没有好好做完。现在看来“我一定要搞产出”这个念头真的是浪费了很多精力,不是说这个思想不好,而是不应该把它作为一个硬性目标强迫自己去实现。不如把手头的事情解决了再花足够的时间去研究真正有意思的东西,这总比工作时焦虑要好 第二条是需求,这个也是lz认为一个比较重要的点,虽然刚入职的时候没法做到很正常,因为有很多乱七八糟的流程要搞明白。我认为这个能力应该是在入职1 2个月后,面对一个需求能够有一个基本的认知,能够说出一个每个功能大致的执行流程。3个月时,能够针对流程中的各种细节清晰地提出疑问,找出边界条件。如果有能力,可以针对疑问适当地自己提出解决方案。其次是问 mt,这个看个人量力而行,lz 刚入职的时候并不敢去问,一个是对项目本身不熟悉,第二个是不敢去问,没啥自信,感觉自己问完也记不住,没法在脑子里形成一个体系;这非常的正常,所以前文里我提出的是1 2个月去适应他。 第三条与第二条相辅相成,沟通是很重要的一环,他直接能体现出你对项目是否熟悉,对边界情况是否有考量,对业务流程是否有足够深入的理解,以及你的表达是否能够精准命中核心问题,以及你的思维是否清晰。但是如果你是刚入职 + 社恐,不会沟通是很正常的,lz 就是一个很典型的例子,最开始的一个月有疑问都是自己憋着,甚至拼了命也想着要自己解决,一个是不想麻烦别人,另一个还是所谓的“证明自己”。现在看来完全没必要,而且甚至带来了一些问题(有个小事故就是我不敢去沟通导致的),但我也不会斥责当初迷茫的自己,这个确实只能靠锻炼实现。我依然记得我入职一个半月后组里为了欢迎新人,大家一起去聚餐,结束后我们新人小团体决定一起去吃甜品,闲谈之余聊到了沟通这个点,社招入职的哥们说就刚刚聊的这会感觉我根本不社恐,而且表达也很清晰。最后回家跟家人讨论了这一点,他们总结出我只是对业务不熟悉才会这样。现在看来也许只是终于找到了机会去倾诉自己的困惑,也可能是不想让其他人掉入类似自己的陷阱罢了。 最后一点可能不适用于一心只想着大厂的同学,如果你奔着大厂去那你肯定是少不了焦虑的。日常实习,暑期实习,转正,产出,思考,偷核心内容,偷技术,秋招,提前批,捡漏,春招。这些词是我在入职之前听到最多的,有很多人知道了我来微信后都以过来人的身份去给我规划各种未来,让我关注各种乱七八糟的东西和信息,而我刚好处于一个迷茫的时期,众所周知人在迷茫的时候是最容易听信他人言语的(参考沙林毒气事件背后的教团)。我应该就是这个时候开始陷入产出焦油坑,所以入职后拼了命的想搞各种有价值的东西。我在此引用一句席勒的名言: 只有那些有耐心做好简单事情的人,才能获得轻松完成困难事情的技能。 我对这句话的理解是:对简单的事情有了清晰,结构化的认知后,才具备资格和能力在简单的事情基础上思考更复杂的事情,并对更复杂的事情同样采用结构化的认知,如此往复达到思考的巅峰。然后是最后一句少看点东西就觉得亏了,这里引用一下面我的哥们的一句话,“我们一直在给未来的自己创造技术债,并且还是附带利息的那种”(翻译过来就是天天产出史山,还是越堆越高那种,未来还要因为目前产出的史山导致的问题去用更高的史山处理他) 其他碎碎念: 找到一个可以稳定给自己提供情绪价值的方式,无论是运动还是什么,只要你在做这件事情的时候感觉到自己有兴趣,又或者是能够感受到充足的动力,以及能让自己全身心地投入,那就是正确的事情。lz在这里分享日常会做的事情:弹吉他,以及给一个社区做点网页,还有听听歌。这里分享一下目前最喜欢的歌: Kotoha 雪は何色,很好听;以及 Piannet Aoi Tori,古典气息浓厚,是与 Animenz 不同的改编风格。 不要去针对某些东西进行无意义的扒源码,来证明自己的思考或者努力。这里是lz刚入职时犯的错。为了隐私就不透露lz的领域了,但是我举一个例子:聊一下 vue diff。如果是刚入职那会的 lz 则会开始去记忆整条调用链路,这一切都是为了所谓“证明”自己的思考,但现在在我看来这完全就是一个很低效率的过程。比起记忆调用链路更应该做的是抓住核心,搞明白 vue 在 diff 过程中做了哪些额外操作与优化,解决了什么问题,又或者他用了什么技巧去更好的解决某一个小问题,而不是记忆他怎么实现的和他的执行过程。哪天这套链路被推翻了,不是又得重新记忆一遍,而且也没法抓到其思想真正的精巧之处。针对这种话题我认为的一个理想状态是,学到他的思想,然后能用自己的话讲出来,又或者基于思想自己实现一遍,并针对自己的实现对比官方的实现,有哪些不足或没考虑到的 case,又或者哪些地方实现的比官方好,以及下一次实现时该注意什么地方。eg. 这里如果是我来聊,那么我会写一个类似 lodash 的 isEqual 方法,并基于这个展开 vue 做的额外操作:如果对比 children array ,其内部有 key 则走精准 diff,这里我使用 map 实现它,否则开始解释最核心的 递增子序列算法;为了优化这个 diff 过程,开始列举 vue 在此之上做了什么实现:编译期确定静态节点,抽离到组件外部复用;对于过长的静态节点直接上 innerHTML;使用 shapeFlags 跳过大量的对比... 内容还是很多的,但他们的核心都在于抓到了实现后能解决的问题和带来的成效。 感谢许多与我一起合作过的同学,感谢我的 mt,他一直很认真的review我的代码,擦屁股时也没有斥责我;也感谢 ld,在我迷茫的时候去开导我,让我回归正常的生活节奏;还有感谢同组的哥们,每天饭后散步是心情最舒爽压力最小的时刻;也感谢同组实习的哥们,他很有想法,对手头的事情有清晰的认知,他也是第一次实习,是我每天不可少的饭搭子;还有在职时所有跟我对接过的大佬们,大家都很热情,甚至会手把手告诉你原因和解决方案,沟通时大家都主动思考,快速确立各自负责的内容,遇到困难大家也不害怕,而是积极解决。 最后,希望这篇总结能够给你带来一些思考或者启发,或者是给处于迷茫/焦虑期的你点亮一盏明灯,让你找到一个正确的前进方向,从而走出迷雾,做回真正的自己。

2025-04-25 - Shiina

我的2024年终总结

其实今年年末没想着要写这个总结的,但是想到一整年努力没有给自己一个交代似乎又有点可惜。现在想一想能写的东西似乎很多,也似乎很少,很多是因为产出了不少实质性的东西,很少是因为从来来回回就做了那些事情。但是我觉得最幸运的还是说走出了舒适圈,去见证了一下不一样的世界,也认识了一些很优秀的人,学会了一些话术与沟通的技巧,明白了什么叫总结与精华,发展了一些特有的技能。 这一整年做的事情都很简单:重构,新功能,重构,新功能,最后是面试,遇见了不同的圈子的大佬,以及更多的大佬。 时间线回顾 从年初的重构开始说起 年初寒假主要是在做一些自己项目的工作,一个是 dmv 重构计划,当时计划重构成多包项目,为的是一个方便的维护与升级,以及未来的发展做铺垫。其次是我的 qq bot,现在官方虽然已经开放了自己的 bot framework。但是听说很烂,不是很好用;且我现在没有精力去重构他。 就 QQ bot 来说当时寒假主要做的一个事情是:重构 runtime core,支持多环境配置开发,支持开发热重载,支持 app 实例管理模式(类似 vue3),且内置限流和黑白名单管理控制,为什么要做黑白名单的原因是 bot 曾经遭受过脚本小子的攻击,没有做限流管控,导致签名服务(qq 消息特有的一个机制)经常崩溃。 dmv 的话当时直接上手重构多包,结果由于没有规划而导致重构的时候做了很多白费功夫的活,但是经验倒是攒了不少,且对旧代码重新进行了一波规划;以及重构的代码大部分都采用了纯函数编程,这也使得后续迁移的时候方便了很多,大部分逻辑仅需 cv 而不用考虑太多副作用。这是比较值得欣慰的一个地方。 其次就是寒假旅游,寒假旅游了一周,就记得去了虎跳峡,其他都是寺庙,体验一般般 但是旅游前有个哥们提出说能不能给生息演算做个 3D 地图,当时刚好对于我来说是一个新鲜的体验,于是用了不到2周时间直接从 0 开始搓了出来,并附带一个网页编辑器 + 文档,供地图制作,项目链接:https://github.com/QingXia Ela/reclamation algorithm map 还有现在急招接班人,我已经没啥时间去更新项目了(悲) 开学后学到的东西 我觉得这学期唯一开心的事情可能就是接触到了 OS 这门课,虽然学的一知半解,不过部分概念还是记住了,包括锁,中断,分段管理和分页管理,虚拟内存,地址映射,硬盘日志,进程与线程等内容。希望未来能在 35 岁前用 rust 实现一下属于自己的 xv6。其他课我都不是很喜欢,web 过于注重表层和 ui,数据库全是可以靠文档自学的 crud,没有讲过底层算法。软件工程不好评价。而且很难受的是这学期 5 月整个人湿疹很严重,当时几乎全身上下都有溃烂的地方,一直到六月中旬才好起来,现在想想也有可能是因为当时51放假结束,一周4个5k字实验报告 + 后续连续的实验报告和考试,压力属实是拉满了。不过还好后续就调整过来了。 最遗憾的是学期末的硬件实践,本来小圈子的哥们都鼓励做 cpu,但是考虑到稳健和速通还是去做 timer 了,所以饼画在这里了,就看什么时候填完。 暑假 最累的一集,这个假期我把旅游推掉了,一个原因是要准备简历项目,另一个原因是之前旅游真的很不愉快,让我有点阴影。 整个暑假除了塞壬唱片播放器,就几乎都泡在在线编辑器的研究中,包括协同理论与实践等,每天强迫自己进行产出,同时还把之前塞壬唱片桌面版的坑填完了。从回家开始算连续 45 天几乎都没有停下来过,每天保持一个产出的水准,代价就是整个人很累,很累,直到后续朋友约出去玩了三四天才勉强有些放松,最后赶在暑假结束前将项目收尾并上线了第一个基础版本,虽然细节上我不太满意,但是整体上大致达到了预期效果 大三上学期的冲突与希望 这里的冲突指的是学校课程与项目的冲突,这学期有一门编译原理的课我很喜欢,虽然讲的很浅薄,但是其多多少少给我留了个概念;其次是计算机网络,老师讲的很浅,也是应试教育,但是我想深入学学,因此去额外找了些资料,但是目前还没有全部看完,计划未来是看看 http2 和 3 的 rfc 其次是 9 / 10 / 11 月基本都在继续沉淀项目,继续优化细节,主要是为了丰富简历内容和提升健壮性,然后就是看八股什么的,迷迷糊糊的就到 11 月底了。然后就是面试生活。 面试实习 见 $1 刚面试那会也注册了牛客,疯狂刷面经和八股,每天看各种帖子焦虑和羡慕别人 offer,但很幸运的是面了这么久腾讯终于在年末发了一个 offer,给了我一次见识世界的机会,我一定要好好珍惜他。 未来的目标 短期: 回归我的项目开发,去到一线体验当前写词条的痛点与问题,并提出可能的解决方案 最近有哥们想研究 mc 对接 gpt 做点小玩具,看看能不能寒假内给他做好 继续学习 xv6 把入职手续准备完,跟 mt 提前聊聊要学什么,有什么要准备的 准备开启实习生活 继续练吉他 长期: 在实习中确认自己想要的东西 想清楚未来要做的事情 坚持学习英语 保持独立思考 EOF

2025-01-03 - Shiina

我的秋招实习之旅

我的秋招实习之旅 本篇主要记录的是个人在 24 年年末找日常实习时的一些面试经历。同时也是一个对自身目前发展情况的检讨,算是给自己的学前端这么久留下的一个交代吧。 先说一下背景:双非,目前在读大三,主要做的就是前端开发+基建和项目管理,目前 (2024/12/31) 无实习经历,所有投递都是从官网投递,无内推。 简历大概投了大概一个月吧,从 2024 年 11 月底开始投,再到现在也就微信,字节和一家外企(RightCapital)给约面,之前看别的佬的面经说内推可以直接推到部门 ld 去,所以内推也算是一个优势之一,网申就经历了不少初筛挂,总之很难受就是了。 通过不同公司几场不同的面试是可以感受出每家公司风格都是不太一样的,字节给我感受最深的就是写题写题,除了搜索岗3面没有做题,其他都在做,而且都是 3 题起步。而微信的话感觉是不同部门风格也不太一样,之前有人说上来就是先做题,一个小时起步这样子,但是面微信游戏的时候没有这样做。而公众号&小程序一面的时候就是这样,当时给我整懵了,不过写题也有个有意思的点就是更多都是场景题,还是挺有意思的,尤其是 glob 库简单实现的时候,这个库我在 astro 源码就看到过,他被用来获取内容集合所有 markdown 文件。而 RightCaptical 的流程分的很清楚,第一次是基础考察,第二次则是问项目以及思考,第三次则是知识边界探究,体验还是很不错的。 现在再想想玩的还是挺大的:上来就面全中国最难的几家的岗位。但也确实没办法,因为其他公司应该是坑位都满了,要么初筛挂要么没有回复,如果抛开面评来说,我反而觉得每次面试都是一个很好的机会,原因如下: 我能有机会去跟企业中的神犇们去沟通和探讨我的想法,一个是,我能借这个机会去反思我项目可以提升的地方,项目 mvp,还有如何决策等问题;其次是我能借一些反问机会去了解不同业务承担的职责,去督促我思考在真实企业场景中更多需要考量的因素;最后,能聊技术和实验室经历真是太开心了(逃) 废话不多说,下面是正文: wxg 游戏实习 这是作者本人第一次面试时的岗位,当时整个人很紧张,甚至提前一天进了会议上传简历,正式面试开始前20分钟就进了会议室,不过面试官也提前两分钟就加了进来 总共三面,都是视频面试。而对这一次面试的总结就是:需要巩固基础,需要主动抓住面试主导权,并以简练的话语展示这个项目可以深入细究的地方,去体现出自己思考的点,让面试官感受到自身对项目的认真态度 现在想想这几乎简直就是表现最差的一次,很多做不好的地方都是在事后才意识到,但毕竟是第一次面试,还有很多可以成长的空间,慢慢来吧。 一面 面试官人很好,整个面试过程中就像是聊天一样,全程演示项目,中间穿插了一点八股。 后续想想这也是一位很好的面试官,愿意一点点看我项目的细节,还有用的什么包,为什么选他,目的是什么,解决了什么问题,真的是一点点引导。反问聊部门业务的时候还很认真细心的介绍了部门的职责和业务,体验真的很不错。 蓝桥杯是什么 问简历上的项目是实验室还是个人项目 面试官说都会把比赛项目给放到前面,所以以为这也是实验室作品。然后我就拿了挑战杯写的前端页面简单说了一下 以下基本都是项目细节: Mod 开发组与你是什么关系(甲乙方?) 为什么分了开源核心 + 后台仓库(后台仓库代码不安全,需要审查) 编辑人员提交流程(后台编辑 + 管理员提交 gitee pr + 审查后合并 + webhook 触发 cicd 同步到 oss) Astro 是什么,SSG SSR 是什么(说了一下基于 vite 进行驱动与支持 ssg + ssr,然后说了一下 ssr 的动态拼接字符串;然后面试官说了什么 jeklly?) 选了他的原因是什么(博客落地实践过,知道一些底层原理,内容驱动生成网站,符合 wiki 定位要求) 框架可以插入 react 或者 vue 组件吗(可以,且可以一起使用) 有试过放在一起吗(没有,提了一下 vite 放在过一起导致开发声明报错,其次是两个应用相互独立,通过各自的 app 创建函数来渲染页面,只要他们副作用不会相互影响我觉得问题都不算大,不过现在看来感觉还得想一想 vue react 底层,他们的更新机制不一样,会不会一个框架的占用线程太久导致了另一个框架更新不及时) 编译器和 polyfill 的关系,知不知道每一个 es 版本的区别 整个项目内核升级是什么意思(说了用插件将所有的逻辑进行封装,最后进行复用,要求展示了一下除了简历还有哪个网站复用了) VSCode 插件展示一下,具体在 VSCode 做了什么,用途(mdx 转 ast 语法树,对节点进行分析,并读取工作目录下的资源进行查错;给一些编外的词条编辑人员使用)? 网页插件展示一下?(没实现,说了一下对每一个用户都要开一个专用检查进程的原因) 看一下你的分析器和 mdx 官方分析器的关系(完全独立,没来得及说存在的优化部分) 本来要进笔试了,然后说了一下 yjs 是核心之一 在线平台演示效果 yjs 是什么(协同编辑中编辑冲突的一个库) 协同主要问题(说了并发冲突和 YATA 算法的作用,面试官似乎没做过这个领域) 笔试: 反问: 工作时间(上午十点到晚上八点半) 地点(深圳总部) 实习时长(越久越好) 技术栈(挺多跨端技术的,感觉进去又要开始上手新东西了) 有没有什么可以改进的地方 下一面几天后(最晚一周后) 总结:需要回去 总结好项目重点,针对每个重点提炼一套要点内容 ,而不是想到什么说什么。其次要梳理清楚项目的一些实现。 说个趣事:我在这次面试后看了一下项目,发现自己亲手配了 babel 去实现一个低版本浏览器的提示代码转换。还有一些 polyfill,但是都由于太过久远而忘记了 不过项目本身很大型,因此记不住所有细节也是正常的。因此在二面前一天我疯狂地看我项目的各种细节,就是为了能好好的聊项目,不过二面的计算机基础拷打给我来了个措手不及 二面 老家是哪里的,还有住在哪,学校在哪 说一下数据结构栈和队列,他们的区别,栈在哪里有应用场景,队列,然后假如队列发生了插入,那么此时这个队列变成了什么,具体应用场景有什么 先说一下 localStorage 大小 然后引导到操作系统页置换算法,要求写一个按字节数大小计算的 LRU 缓存,问了一下时间复杂度,有没有什么可以优化的地方 计算机网络(七层模型,常用的四层),每一层帧封装的格式,知道的越多越好。到传输层后问了一下 udp 的校验和是怎么做的(忘了),应用层有哪些协议(http,ftp,就记得这两个) 说一下项目大概的情况 看一下你项目的架构图 你的项目最终为了解决什么问题,相比其他 wiki 第三方平台有哪些优势 看你 wiki 用 astro,性能是不是很好,跑个 lighthouse 看看(第一次不给力,才89,第二次才满分),那么就结果来说你能信任 lighthouse 吗,最好的收集用户数据手段是什么(埋点),埋点的话你会怎么解决(就目前个人能力可能会找 google analysis,现在想想应该回答一下如果能接受就找一些第三方埋点包,评估并进行引入) 反问 我需要改进的地方 这次实习是有考虑提供转正的吗 如何提升项目积极性(一个是正反馈,还有就是当你的代码面对千万级用户时你该怎么办) 聊了一下跟踪脚本,现场出一个场景题,假如要拦截该怎么办(https://developer.mozilla.org/zh CN/docs/Web/HTTP/Headers/Referrer Policy) 看一下你的项目文档 以为这一面会继续拷打项目,为什么没有深入细节 平时怎么学前端的 一面是主管吗 有因为学历而考虑考研吗 总结:需要回去 巩固基础知识,复习计算机基础 ,以及一些核心开发必须要知道的八股文 在面试前一晚我一直在实验室的小会议室复盘和总结我的项目,就是为了第二天能好好的一点点细讲,结果来了这样一出,属实是有点倒霉,不过还有一点就是信息差,就是微信可能更喜欢问一些计算机基础,可能大部分面试官也是写 C++ 出身的,这点也是在后续跟哥们聊天时才知道。 那天晚上面完后我一直在反思,我真的是热爱计算机吗?其实这个答案其实以及很明确了,我要是不喜欢我就不会坚持这么久,也不会因为说因为学历就想考研,而是努力提升自己的硬实力和能力,更不会说在上学期学操作系统时去看 mit 的实验课,并尝试自己去一点点去做完,还有这学期的编译原理也是。如果未来允许,我希望我能在 35 岁前用 rust / c 在 riscv 电路板上跟着课程实现一遍 xv6;其次是用 rust 实现 bellard 先生的 quickjs js runtime core。 不会东西不可怕,可怕的是不会还不想着去弥补和保持上进心 按字节计算的 LRU 自己写了一份,简单测了一下,似乎没问题: 可以继续优化吗?也许,比如搞一颗搜索树,用来快速查找哪个节点之前所有的节点移除后能够满足空间要求 三面 自我介绍 说一下项目 问到静态网站的时候拷打了一下 CDN 是什么 网站访问量高吗,有多少人在用? Astro 框架是你自研的还是第三方的 八股: http 每个版本的区别(只说了 2.0,本来想讲 1.0 的一些 chunked 机制,但发现自己记不清那个头是啥,索性就不讲了,3.0 知道是 udp 和 google 研发) 缓存(结合项目的 html etag 协商 + vite 打包 8 位 hash 说了一下,但是面试官不是很满意) 反问 需要改进的地方?(反问了你从这个项目学到了什么) 阅读了部分 Astro 源码(content collection 与 vite 结合的底层实现,知道了可扩展性和局限性,翻阅了 RFC 文档,知道了其开发目的解决的痛点,最后评价是又好又坏,好在对 mdx 的处理工作是在编译器完成,在运行时无过大开销,缺点也是 mdx 在编译期间处理完成,没法应对更灵活的需求;其次讲到了 Astro 上周第 50 个 RFC 文档,github 可查 content layer api,也是不把运行时编译列在目标内;所以评价是又好又坏) 深入研究了 CRTD 思想及其背后的 yjs 生态库(从小团队开发比重权衡选择了 yjs,生态丰富,且配备 demo,体验很不错,尤其是周边库,源码内容简单,要针对做定制开发的成本也比较低) 面试官主动问了一下有没有了解 OT (对比了一下 OT 与 CRTD 的区别;他与 CRTD 解决的目标相同,不过思想核心不一样,OT 是保证过程顺序一致,CRTD 保证数据一致性,颇有分布式思想的感觉;OT 在生态上较为薄弱,调研了 ShareDB 实现,发现后端代码过于复杂,对于小团队开发可能时间并不充足;我的中心服务器性能不够的话可能导致体验下降;针对不同数据模型要实现不同接口,开发成本增加) 了解了一些 vite 的短板(生产环境与开发不一致,不合理分包导致模块循环引用(上周优化时发生的),首页白屏的问题(vite 仅仅经过最简单的转义便直接把模块发送给首页,没有像 rspack 一样做一个合并优化,导致项目变大时首屏发出大量的模块请求,且 vite 开发服务器 http 协议似乎是 1.1,只允许 6 个 tcp 请求,其他的会被阻塞,进而导致长时间白屏)) 实践了一些设计模式(模板模式,策略模式) 站在了开源包使用者的角度去看待一些内容(包下的语法分析核心分了两层设计,用户可以选择最简单的 plugin 模式去定制规则,也可以自己创建 core 实例去完整覆盖 mdx 的检查行为) 总之做这个项目就是很开心,学到了很多也收获了很多 您是 GM 吗(不是) 平时玩什么游戏,但是当时脑子有点短路答不上来,就说最近玩的比较少,会练一下吉他 虽然最后隔了几天收到了流程结束的信息,但也是从这一次面试后,我就意识到了 必须要主动争取面试主动权,面试官给出机会时一定要有意识,抓住项目核心讲,并引导到自己熟悉的领域 ,因此后续继续优化总结,把项目最重要的几个核心抓了出来,并进行了提炼,因此一天后的字节二面我收获了一个非常好的体验 字节跳动前端搜索方向 这是作者第二次面面的公司,一面就在 wxg 游戏部门隔了一天后。总体感觉这个部门方向挺综合的,感觉是业务和基建都有点?问问题的风格也和后续面的商业化部门不太一样,不过可能因为面评或者侧重点的不同,导致两个部门面试的风格不太一样,不过基础拷打还是差不多的 不太理解就是最后审批挂了,很奇怪,当时收到这个消息冷汗冒了一身,因为当时还在招聘网认识了一个同部门的后端哥们,都加了微信了,还聊的很开心,很憧憬实习后的合作。二面面试官也加了我,想跟我继续聊聊探探底,结果来了这样一出,真的是来了个措手不及。 当时甚至很长一段时间都对自己的实力产生了一些怀疑,甚至开始从头复盘,到底是哪里不对。最后看下来觉得就是一些项目表述可能太过于啰嗦和浪费时间;其次是可能跟部门业务 baseline 有一些冲突;最后可能就是这三面都没有完全确定我是否符合他们的标准,当然这个可以通过加面解决,就是时间成本还是有的。 不过也没办法,明天和意外往往都是意外先到来,所以当时沉默了一会后马上开始继续往各个网站投简历,如果不行动起来去改变一些什么那就只能挨打了。 吐槽一点:大部分面试官都是只知道 acm 的,蓝桥杯没啥用,所以以后自我介绍我绝对不会主动说了,除非面试官主动问 一面 自我介绍 蓝桥杯是什么 问两个开源项目: Threejs 那个怎么说(2年前的项目了,根本不记得多少,扯了一下新版实现,模型优化,看了一下源码解决bug) 某音乐网站嵌入 tauri 二次开发(扯了一下写的 vite 插件,实现了把外部网站嵌入到脚手架内实现的直接开发,还有重写部分热重载代码,以及代理后端,实现内容覆盖与整个网站的控制权,以及扯了一下这种跨平台开发要注意的是什么,然后就扯了一下ipc通信与序列化的性能) 做了这些插件最终的意义?(提升开发体验与效率) 这些是自己做的还是实验室做的(第一个跟隔壁实验室哥们一起做的,第二个是自己做的,2023年7月 2024年8月,有GitHub提交可查) 说一下你对前端工程化的理解(尽可能地实现非业务部分过程自动化,使得开发者可以专注开发) 用过webpack吗,没有,直接 vite 上手 说一下你对 vite 的认知,越多越好,尽可能地说(esbuild 开发环境,rollup 生产环境,vite 在加速方面做了哪些努力(esbuild 构建开发环境js,预构建依赖,对源码更新采用链失活处理(仅概念))) esm cjs(同步与异步导入,import 静态分析) url 到页面呈现(合法判断,cache,dns,tcp,dom树,cssom,js 阻塞,render tree,绘制,部分 css 送入 gpu 处理) 说一下用 Astro 的原因(vite 作为底层驱动支持,内容驱动静态网站生成,支持SSG,SSR) 除了 SSG,SSR 还有什么渲染,区别是什么(ISR,CSR,增量静态生成) Astro SSR 还有哪些应用场景(扯了一下官网文档的电商平台,用户可以先看到页面商品内容,具有交互性质的按钮可以在后续注水激活) 说一下 yjs 是干什么的(以CRTD为核心思想的并发冲突解决库) 在线演示平台,平台有多少人在用(不多,给内部人员编辑使用) 做这个遇到最难的地方是什么(服务端崩溃上下文丢失后内容恢复,说了目前的实现与未来最好实现) VSCode 插件看一下效果(演示了一下并说了转 ast 做处理的简单流程) 笔试第一题: 笔试第二题: 笔试第三题 有一个树: 现请你遍历该树,并在到达叶子节点时将其前方所有的值拼接为数字,对于本树就是: 124 + 125 + 13 = 262 本来要反问了,感觉节奏不对,继续跟面试官扯完了简历上的后两点: 页面预览实现? 成本有点高,目前思路是转发脚手架页面 曾经做过的努力: 用 astro 的编译器看看能不能 build 一些组件并拼接完整页面(不能,必须依赖 node 环境或在浏览器实现需要的 api) 用 SSR (审查了 astro 部分源码发现对于 markdown 编译逻辑都是写在 vite 插件内,打包时是直接把 markdown 编译成 js,SSR执行时直接静态出字符串,没有运行时编译过程) 11月14号新出的 content layer api,去官方文档看了里程碑,不把运行时编译 markdown 放在目标内,与 astro 的 baseline 与解决问题场景不一致 jsx 编写通用组件? 曾经做过的努力: 调研 tinyMVC,在示例仓库里发现他针对各个框架都写了一套 renderless 逻辑,还为此写了一个专门抹平框架差异的函数 taro,基于编译器实现,背后有编译团队,运行时团队,小程序团队和跨平台团队支持,对于小团队开发成本太高了 反问: base 北京上海 二面什么时候 主要业务?负责抖音头条等搜索处理 需要改进的地方? 总结:需要增强自己的 自信心 ,项目都是自己做的,没必要慌。面对需求时保持冷静,去一点点拆分问题,并解决它 其实有时候也能理解为什么有些同学会请人进行模拟面试,有过模拟面试的话多少都能锻炼一下口才,也不会说更紧张,而是能做到从容应对 二面 省流:无八股,四十分钟项目输出,二十分钟笔试题 + 反问 面试体验最满意的一次,虽然开头细细的讲项目细节导致节奏有点慢了,只讲出了两个核心,还有两个核心没讲,但面试官很耐心的听完并跟我确认上下文细节,下次继续优化 自我介绍 挑一个简历上最值得讲的项目开始表演 背景介绍(某游戏 mod 开发组前端成员,主要负责一些页面制作宣传的需求,后期组内其他成员提出 wiki 制作需求,开始了调研之旅) 主流 wiki 框架(语法晦涩难懂,开发者需要时间去学习成本;使用 mdx 可以无压力上手 + 需求/问题快速沟通解决;Astro 我有实践经验,阅读过核心 api 源码,知道底层实现与扩展/局限性) 反问了一下这个项目什么时候开始做的:第一版落地时间周期(去年5月调研,7月开始第一版开发,9月落地,到12月前长期维护 + 新功能上线) 第一版落地后遇到的问题(项目结构混乱,非业务核心代码与核心混在一起,网站无法进行复用) 解决方案(采用 monorepo,重新梳理整个项目业务核心逻辑与周边生态逻辑,进行归类划分并确定职责和要暴露的接口) 成果(项目职责分离(解包,语法检查,wiki 核心,组件库,针对不同 ide 的检查适配器)对整个项目有了个更好的认知,知道整个项目的进展和状态) 带来的新问题(此时已经半小时了,面试官让我挑2点最大的问题(不同包之间没有权限区分;一些历史遗留插件没法及时迁移,付出了一定开发成本)其实这里可以讲一下代码复用,参考了 Astro Starlight 项目落地后发现全局 Astro 特性被局限至仅 集成暴露 api;部分 api 使用后效果不一样(Astro 官方给出了解决该问题的实验性特性)) 网站访问量多少(不多,算是技术能力锻炼产品和圈子内的服务用产品) 是不是 minecraft 的发烧友(还真是,高中就喜欢玩珍珠炮,并且从里面开始接触到编码解码概念和一些二进制理论) 笔试 版本号排序(后续讨论了一下健壮性和 plus) Promise.all 实现 写一个后台管理系统的侧边栏组件,伪代码即可(顺便聊了一下 vue compiler 的 props 宏展开) 本来还有第四题,面试官说不用了,直接开聊(以为会问 Promise 顺序,他说他不喜欢考这些,然后聊了一下 Promise 内返回 Promise 的问题,涉及到 v8 以及 ecma resolveThenableJob 规范,不过面试官似乎不是很了解这里) 反问 我需要提升的地方(计算机四大件别丢了,讲的很认真) 部门主要技术栈(react,然后就是要了解一点 node,不用做开发,nginx了解即可,吧啦吧啦的,后续忘了) 新技术会用吗(会做研讨会和研究,不过更多是基建部门负责,他们会看手册学习并尝试在小项目落地) 主要业务(搜索中台,技术 + 业务结合部门?面试官好像一时也没法彻底讲清楚) 部门压力大吗(不算大(真的吗)) 入职要注意的事情(需要两个月进行磨合,因为有些事情可能没有给到完整上下文就让你做,需要自己翻手册或找 mentor 问,流程清楚后就轻松了,后面一堆不记得了) 转正?(会给,但是看分到的名额,说25届留了两个实习生,刚好两个名额就全给他们了,然后细细的讲了一下转正前会给你的各种通知和要做的事情) 就面试来说有啥需要改进的地方(笔试侧边栏组件你可以做的更好点,抽象级别可以更高点,加强一下基础框架学习使用) 体验最好的一次,唯一的遗憾就是讲细节太多了,还有一些核心没讲出来。其他我都很满意,1 小时后收到了三面时间选择通知 许愿三面能遇到像这样体验这么好的面试官 三面 自我介绍 为什么学前端 什么时候开始学的 看你项目还挺多,挺多方面都有涉及的,node 学的怎么样(仅基础,rust 写的那部分后端可能还多点) 平时怎么学(从实验室给的路线发展到自己看文档查资料,会主动关注新 api) 关注新 api?举个例子(用我博客的 content collection api 举例子,翻了 rfc 文档,对着英文生肉硬啃) 最近科技周报看了啥,举个例子(rspack,阮一峰谈发展 ai 的公司,还有自己想在项目落地实践 ai) 为什么想要实践ai,你是想在自己项目的哪里实践?(原来的开发者想更专注于核心开发;词条内容编写,让 ai 写雏形,自动生成框架,我们按需补充(其实有个点没谈到,就是有些内容需要编写者阅读过源码才知道机制,ai 写可以节省一部分时间;其次是语义检查,看看是否符合人类阅读习惯)) 看一眼你的后台(演示了一下基本内容,是 monaco 做的) 讲一下选 Astro 的原因(调研现有 wiki 框架发现不适合,学习成本高;横向对比 VitePress VuePress,局限使用于 vue,扩展性开发难度较高;从 Vite 或者 Nextjs 开始写的话基建要做很多东西,一时看不见效果;页面样式自定义要求程度非常高,css 几乎都是手写;Astro 基于 vite 封装,帮我们做好了很多事,且具备 vite 大部分能力;阅读过内容集合 api 源码,知道扩展性和局限性(其实还有很多可以说,不过脑子一热忘了)) 有试过什么优化手段吗(开始拷打) CSS 规范,强制要求所有元素尽可能有个固定宽高,避免 CLS 某些显隐采用 visibility + pointer events 处理,避免重排 后台部分使用 分包(面试官让我打开项目看看分包结果,然后就对着页面的请求在那里讲自己的分包思路) 接下来从开发过程,打包编译,网络传输,首屏展示四个方面聊聊你知道的优化,越多越好 开发过程扯了一下 vite 全局定义 变量,然后把仅开发逻辑放在这里头,编译过程会移除(其实可以再讲讲引入路径规划,做一个强隔离,项目后台就是对每个页面进行强隔离,保证逻辑无关联,这样分包函数可以针对每个页面打包成一个 css + js,避免过多网络请求),还有 await import 作为分包点 打包编译讲了 terser 的上下文分析,分析 dead code 的存在和不必要的逻辑进行移除;其次是避免桶文件 + rollup 静默打包(桶文件在项目中真实出现过,打包整个 mui icon 导致打包时间 + 2min,面试官当场提问最终这些会被打入包内吗(不会,会做 tree shaking);静默输出则是因为 mui 组件都写了 'use client' 导致 rollup 警告大量占用控制台输出间接导致打包时间下降,面试官继续提问如果我不让你用静默怎么办,见我不知道就说了可以写插件去直接替换底层方法,不过感觉不算太严谨(逃));聊了一下通过插件移除指定注释下的代码(类似 rust 注解)(其实可以再讲讲语法转换,即向低版本的 js 代码进行兼容处理,即 tsconfig 的 target 选择) 网络传输用了项目从 http1.1 升级到 2.0 避免一个队头阻塞的问题(顺便牵扯到 tcp 阻塞,讲了一下前面的包没到后面的都得等),还有 3.0(其实可以扯 2.0 请求无序 + 服务端主动推送和资源优先级控制,还有 CDN 等,但当时脑子笨想不到) 首屏的话则是聊了一下 script 标签的 async defer 去避免 dom 解析阻塞,还有内联资源,扯了一下 tcp 拥塞控制的一个算法算出来首屏 css 控制在 14.6 kb 内,不过没讲出原理;顺便聊了一下我的博客,他的夜间模式 js 是放在 async 内执行的,面试官马上知道了会有闪烁问题,然后我就说在 html 前面写了一个阻塞 script 去修改 cssom 树,避免了闪烁 场景题,现场设计一个 PC 登录扫码功能,PC 要有消息同步功能(1. PC 向服务器请求登录 token 并展示到二维码内,随后使用轮询或者 ws 等待状态 2. 手机扫码,获取 token 后发送到服务端,服务端改变状态 3. 通知 PC 可以登录了,由 PC 主动去请求个人信息)(中间扯了中间人攻击,包阻断,重放攻击;根据操作系统生成唯一标识符,mac 地址等)(感觉最核心的还是各种安全细节和登录成功后的消息同步功能,如何保证数据一致性) 最后十分钟学习 IntersectionObserver,现场投屏写一个应用(前面聊了一下图片懒加载跟面试官说使用原生 loading lazy 和缺陷,面试官就反问有没有用过 IntersectionObserver(没有);最后没写完,但是面试官看完思路说大致没错,改改细节就可以了) 反问 是日常实习吗(是) 您负责的内容(leader,项目负责人) 部门主要业务(搜索中台 + 大模型,顺便提醒我可以去学习一下看看真实项目怎么落地的 就个人来说要怎么继续提升自己(去一下更大的平台,学习一下企业是怎么管理的,以及整个 workflow 的实现;就我的项目举了一些例子,我自己一些自研的地方其实有插件去帮助实现) 压力算大吗 实习时长 面试有什么需要改进的地方(还可以,主要是有自己的特色) 1 小时后 hr 约明天面,应该没问题了吧? 总结: 体验下来还是很不错的,唯一遗憾的是总是忘记还有更多内容可以讲和远程协同讲不出来(怎么每次都是这样啊(恼)) (我的项目还是太大了(雾),仍然有很多东西可以继续细分,网络优化我自己亲手配置了 gzip 优化,而且还对他设想过一些未来(低于多少 kb 后就不压缩,直接传输,考虑这点是因为小内容可能冗余数据比较少,压缩后的压缩率并不高,且在运行时客户端也要解压缩,会有一定的消耗,但是具体消耗还是要靠用户侧数据收集以及benchmark去确定)) 后续假如 oc 了我会把项目总结文档开源给大家学习,毕竟可能到后面面试就基本都问实习了,这个项目就面试来说可能发挥不了那么大的作用,但是他在我心中依然是最好的项目之一,因为他沉淀了我一年半这么久的思考,不能就因为面试结束而结束使命 后续 挂了,hr 说不方便透露原因,运气有点差 字节跳动 商业化 这里是字节在牛客捞的简历,这里能很明显感觉到风格不太一样,全程逮着问基础,项目就是几句话带过。应该是面试官看了面评吧,知道项目应该是够了,所以想看看各方面基础怎么样。 这些对于经常做业务的同学应该是很容易上手的,但对于我来说可能就有点吃力,在过去的3个月我几乎全身心投入到远程协同的研究和开发落地中,因此在这方面就稍显的有些劣势,但好在面试官问的这些我基本都能答出个七七八八,对于一些底层部分也有自己的见解和认知 一面 自我介绍 项目背景 react 事件处理机制(16,17的不同以及为什么这么做) http 缓存,以及应用场景 react,看组件说输出顺序(元素本身挂载和 react 事件挂载,事件触发后输出顺序) this 指向(几乎所有情况) 事件循环模型 宏任务微任务有哪些 Promise 输出(比较简单) 并发数量控制 全排列 反问 二面 隔了一天就马上约了,不过当时我要回家,就约在了回家后第一天,也算是第一次在家里面试 自我介绍 怎么学习前端的 更倾向于基建还是业务部门 最近学了哪些新知识 vite 与 webpack 的区别,优缺点 esm cjs 为什么项目升级成 monorepo + pnpm monorepo pnpm 优势 git merge git rebase 设计模式 观察者和发布订阅的区别 对 fiber 的理解 react hooks 解决的问题 useEffect useLayoutEffect 看一下封装的 hooks 你作为实验室负责人,怎么做技术选型的,策略是什么 成员积极性不高,或者能力不足该怎么办 手撕:给数字增加分隔符(1234567 1,234,567),合并两个有序链表 反问 部门具体业务(CRM) 期望入职时间 还有几轮面试 改进的地方 整体聊的还是特别开心的,尤其是讲到最近看的科技周报与一些开源事件(rspack投毒)时聊了很多想法和看法,还有实验室经历和我做的一些决策,以及带来的效果 不过可能是因为业务不匹配的问题,两天后收到了感谢信,跟哥们复盘的时候觉得可能是话术不对 总结:可能在话术上需要有一定的谨慎思考,如果下定决心想做基建的话那就直接去投基建岗。面试中我也可以有意识的问问,这样我能确定这个部门主要做的是什么,后续有这样说选方向的问题我就可以根据一个之前获得的上下文来确定面试官想要听到的答案 RightCapital 当时是微信游戏挂了两三天后约面的,有意思的一点是 hr 多多少少也知道前端的一些东西,硬控我 20 分钟,甚至聊了点 react vue 框架,我怀疑 hr 之前就是做前端,想逗逗小孩子罢了(逃) 面试给我的体验还是很不错的,没有做题,没有手撕,更多是看你对技术与项目的思考,是否有自己的独立想法,还有探测知识边界,虽说就深度来说肯定是没有大厂那样厉害,但就一些基础知识也能聊不少东西 不过唯一的遗憾就是工作地点在北京,其次是进去后可能要先做一些测试工作,而且同期还有 wxg 开放平台在等开奖,虽然作为人生中第一个 oc 还是挺开心的,但是由于工作地点的问题。所以到最后还是忍痛拒了这份 oc 一面(45min) 隔了几天才想起了博客没有补充,记得不是很清楚了,将就写写 业务介绍,入职时间 什么时候开始知道和学前端的 Astro 框架简单介绍一下 用 pnpm?说说项目分包的好处 讲一下 git rebase,平时怎么解决 conflict 的 用 React 还是 Vue 多 用 vite 还是 webpack 多 他们的区别以及优势和缺点 ts 学的怎么样,讲一下几个常用的工具类型 如何在类型体操内实现 if 和 for 循环 React 新特性了解的怎么样 React 新 hooks 实践过吗 jsx 编译后的产物是什么 讲一下代数效应 看一下你项目封装的 hook AbortController 以及调用时机(考察副作用清理) 知道有哪些设计模式 对测试了解的怎么样,编写测试时要注意的点(e2e, vitest) 英语水平,给一个文档能看懂多少 反问 除了 react ts 还有什么技术栈 本次面试出结果的时间 主要工作 需要改进的点 二面 (40min) 面试的是部门 ld,一位很稳重的大哥,能感受到颇有强者的气场,这次就项目提问了不少内容,很多开放性的问题可以探讨 自我介绍 说一下项目里最难的点 为什么升级成 monorepo 和 pnpm monorepo 适合的场景 实践 monorepo 的时候有没有遇到一些什么问题 项目的架构,怎么分包的 项目的发展过程 团队有几个人,都是自己写的吗 项目背景 astro 框架是什么 相比其他框架,astro 卖点在哪 用过 nextjs 吗 你喜欢 astro 框架吗,说说优劣 react 平时自己开发的时候有哪些规范和注意点 你觉得 ts 的优点是什么 有些工作是 ts 推导类型的修复,能接受吗 没有实习经历吗 英文文档读过吗 了解公司实习生职责吗 从哪里找到招聘信息的 需求有 ddl,能接受吗 简单说一下 tauri 项目的难点 rust 是怎么学的 rust 与 ts 的过程宏结合是什么 为什么想学 rust,你喜欢这门语言吗 vscode 插件是啥,作用? 反问 职责(ld) 业务|基建?(业务) 需要改进的地方 还有几轮面试 总结:有些复杂场景还是没有接触到,比如 monorepo 的优劣,但是 monorepo 给我的感受就像是一个工具,我知道项目未来会怎么发展,需要一个模式去改善发展了。我个人觉得 monorepo 主要还是为了逻辑分离,提升模块化程度,缺点就是依赖管理复杂,且没有代码修改权限区分。网上的答案也比较类似,比我想的多的就是测试和重构方便 / 构建部署耗时增加。不过针对后者有类似 turbo 这种工具去进行加速 三面(1h) 最友好的一集,面试官把我几个仓库的结构都看了一下。这一次面就是综合知识 + 业务能力 + 认知边界探究了。不过感觉面我的老哥可能面试人的经验不是很多,感觉比我还紧张(无端),自我介绍还是我主动提出的 自我介绍 为什么说想做基建 有给一些大型项目提过 issue 和 pr 吗,出发点是什么 假如现在有一个日历公用组件要进行开发,你该如何完成他 假如这个组件需要定制很多地方,你该从哪几个角度去考量 假如有一个组件,网络上一点资源都没有,需要你从头定制,你的出发点是什么,该怎么做一个迭代 现在有一个功能,针对他有一批库可以选,该从哪几个角度去考量选什么库 看你仓库里面有用 js 去写一些 script 运行脚本,他可以用 ts 替代吗,有什么方案,最新的方案是什么,他们之间的优缺点 刚刚你说到 bun,那么用这个工具的时候遇到过什么问题吗 v8 爆内存的可能原因是什么,有什么工具或者方法去定位(从项目实践优化再到快照拍摄,还有开发上用一些 Weak 对象处理) 有时候遇到页面卡顿,你的定位思路是什么,解决方案是什么 看你开源经历里桌面播放器项目那个似乎是 monorepo 又似乎不是,当时改成 monorepo 的想法是什么 你简历的项目也是用 monorepo,出发点是什么,解决了什么痛点,有什么新问题 webhook 听说过吗,cicd 环境中要注意的是什么,如何从安全上去考量 webhook 的使用 最近学的一些新东西是什么,了解了哪些好玩的东西 反问 团队规模 团队项目迭代更新方式 您的职责 kpi or okr 会因为 ddl 加班吗 团队会关注新技术吗 如何针对一个项目提炼一些可复用的方法论 整个面试下来耗时最多的就是组件开发考量 + 知识边界探测了,一开始面试节奏也不算好,双方就沟通上还是有点小问题,不过后续节奏好了后就很愉快,整场面试就像是聊天一样互相分享看法和注意点,整个过程聊下来感觉是很舒服的。 面完后 hr 马上打电话沟通说这边没啥问题,可以发 offer,就看什么时候方便过来。作为人生中第一个 oc 还是挺开心的,不过当时正好 wxg 在等开奖,而且技术面都过了,所以后续还是忍痛把 oc 拒了。舍得舍得,有舍才有得。 复用方法论是今年暑假提出的一个研究课题,起源于之前看别人做 react 最佳实践时总结的一个项目规划管理模式,我自己在我的项目中用 vue 的方式实现了一遍,体验还是不错的,比如页面逻辑强隔离,页面内部 store 管理,专有组件与 hooks,缺点就是可能要编写的代码内容变多了,其次是对于某个被依赖多次的模块需要做好健壮性和完整性考量 但是就我自己的项目说很难提出一套全局可复用方法论,更多是特定场景下的复用实践,这点在我这个项目还是有一些感触的 wxg 小程序 & 公众号基建 最汗流浃背的一集,当时刚好是在游戏部门挂了后几天微信打电话过来问愿不愿意面试,我说上次不是挂了吗,双方就都很尴尬的笑了一下,最后说回去思考一天再确定要不要面。当时学期也快结束了,跟几个哥们聊了一下这件事,就觉得可能是 kpi。还好当时鼓足了勇气,想着就算是 kpi 也要尽力去学到东西和表达想法。 事实证明确实不是 kpi 面,而且拷打的非常恐怖,一面面试官说看了面评知道项目很大很复杂,于是就狠狠的考察了项目的广度,以及临场反应速度。二面则是结合计算机基础深究了项目的细节,现在回想起来我都不知道我是怎么顶住面试官的拷问的。三面则是最轻松但也是最需要口才的一集,就像是在给上司讲述自己的产品,讲自己的思考以及是否存在能效提升一样 视频面两面都没有开摄像头,就最后 hr 面开了一下。 最后实习 oc 也选了他,首先是因为没几个能选的,同期的就另一个外企发了offer,地点在北京,往返比较麻烦。主要是技术栈为 js 和 rust,还是基建岗,感觉还是比较符合胃口的。 我对这次面试最大的总结就是:计算机的基础思想很重要,许多地方都可以用上他。理解思想,并把它融入到自身作为一个工具使用。就好比我前文提到的 monorepo 和 react hooks 一样,我感觉就像是把他融入到自身,他是一个工具,理解他在什么时候该发挥什么样的作用 其次还是基础,一面结束后复盘了一下八股,答得真的是稀烂,寒假还是要恶狠狠的弥补啊。 一面(2h 30min) 上来先四道英文题目手撕(1小时 + 20 分钟思路拷打): async pub sub 依赖解析 爬楼梯 glob 库实现 八股: 事件循环 异步任务的作用 setTimeout 浏览器底层实现 JS 内存管理(v8 回收,但是讲的不是很清楚 引用计数 weakMap 以及为什么不能遍历,以及只能用引用数据类型做 key 对 ts 泛型的理解 rust 用过什么异步框架(tokio) rust 内存管理(drop trait,作用域,无GC) css 媒体查询 git merge 行为(只知道合并成一个提交,面试官说还有一些其他行为,后续看了一下是 fast forward / 无冲突 merge / 有冲突 merge) 约定式提交以及如何做约束(命令行应用与 git hooks 正则匹配) https 中间人攻击 https 链接上请求内放密码 https 的数据是安全的吗(只想到密钥泄露) 快排时间复杂度,为什么最坏是 On2 对一块内存上的数组尾插 / 头插元素的时间复杂度 讲项目(40min+) 立项,重构,后台实现,远程协同 CRDT 思想 脏路径处理 并发冲突 简单说说 YATA 数学证明?(包不懂的) 断网后怎么办,或者说有个客户端延迟很高(插入永远有一个唯一位置,应对比较轻松) 服务是中心化还是去中心化 一个人删除了一行文字,另一个人在这行文字添加内容,结果是什么(根据 YATA 算法第一层比较,客户端小的操作优先) 简单对比 OT 项目背景 简单介绍 Astro 框架 项目设计(做成 npm 包,并作为 astro 插件使用) 项目技术栈对比,自研的原因 第一次升级后的成果与遇到的问题(框架问题,GitHub issue 讨论,细节挺多的) 语法分析器的设计(core 层 和 plugin 层) 如何进行语法检查的(ast 语法树遍历分析) LSP 服务器设计与消息优化(VSCode LSP 使用 pipeline 或 websocket,如果要优化可以通过自研协议分主动推送和监听广播行为) 前后端结构(前端,后端,脚手架后端) 项目发布过程 mdx 中用户如何使用自定义组件 mdx 可以回退 md 吗(没有研究,后续看了一下,mdx 是作为一个 astro 插件使用,回退的话可能需要对内容进行过滤处理(表达式,用户组件,script 标签过滤)) markdown 过滤 astro 编译 mdx 底层实现(讲了用到的插件,但是还可以继续讲讲 vite 怎么去 resolve module 的,和源码中经过了几次编译后才输出结果) 如果有用户恶意输入,你是怎么处理的(pr check) 如果用户太多你管不过来怎么办(插件过滤 script,工作流中使用 bot 自动检查) mdx 注入组件的白名单 mdx 可以渲染 react,那可以渲染 vue 吗(可以,配置插件即可) 如果要在一个 react 组件里面使用 vue,我该做什么 app.mount 发生了什么(没说全,讲了一下对比和 mount 和 patch,其实就相当于把 vue 渲染讲一遍) 如果我想在 react 组件内用 vue,vue 组件内继续套 react,我该怎么办(编译器做一个类似 rust 的宏展开自动注入 render code) 还有可以扯的吗(astro wasm 组件编译,content layer api,SSR 编译 mdx 可以实现运行时无编译开销;选择 jsx 作为通用组件的原因) 反问 技术栈(js ts rust c++) 业务还是基建(基建) 期望实习时长 大概还有几轮(一般三轮) 关于微信游戏二面面评(每个面试官都有自己的看法) 需要改进的地方 当时开始做题的时候我还没有意识到事情的严重性,还跟群友聊了一下说怎么一上来就做题,随后一顿拷打让我知道自己是多渺小了。 八股复盘的时候感觉自己就是个超级大笨蛋,说不定面试官都躲在屏幕后面笑,说这小孩子想象力还挺丰富的 面完这两个半小时人都虚脱了,在会议室里面跟群友汇报完后缓了好久才走出会议室,刚好实验室外面刚刚结束24届大一同学面试。后端的一哥们说想转前端了,于是就把前端在场的同学一起叫了过来,聊了一下他们的学习进度,并针对他们现场确定了一下学习路线,最需要关注的内容和接下来该做的事情以及未来要如何发展,全部聊完后也都晚上 11:10 了,于是听着私宅特有的歌冲回了宿舍。 实验室真的跟家一样,我可以说实验室和简历的项目几乎就是我大学的全部了,没有这两样我也走不到今天这一步 二面(1h) 最有压力的一集,有两位面试官,一位问一位听。一开始还好,都是从浅层知识开始问起,后续就开始深入拷打,一直拷打到不会为止,太可怕了。 其次是计算机基础,还得是科班同学,当时从编译原理一路回溯到计算机组成原理,最后感觉还是操作系统最重要,当时做 mit cow 实验理解了一下其思想,没想到现在回过头来在面试用上了,这个寒假一定要好好看看操作系统和数据结构以及一些基础。 感觉入手比较简单的还是计算机网络,毕竟可能更多时间都会花在 rfc 文档的阅读和对传输的理解和作用以及优缺点 其次是远程协同这个课题能拷打的地方真的很多,我虽然认真想了,但想的还是不够,还可以变得更好,只能说慢慢来吧 我曾经也憧憬过在开源圈内总结一套比较稳固的远程协同实现,包括服务器崩溃,服务中断等,这些都留给未来的自己吧 简单自我介绍 什么时候开始学前端 前端工程化,以及各种其他方面的东西是怎么学习到的 怎么平衡学校与个人学习 觉得学校的课业对学习有帮助吗,举个例子 讲一下 cow 是什么(copy on write) 为什么说考虑过用编译原理的知识尝试去实现 markdown 编译 对于 string.replace 方法假如要自己实现有什么优化的想法吗 挑一个项目最有挑战的点来说 简单解释一下 CRDT 协同面对的两个问题 跟 OT 对比优劣在哪 为什么选择远程协同作为解决方案,在此之前调研过其他方案吗 说一下光标速度优化,具体为了优化哪个层面(网络传输) 讲一下前后端结构设计 服务器崩溃问题(一路延申到快照创建,历史版本,内容压缩,使用外存) 说一下现在的解决方案和未来的解决方案 为什么快照可能可以解决 yDoc 实例占用内存过多的问题 遇到环形引用怎么解决,这里如果改为 json 可不可以进行压缩 结合 cow 说一下 json 压缩实现 说一下 yjs 在避免内存泄漏上实现的 gc 是什么 做上下文序列化时为什么说可能阻塞 说到阻塞,解释一下为什么 js 与 gui 互斥,从操作系统层面来说可以通过什么方式去实现互斥 平台有多少人在用 了解 js 与原生语言之间的通信吗 简单说一下 tauri 那个项目 用 rust 实现了什么功能,解决了什么问题 除了编程还有什么爱好 反问 需要改进的地方 您负责的内容 这一面能很明显感受到考察的是项目思考深度,我可以说一个好的项目是非常加分的,这个好指的是你对他的思考,深入到了什么地步,对比过什么方案,最终权衡下怎么解决的,为什么选用这个方案,效能比怎么样,有考虑过未来发展吗等等问题 ,即 STAR 法则。而不是单纯说我 star 多,被推荐等。我简历上的项目也没说多少人 star,因为他面向的是一个特定领域的解决方案,是我们团队内部为了解决问题而实现的一套工具。 压力面加上发挥的一般,一些基础和深入点没讲好,面完后有点难过,觉得自己马上挂了,结果两个小时后约了电话 3 面,真的是极大惊喜啊。 三面(电话面 30min) 这一次是电话面,连时间都没约,直接发邮件问面不面,那当然是趁着这股劲狠狠的面了! 听声音感觉是一位很和蔼的面试官,给了我 20 分钟讲项目,中间提问 + 反问。可能是为了考察一下沟通能力,因为二面的时候讲塞壬唱片项目的时候没有讲好,有点啰嗦和抓不到重点,可能因此加了一面。 自我介绍 之前有实习过吗 简单说一下项目立项 第三方平台卡内容?那有没有想过其他自由的平台(我们的平台有属于自己的精神内核和思想,希望从自己的网站上去体现) 平时平台上面会发布什么内容,选择 astro 框架的原因 除了对比市面上的框架,还有没有调研过 hexo wordpress 这种框架? 成果怎么样 之前面过微信游戏,有没有总结面试为什么挂了,简单说说 对于玩具项目的定义 项目第一次大更新的目的是什么,解决了什么问题,中间有什么困难,现有的问题和未来的发展 第二次大更新解决的问题和困难,以及现在的状态 聊聊结构设计,为什么分了新仓库,基于什么考量,为什么要这样设计,好处和缺点 反问 这一次面试这么快的吗(把内容输出总结了就大概知道是什么水平了) 您负责的职责(c 端用户端) 还有几面(应该是最后一面) 可以改进的地方 入职时间 整个过程还是聊的很愉快的,能感受到面试官为了理解我的项目在做提问。 沟通真的是很重要的一环 ,作为开发人员沟通是绝对少不了的,因为你要搞懂需求,确认上下文,个人觉得唯一不用沟通的就是搞算法科研,天天发论文就好(雾)。不过把沟通交给我的话我还是要事先准备准备,对自己要说的各种东西有一个大致的了解,这样才不会在现场时显得很慌乱 其次就是感觉在与大佬沟通的时候,我就像是在给老板分析我的产品,他的优劣,以及综合团队的思考等,还有他带来的收益 后续 2025/1/2 oc 我的秋招实习之旅到此算是以 1 wxg 日常实习 offer + 1 外企日常实习 offer 结束了,虽然我完全有信心一口气在外企干到毕业并努力转正 后记 有人问过我说为什么我的项目能做这么多东西,我的答案是:经历了长时间的沉淀,为什么能坚持这么久,因为我想 我正在做我喜欢,且能满足我和让我充满动力的事情 ,在此引用一句其他大佬精辟的总结: Do what you love, love what you do. 其次是由于面试,我也脱离我的项目组有一段时间了,是时候要回归他们,做一些 mvp 开发和文档攥写了。他们都是很善良很友好的人,没有他们我可能就没有我简历上这个项目,也没法约到这些面试了,可以说是他们成就了我的项目基础;其次要感谢社区所有的开源开发者,他们燃烧自己的热情去实现了一个又一个无与伦比的开源库与包,尤其是感谢 astro 与 yjs,astro 官方维护成员很积极,社区声音也很多,对于 bug 处理也非常认真;yjs 则是实现了一整套生态周边,方便了我们快速上手,如果单纯给我一篇论文让我自己去实现远程协同那绝对是做不到的。 希望这份经历能够帮助到正在阅读的你,给你带来一些思考或者启发 另附文中说的项目和一些参与过的项目: $1 一套一站式生成 minecraft mod Wiki 网站解决方案 $1 Wiki 网站解决方案项目的前身 $1 对塞壬唱片官网实现的一个功能增强,为其增加了自定义播放列表 / 第三方音乐平台接入 / 歌曲下载 / 离线访问等功能 $1 一套以内容驱动为中心,支持 SSR & SSG & 混合渲染的全栈 Web 框架(提了两个小 pr 和文档修改) $1 一个基于 bun 的后端框架,支持高度自定义编码风格(只是改了一下文档(逃))

2025-01-02 - Shiina

(转载)前端速通指南

(转载)前端速通指南 原文地址 原文地址:https://github.com/huanxiaomang/cz official/blob/main/docs/guide/%E5%89%8D%E7%AB%AF%E9%80%9F%E9%80%9A%E6%8C%87%E5%8D%97%20copy.md 写在前面 本文源于跟牛客某美团✌交流时提到的一个内容,看完后只能说自愧不如,能在这么早的时候就有一个对未来与现状的清晰的认知,已经至少打败同校 95% 的学生了。为此我决定转载这篇文章,不能让这么好的东西就埋没于 GitHub。 笔者认为本人最核心的点在于: 学习资源 学习能力 学习兴趣 最后是 努力 (有效时间) 学习资源:网络大把,找不到就别来沾边(暴论 能力:看个人吧,这个是主观+客观因素各有影响 兴趣:也是看个人,GitHub国人里10有8是sb二刺螈 努力与成果:比起我吹嘘花了多久,我的效率更高才是更重要的,成果才是最好的物质客观证明。 Talk is cheap, show me the code! 提高能力 提高知识量 知识是学不完的,尤其是前端,曾经有一张梗图描述了前端生态,几十种框架,涵盖UI渲染,SSR,后端,编译器,质量检查工具等。笔者本人在大二的时候曾经有一段时间出现过技术崇拜现象,认为一个项目用了常用的技术就是个模板项目,直到看到项目内对数据流清晰的规划,合理的架构,以及设计模式的合理运用,我才意识到这又是另一方面的能力,不是提升技术量就够的。尤其是计算机,知识更新迭代的很快,昨天加的一个群里有个搞 riscv 的老哥开完会就吐槽说又有新的更优硬件架构,又要重新学。现在 vue 和 react 是热门,谁知道未来又有什么顶级框架干掉他们呢? 本文已得到作者授权转载喵,灌注本人 (Github)[https://github.com/huanxiaomang] 喵 正文 来看本文的可能有3类群体: 1是还未想好具体发展方向,前端作为计算机基础知识来学的,后期可能转为JAVA方向,2是明确了就业前端,打算大学通过前端方面的项目经验和奖项丰富自己简历的,3是对前端或全栈等领域进行深入研究的,本文更侧重2类,有必要区分方向的地方会特别标注。 本文章为纯技术流路线,请根据自己实际情况自行取舍! 软件工程做什么 从就业方向来说,有web开发(前端)服务器后端开发 大数据等等。总之就是:开发。 也就是用各种编程语言写各种代码来开发服务器 网站 小程序 桌面应用 安卓/ios应用。 相关职位: 前端:拼视图 调接口 和用户交互 技术栈有 后端:功能实现 数据处理和存储(数据库)通过接口把数据返回给前端 技术栈有 美工:UI/UX设计美观交互性强动画流畅的界面,做出产品的“原型”交给前端用代码实现 原型工具有 等 产品:负责设计产品功能迭代 用户竞品分析等等。 实际的职位还可能再细分,除了这些还有测试 运维等等。这里只列举主要职务。 前端热门技术栈和对应方向 WebGL 涉及 图形学等等 $1 数据可视化大屏 微信小程序/ 各类移动端应用 小程序游戏 开发桌面应用程序 如飞书 新版QQ界面 VSCode 前端工程化底层 架构师 涉及底层源码 自动化 精通一门技术需要的条件 个人认为,分别是: 学习资源 学习能力 学习兴趣 最后是 努力 (有效时间) 1. 学习资源有学习环境 有没有带你的或者互相促进的人 还有看什么样的学习资料。 如果只看得到一群只会念ppt的老师,那么他的水平可能都做不出毕设。 如果只看得到b站某马某硅谷的基础课和毕设速成,那么他可能很难找到工作,还要抱怨“前端已死”。 学习资源要 自己找 、 一直找 ,自己脑中的知识网络是逐渐更新的,不要说我现在啥也不会把这个基础教程看了就行了,这是一种逃避,只在舒适圈待着,那学到什么时候也很难摸到更高端的东西。 不过每个人所在的环境都很难改变,一般的学校环境很难赶上好的学校,家庭环境也是,宿舍环境,学校环境也是,这是事实,就是没办法。(你以为我要劝你提升自己?)我之所以把它放到头一位,是因为它还能直接 影响下面三点的好坏 ,而且也是 最难改变的 ,像人与人的差距一样。 2. 学习能力有天赋、能力。天赋和能力有人已经赢在起跑线上,好在我们后期还可以提高能力,也不用和他们参与同一个赛道。 区分好能力和知识量: 拿网上泛滥的长达几十小时的基础前端课来说,如果从头看到尾甚至还去背那些属性,只能说提高了知识量,但能力没有显著提高。能力是在反复利用自己的知识量和经验解决各种问题里提升的,不是看完了基础看完了vue源码看完了 就有的。 3. 如果对自己学习的技术有学习兴趣,那么学习过程中会非常丰富多彩:你会被大佬的作品所触动,也更乐意动脑实现自己想要的东西,你的兴趣会促使你一直学下去。 4. 努力不必多说,充分利用学习资源,有合理的学习方法和不断提高的学习能力,还有兴趣驱使,再把有效时间堆起来,技术一定会飞快提升。可惜没有前三个因素加持的努力其实暗淡无光且浪费生命,所以我把它放在了最后一个(悲) 最近真的发现,我带的几个能学到什么水平基本刚开始就能看出来,人和人上手一项技术的速度真的是不一样的,而这就取决于上面的前三条,而不是后续的努力。光努力只会在当前技术能力的阶层比别人知识量更多一些,起不到决定性的提高。 所以相比提高学习时间,还有很多其他的工作不可忽视:能不能找到可以带你的人?能不能持续提高学习能力而不是只学习知识?还有,我真的对这个东西感兴趣吗?千万不要局限于“自律”、“努力”这几个概念,你考不上好大学,就一定跟平时教你的老师水平、模拟题的质量、学校管理水平有关系,很多人给你洗脑是因为这些根本改变不了想让你从自身找原因,但现在我们可以改变很多东西了: 1. 宿舍太吵没学习环境?还不想去图书馆?那就去租房,要么说服父母,要么自己攒钱挣钱。 2. 身边没厉害的人指导?github、掘金、qq群有很多高学历高水平大佬,勇敢地加他们,问着问着可能就熟了(技术水平高的很多都是二次元,比较好说话) 3. 你觉得把各种教程、学习路线从头学到尾就完事了吗?去github找个相关的项目看的懂吗?看不懂,那就是能力不够,学再多新知识也没有用,能力是费脑子练出来的。 4. 我真的找到了我要从事的方向,我自发地想去做的东西了吗?就业还是考研,前端还是后端,是跟风走还是遵从自己的主见?还有,我不认可”不试试怎么知道呢“,如果只是单纯为了”试试“,那大可不必,时间浪费了就是浪费了,学没有用的就是浪费时间。 要有自己的追求和目标,这些一般就不会被很多人理解和看好,这和创业也有些类似,我们创业的干的事经常不被人理解,我只想说,在这方面他们看的太浅了,自媒体或者直播或者电商走下坡路太卷这话谁都能说出来,所以他们不去研究,可是只有自己真正琢磨了去做了才能发现做什么怎么做是更赚钱是更好的,他们拿道听途说的“参考”把这条路否定,我们把这当成一次机会当一次尝试来积累经验。 归根结底还是,我们的追求和思维模式是不一样的,我想赚钱,而他们没仔细想好过什么追求,什么财富自由 技术超群也都是想有的,可现实的巴掌呼过来时,他们只能选择从众这一条路。 这些就不是单单一个努力就能做到的,却能提高你境界的东西。那些让你痛苦的东西,就是你最该提升的。 学习理念 提高能力 提高知识量 上文提到过能力与知识量是不同的,我们要重点提高能力:学习能力、开发能力、设计能力、debug能力等等。这些都是需要动脑子来提高的,只机械地输入各种知识是不行的。(甚至很多学完就忘了) 那么既然是这样,学习视频教程(初学建议看视频教程)的方法也要有所不同: 1. 千万不要只无脑输入:有选择地看教程,带脑子去思考,使用项目驱动学习的方法,只吸收项目需要的,跳过已经过时的、对现阶段太难的或现阶段用不上的。 2. 面对例如数组的方法这种很密集的知识点,不是说听一遍讲解跟视频敲一遍就会了的,之后该忘还是会忘,只有在实战中自发的使用这些方法,才会真正记住、理解他们。 3. 先速通最热门的技术栈(取决于当前招聘趋势,目前是 + ),比如直接学 跳过 前后端不分离的内容、直接学 跳过一些原生实现各种功能的操作。按传统的学习路线,这些框架都是大后面才去学的,但我并不认为前面很多所谓“基础”的知识是必要的。 首先要说清楚一点:学习路线是知识点串联的,不是说前面没全学懂就不能学后面的了,也不是说到后面学完框架就是进阶的了,更不是说进阶的工程师不会再去做前面所谓“基础”的东西了。学了 ,学了 ,这不叫进阶,这只是你多学了一个框架,一堆知识点。使用各种技术来实现各种功能和业务才叫技术能力高,而不是你比我多学了多少东西。 前面的知识也有很多很难的(比如闭包原型链)、现阶段用不到的(比如WeakMap Symbol),在你没到那个水平、那个境界的时候不要去死扣,扣也没用,而应该去学习更多知识点、练习更多写法、学习更多程序设计的思想、提高自己的境界。 前端学习路线 第1阶段:HTML+CSS+JavaScript基础开发 目标:配置简单的开发环境,掌握初步的网站开发,能够完成结构略复杂的布局,进行简单的DOM操作 关键知识点: 推荐实战案例:响应式布局还原某官网、JS实现轮播图 第2阶段:Node.js+vue3前端工程化 目标:使用node构建前端工程,用vue3(vue2不用看了)和组件库完成基础的业务逻辑,express与前端aixios实现前后端交互,使用git进行源码管理。 关键知识点: 你可能会疑惑:你这学习路线是不是少了不少东西?某马程序员某硅谷写的比你全面多了,闭包/原型这么重要的知识点都没有?上文提过,有些知识不是当前境界能碰或者说用得到的,我列举的是实现大多数功能必需的基础知识,此外的了解即可。这些知识是都可以速通的,我将更多东西放在了三阶段。 第3阶段:开发能力与技术栈扩展 此处学习更多的技术与工具,阅读文档和源码。 到了这里,就不要像刚入门时沉浸在视频教程里被人喂饭的感觉里了,一定要去github,习惯去开源社区找资料、去学习。 到了这里,就能真正见识到前端知识的多与杂。 关键知识点(太多了只列举部分): JS补充: 更多CSS方案: 前端面试: 面试送命题)性能优化 React系列 Electron Tauri Uniapp 微信小程序 cocos游戏开发 Socket.io 低代码 docker Nginx 性能监控 数据埋点 CI/CD Koa nestjs JWT MySQL MongoDB Redis 中间件 分布式架构 VantUI AntUI Typescript Webpack Rollup Mockjs WebGL/threejs DataV WebRTC Rust WASM PWA 开发能力 业务能力 协作能力 TS Vite React18 ReactRouter Redux Redux ToolKit Ant Design Axios wangEditor`等 负责模块:项目基础设施搭建、代码打包 责任描述: 1.利用Vite内置import.meta.glob方法,动态获取路径下所有路由配置文件,生成动态路由表 2.根据React 提供的lazy函数封装路由懒加载工具组件,实现路由懒加载功能,提高性能 3.利用RBAC的权限设计思想,封装导航守卫组件,对当前登录账户进行权限控制,利用concat方法合并登录 账户能够访问的路由表 4.封装校验网络请求状态码方法,根据后端响应状态码进行弹框提示 5.封装按钮权限Hooks.封装递归函数遍历所有路由,判断当前账户的所有页面按钮权限中是否包含当前页面 6.封装工具函数利用map字典构建栏目ID 和数组的映射关系,将下级栏目依次添加到上级栏目中 7.封装wangeditor 富文本插件,适配在React项目中使用 3. 奖项证书 我们一般会参加两类比赛(前后端开发方向):一种是纯考验技术的个人赛,另一种是又答辩又写文档的团队赛。 我当然是推荐参加 蓝桥杯 acm 这种个人赛,这才是通过实打实的技术过关来获奖,而大创、互联网+和各种团队赛参杂了太多其他东西,作品都是给评委看的,而且大家水平比你低的多的话,也不能很好地发挥,还要被各种老师“指导”。虽然看上去含金量很高,但其实跟奖学金证书,还是三好学生,包括什么优秀毕业生之类的一个性质,在HR眼里,统统没用。这些只能证明你考试成绩不错,甚至还有一些暗箱操作的可能,企业是招你来 干活 的,你要拿出证明你技术能力的东西来。 看好了,现在的路线是就业,不是保研。 那么证书方面的配置至少如下: 英语四六级证书 :至少,至少把四级考了,英语,不一定能给你加分,但不会,一定给你减分。 竞赛国家级二、三等奖 :每一级名额都不少,争取一下还是可以的,省一是比较low了。 [可选]训练营证书 :字节青训营、腾讯犀牛营,去和一些水平相近的人远程协作,最好拿个奖,也是不错的。 注意!计算机专业的是不需要考全国计算机二级的,因为全国计算机二级面向非计算机专业的人。软件工程专业毕业默认视为计算机4级水平。 以上是简历最关键的证明实力的三部分,确立好自己的就业路线后,就狠狠地丰富这三方面,绝对错不了。 入职后续的发展方向: 1.先利用前端弱鸡多大神少的特点踏入大厂的门 2.自学一年不如工作三个月,在工作中狠狠地学习 3.可以从前端过渡到后端、全栈、产品、管理或其他岗位 4.也可以在技术扎实之后学习英语,应聘国外的远程开发岗位(美元比较好赚) 5.也可以在技术扎实之后投入开源圈,现在 Vue 团队就是靠开源盈利的(但这个在大陆可能难以实现) 6.也可以在技术扎实、熟悉开发流程之后辞职创业,直接面对用户,解决用户的需求或者直接回家卖课 环境准备 浏览器:Edge + 内置Bing搜索引擎 别特么用你那老百度了,全是广告,bing至少会少一点。 之后会更推荐使用谷歌搜索,但大家现阶段用不上梯子。 软件:VSCode 真的见到好多下载软件第一想到的是去软件商店的,醒醒,这是电脑不是手机,打开edge,搜索VSCode,前面几个就有官网,有的是广告。 看好域名,code.visualstudio.com,这就是官网,进去Download下载。 并下载Live Server的插件,用它来编写代码实时预览网页。 让我们开始吧 不知道有几个人能看到这里( 我将整篇文章称为指南,而非教程,就是要声明,本指南对随便一搜就能学习到的知识点或案例不会有太详细的讲解,重点是写点常规教程没有的,做点别人课程里没有的案例。 从上面环境准备就可以看出来,比如我会介绍给你Live Server,但不会细讲怎么用。 我会在之后对初学者的学习流程进行指导,而非仅仅教知识,并且总结常见的问题循序渐进地用一个比较优雅的方案去解决。 原文地址 原文地址:https://github.com/huanxiaomang/cz official/blob/main/docs/guide/%E5%89%8D%E7%AB%AF%E9%80%9F%E9%80%9A%E6%8C%87%E5%8D%97%20copy.md 本文已得到作者授权转载喵,灌注本人 (Github)[https://github.com/huanxiaomang] 喵

2024-11-27 - Shiina

基于Yjs实现的多人协同编辑应用实践

基于Yjs实现的多人协同编辑应用实践 前言 远程协同在大家生活中多多少少都是有接触过的,包括但不限于腾讯文档,金山文档等,他们都有多人在线协同编辑的能力。其主要围绕的都是一个 “多人实时编辑”, 在没有多人协同编辑的过去,假如一份文档需要多个人来完成,要么是按顺序每个人写一点,上面一个人写完了发给下一个人继续完成,要么就是所有人自己写自己的,然后最后统一发给一个人整合成一份文档。这样效率多少都有点低。远程协同正是为了解决这一个问题而诞生的,他做到了一份文档每个人都能同时写自己的一部分,同时展现整体效果的功能。 本文不会着重探讨 Yjs 背后的底层原理,而更关注于项目的技术栈与架构流程演变,如果您对 Yjs 及其背后的 CRTD 协同算法有兴趣可以移步文章: $1 项目背景 起因是个人自身的一个项目,他有这样一个词条编辑功能,其基于 Markdown,可扩展为 MDX,是纯文本编辑应用。当这个词条正在被一个人编辑时,其他人不可进入该词条房间,直到前一个人退出房间才可继续。 有时候写词条会有多个人,两个人要想写同一个词条或者对另一个人写词条做指导时是完全没法实现的,为了解决这个问题,接下来就是开始了技术调研与方案选择。 解决方案选择 经过调研后,总结出来的选择如下: 开放观看编辑操作,这个可以实现平台内小部分指导编写词条功能 开放每个人的编辑,每个人编辑完成点击保存时服务端进行一次类似 git diff 合并操作,假如发生冲突则反馈到用户端,让用户自行处理 通过远程协同技术实现多人同时编辑 三个解决的问题和新产生的问题如下: 观看编辑操作满足了一小部分可以通过语音沟通进行编辑的词条,但是其本质上并没有解决多人同时编辑的问题 开放每个人的编辑操作则解决了不能多人同时编辑的问题,但是新产生的问题如下: 假如两个人发生了并行编辑,其中一个人编写了大量内容,另一个人同样编写了大量内容,两份文档提交到服务端后势必会有大面积冲突,虽然这个问题在本应用下问题不是很大,因为是纯文本编辑,但是在富文本以及 excel 场景下用户解决的成本将会变得特别高 当两个人编写的内容发生了穿插(每个段落中都有类似的文字)时,用户 diff 的成本将会随着内容的变化呈现线性提升 远程协同解决了多人编辑 + 实时展示的问题,但他同样也有一些问题: 个人并没有远程协同技术落地实践的经验,算是第一次接触 服务端实现是基于 websocket,需要具备这部分的编程能力 最后经过斟酌个人还是选择了实现远程协同这个方案,这也算是个人对技术能力的一次实践与提升。当然假如这是一个大型项目,我肯定会找研发团队参与进来进行彻底的研究,或者选择 diff 作为解决方案,因为本应用是纯文本;假如时间不够的话我会选择直接在操作平台内嵌腾讯文档,毕竟现成的可以直接拿来用,当然也要承担一部分第三方应用的风险就是了。 经过长时间的探索与实践,现上线版本的一个协同编辑的页面展示如下: 包含的功能如下: 多人编辑协同 提供协作者列表,光标位置信息 历史版本记录 支持不关闭浏览器的离线编辑,上线内容自动恢复 未来计划功能: 离线提醒 回滚操作发生后全体通知 浏览器关闭后内容恢复 接下来讲讲技术选型和一些小细节: 技术选型 参考过很多文章后我选择了 CRTD 作为冲突解决算法,其背后生态支持库是 Yjs,原因如下: 个人并不熟悉这个算法的过程,且项目存在隐性 ddl,时间成本较高 需要大量服务端编程,不清楚这个算法在后端是如何自动解决冲突的 本编辑器采用 monaco editor 作为载体,社区中没有 OT 生态支持,很多代码可能都需要自己探索和自己写 Yjs 包含一套完整生态,覆盖编辑器接入到通信协议实现,且各个部分之间都是单独仓库 Yjs 对于 monaco 有一个简单 demo,与想象中的几乎一致 OT 背后一个针对的方案是 ShareDB,但是数据模型的接口可能需要自己实现,且查看过一些基础代码后发现其编写的代码都相对底层,开发成本会偏高 项目中大部分词条字数最多是几千字,且为纯文本,而 CRTD 对于万字数量级的纯文本支持都非常好 (https://github.com/pubuzhixing8/awesome collaboration/blob/master/crdt/5000x faster crdts an adventure in optimization.md) 当然现在看来两者都有各自的优劣,尤其是在离线后重连这一部分上,这一部分会放到后面展开讲讲 最小 Demo 实现 这是个人基于官方例子实现的一个符合项目需求的最小 Demo,前端是 monaco 实现,后端则是使用的 elysia + bun 实现的一个处理:(Y LSP)[https://github.com/QingXia Ela/y monaco lsp example] 相比官方示例这里提供的额外功能是用户名字展示 + 悬浮。 这里还有一个额外功能是语言服务器服务,因为这个项目我们编写了一套基于 LSP 协议的 IDE 智能提示,用于在词条内给编写者提供提示,提升开发效率,其细节以后可以在另外的文章说说。LSP 与本文无关,可以忽略。 技术方案、架构与落地流程 技术方案只讲一下前端的: monaco editor + yjs + y websocket + y monaco。 目前服务端架构图如下: 其中 auth 层在 tcp 升级为 websocket 前发挥作用,如果验证失败直接 deny。然后是 socket 层会实现一个到 y websocket 服务端官方实现的一个转发,这个服务端本人经过了一定的改写,使得他在监听到共享数据发生变化时向最终的词条服务器发送发生变化的词条的内容,词条服务器实现保存到硬盘上的操作。 先讲一下具体落地的简单流程: 编写 Demo 确定架构与消息流程 移植官方实现的 Yjs Server 实现,并修改鉴权流程 处理历史版本保存实现,排查问题 上线,压力测试,拉上114个人,准备514份长文本,冲刺,冲刺,冲,冲,冲 循环 3 4 步,没有问题后发布并开始上线使用 一些已实现功能遇到的问题细节 历史版本 目前历史版本是通过完整记录词条文字实现的,回滚过程则是直接修改服务端 Yjs 获取原文并存储内容到缓存实现。 这个操作会产生一个新的历史记录插入到历史记录队列顶部。 其次是几分钟保存一次的问题,本项目是当有人进入词条编辑房间时五分钟保存一次,当房间无人时关闭定时器。 未解决的问题在下方有写明 鉴权实现 Websocket 是基于 TCP 协议,其中将 TCP 连接升级为 Websocket 时是在请求头中携带 与 ,随后连接升级为全双工通信,这个可以通过 node 原生 http 库中的 事件进行监听,在 elysia 则是通过 函数监听。 协同者光标 协同者光标的 css 需要自己写,且要进行动态插入,具体可以参考我写的 demo 中断恢复 客户端无持久化存储与初始内容 中断恢复是整个项目中最难处理的一个部分,这里的中断指的是客户端或者服务端关闭后重连,中断可分为以下3种: 客户端中断重连,服务端全程在线 客户端全程在线,服务端崩溃后重新上线 客户端中断重连,但是在中断期间服务端崩溃后重新上线 针对服务端崩溃的情况,其首先的影响是丢失了 Yjs 客户端连入上下文的信息(最后操作时间、删除集等),假如此时服务端恢复客户端重新连入后,服务端会把所有人内容都视为一个新插入,从而导致大量的内容重复。 而针对客户端中断的情况则分 与 的情况,有上下文的情况就好办,发生此类问题的场景是客户端断网,但是保存浏览器开启的状态,此时的恢复是可以依靠 CRTD 算法自动解决。 而丢失上下文的情况则是由于不可预期的故障导致客户端关闭浏览器时发生,但假如客户端没有实现持久化存储,这种情况则可以忽略,因为这相当于一个客户端从无状态情况下正常连接到服务端。 持久化存储的情况放在后文讨论。 目前实现的方案是服务端中断恢复时照常丢失上下文。服务端恢复后客户端重连时,客户端在接收到服务端同步内容后进行一次 diff 比较,对双方的变化均进行保留。 当然这种 merge 存在一个问题就是不能有多个客户端并发进行 merge 操作,否则可能会导致内容错误 客户端 merge 后导致的用户焦点不正确问题 该问题仅发生在服务端中断后客户端 merge 的行为上。 本项目采用的词条换行符为 ,但是 yjs 的 toJSON 方法转换后的结果只保留了 。所以在通过 monaco 方法设置值的时候要把所有换行符替换为 ,否则会出现用户光标位置不正确的问题,从而导致用户看见的内容不一致。 挺可怕的一个问题,但是运气很好,试了一下一个个字符前进,然后就发现了每到换行符时,别的用户的视角发现操作的客户端并没有换行,而是停留在行尾部。 这种问题只会发生于纯文本应用。 未解决的问题与针对解决方案构思 历史版本 前文提到历史版本有个问题就是,用户的撤销栈没有同步清空,需要进行清理操作。 其次是内容大小,所有词条缓存都是存储在变量而不是外部如 redis 等,这就带来了个问题,万一开启房间多了或者某个词条特别长,都会把v8可怜的那点内存撑爆。未来肯定是要移动到外部存储去。 最后是保存的数据结构与持久化,Yjs 创造的快照是 + 其中快照类源码如下: 此处我们不关心为什么 Yjs 只需要 DeleteSet 即可实现快照存储,且他只存储用户对文本的操作,而不存储原文。我们只需要知道他能根据 DeleteSet 恢复内容即可,这里也是后续规划服务端中断掉线后恢复的必要点。 针对本项目我个人还是更倾向于直接存储词条原文,因为其体积并不是很大,可能一个词条文件 10KB 就是上限了,且相比快照恢复,字符串的运行时开销会更小点? 但是面对大文件或数据结构复杂文件,我还是更推荐使用快照功能,虽然从快照恢复内容仍然需要源 yDoc 对象,具体看:$1 回溯历史记录一段。 这篇文章讲的也很不错,揭示了很多底层细节。此处我们只关注这一段提到的 非常轻量的部分,引用原文内容: 由于 DeleteSet 的结构非常轻(例如在记录了真实用户 LaTeX 论文编辑过程的 B4 benchmark 数据集中,18.2 万次插入和 7.7 万次删除后仅生成了 4.5KB 的 DeleteSet),这种设计就进一步贴近了「零开销抽象」,因为删除时并没有创造出任何未知的新数据。 按大文件的体量相比,额外的几KB的DeleteSet序列化存储似乎不算什么。 而从业务开发速度的角度来看,这套逻辑是可以复用到下文的服务端中断恢复的。 如果要实现快照恢复则还需要研究 yDoc 对象序列化存储至硬盘,这个又是一个新的领域了。 客户端持久化存储 Yjs 同样也提供了内容持久化的存储服务,可以通过 来实现。 但是本项目一直没有启用的原因是:假如因为意外导致浏览器上下文丢失后客户端重新打开页面并进行了内容编辑,此时客户端仅剩下一套内容,且可能与服务端存在差异。 针对本项目,此时我更偏向于向用户提示说版本与服务器有冲突,让用户自行选择保存哪一份副本,或将用户的副本临时存储到其个人空间。 而针对更大型保障能力需要更强的项目,且在有研发团队的支撑下,我会实现一个更好的方案: 客户端进入编辑状态时会将ID存储到本地中 客户端在编辑时会将自己的操作与状态序列化存储到本地 服务端在发现客户端离线后为其保持 2 小时的状态存储,或将其放入外存以减少内存占用。否则当客户端重连时进入版本与服务器冲突处理流程 客户端恢复连接后与服务端进行 CRTD 同步 解决方案的本质是尽量恢复完整的上下文,做到类似于客户端在有上下文的情况下重连进入服务器。 服务端中断服务后恢复 接着上面的中断恢复,结合前文提到的快照来说一下未来设想的解决方案。 本流程是基于目前已有基础建设提出,后文还会提到一个新的后端一站式建设方案,对于那个方案可能还会提出一个新的流程 客户端首次连入时向服务端请求一个ID 服务端每隔 1 分钟保存一次快照 + 每次修改后节流一段时间再保存快照(源 ydoc 对象序列化 + yjs 快照创建方法,转为可存储在硬盘或数据库的内容) 客户端主动离线时,清理其信息;客户端非主动离线时,服务端为其保留 2 小时上下文 客户端恢复后,若超过了两小时,则将用户内容储存进用户的副本空间中 然后说一下目前 merge 存在的问题: 多个客户端同时进行 merge 时导致内容读写位置错误 这个属于并发冲突的问题,解决方案是监听 socket 信息,多个客户端连入必须排队进入且在前一个客户端完成 merge 操作后才能进入下一步,在后端上具体实现就是如果发现前一个连入 socket 完成同步消息传递后就开放下一个进来。这里可以通过 promise 实现顺序连入,当然你还要搞懂 yjs socket 底层传输的二进制信息就是了。 假如说不进行控制的话那么就会有脏路径读写的问题存在,从而导致文档混乱。 merge 行为发生后用户焦点会丢失 这个问题与 PingCode 情况一样,都是因为光标是根据文字相关位置确定的,merge 操作相当于重新复制粘贴了一大段内容,而之前用户相关的位置的信息就丢失了,因此导致 merge 发生的时候用户焦点会回到编辑器顶部。 可能的优化方案是 diff 算法不使用 setValue 方法以避免全量替换,取而代之的是使用 monaco 的 applyEdits 实现按需增删,避免焦点丢失;又或者记录用户的 offset 位置,当 merge 发生后自动移动光标到原来的位置。 undos/redos 这里的是依赖 monaco 的本地操作栈记录,但是这个会存在脏路径读写问题,比如用户1插入了文字 ,然后用户2在中间插入了 ,此时假设内容变成了 而由于 y monaco connector 并没有实现与 Yjs 的操作栈结合,所以 monaco 在撤销时是基于用户自己的操作,针对上面那段文字,Monaco 会认为用户在某一行中某个位置添加了 10 个字,因此撤销操作变成了从这一行的那个位置移除 10 个字,此时用户1撤销后就变成了 ,用户 2 的文字被移除,但期望结果应该是保留用户 2 的输入,即 。所以未来需要使用 Yjs UndoManager 去实现无脏路径撤销。 与 PingCode Wiki 对比遇到的问题 PingCode 问题总结: https://github.com/pubuzhixing8/awesome collaboration/blob/master/crdt/yjs/yjs fqa.md 中文输入中断 这个问题也同样发生在 monaco 编辑器中,在同一行中的中文输入内可以观察到中文输入的内容也会进入 monaco 编辑器并进行远程同步。后续将会进行问题研究与修复。 一个可能想到的解决方法是,控制 monaco 在发现中文输入或其他语言输入时,不将拼音给同步到编辑器内;或者对用户输入操作进行节流,直到用户停止输入后才将本地输入向服务器同步? 焦点不正确 这个问题在 monaco 中没有发生,可能是因为 monaco 是纯文本应用,面对换行操作时在底层数据结构采用的是 insert 一个换行符,从而保证相对位置仍然正确。 点击聚焦 光标闪烁后跳动到原来的位置 这个在 monaco 中实测没有发生,因为用户移动光标的信息会立马同步到其他客户端,没有节流,当然这也导致了在连续移动光标时大量消息发生了传输,未来肯定是要对这个操作节流的。不过不同于 slate,远程选区操作不会影响到内容的插入与删除,因为 y monaco 在远程用户选区上只是渲染出用户选了哪一部分,而不会影响到编辑器本地内容选择。 分布式系统与异地容灾? 虽然没实践过,但是我觉得可以想象一下架构的样子: 由于 Yjs 天生就是无中心的数据冲突解决的具体实现,在不考虑服务端上下文永久保存的情况下可以实现一个星型的异地多活图,其中中心机房是任何一个可能的 Yjs 服务端(即本项目后端),然后服务端之间的 Yjs 服务端实例通过机房间专线 + 定制的通信协议与中心机房通信,此时仅保证有一个机房在跟词条服务器进行读写操作。 假如中心机房挂了,可以立刻选一个新机房作为中心机房,保持业务不中断。同理词条服务器也可以改进为分布式系统,但是这个不在本文讨论范围内。 来源:https://www.bilibili.com/video/BV18v411c7FX 有没有更好的后端一站式解决方案? 有。 链接地址: https://tiptap.dev/docs/hocuspocus/provider/introduction 为什么项目不使用?因为早期调研时忽略了资料搜索,这个是看 b 站某个视频的时候看到评论说的一个玩意,光是看介绍就发现这玩意满足的需求还挺多的,包括但不限于只读,中断恢复,数据库,redis,权限验证等。 为什么不移植?因为这是项目临近上线时才发现的,只能说很可惜,然后预估了一下要改写的代码,量还不少(将所有Provider替换成该包专属的,整个socket转发流程都要改写),因为整个协议底层都改了。只能说路还很长。 总结与反思 从最开始的技术选型到 CRTD 应用落地,这中间前前后后大约也有近四个月,而且效果并不是很理想,因为其中还穿插了一个语言服务器的支持,假如没有考虑语言服务器那么这些顶多两个月就能实现完成。 为什么最初是直接考虑 Yjs?因为看到 PingCode 有技术落地实现,且有一些详细的文章参考与细节修复;其次是 Yjs 生态,天然支持 monaco,且网络上还不少解析 Yjs 的文章。但最后回头看过来我觉得我选择 Yjs 的时候还是少考虑了一些问题: 没有现成的生产级别投入使用的开源代码可以参考,必须要自己一点点排查可能遇到的问题 看到 Yjs 进行了无脑选择,而不是再找找 OT 相关生态(虽然选择 Yjs 可以帮助更快落地,因为很多库可以直接现成使用) 在 Yjs demo 编写过程中强行插入 LSP 开发,把一些可能很早就完成的尝试给拖到后期才一起完成 没有考虑自己的应用场景,没有尝试过在纯文本场景下将 CRTD 和 OT 进行优势对比与实现难易估计 实践是检验真理的唯一标准,这句话是一点错都没有。从最开始满心欢喜的选择 Yjs 以为项目可以快速落地,再到发现 Yjs 并没有针对服务端中断实现一个处理过程,再然后就是排查各种奇怪的问题,最后还要考虑新功能的快速集成实现。这么多内容放在一篇文章里肯定是没法彻底讲清楚的,所以我挑了一些有代表性和需要紧急修复的情况来谈。 但最终我还是要感谢这些框架的作者,这里用到的大部分基础代码与相关技术几乎都是开源的,我的内心其实是非常佩服这些开源作品的贡献者的,同时也在督促自己努力的去做更多的开源输出。假如只扔给我一篇 CRTD 或者 OT 的论文让我自己用 js 实现出来一个前后端交互实现,那怕不是这个远程协同的设想直接胎死腹中。 假如可以回档? 假如能够回档的话,首先就是先把 LSP 放一下,然后直接针对 CRTD 和 OT 各写一个 demo,搭配上必要的中间件如权限验证、排队、同账号多客户端连入、服务中断等。这里的每个中间部分可能都因为算法的不同而有不同的实现方法。 评估一个月后确定好最终技术栈,并投入实现,然后就是如上文的测试。 参考资料 https://github.com/pubuzhixing8/awesome collaboration PingCode 实现协同时的问题收集 https://juejin.cn/post/7077092715409702925?from=search suggest 多人协同编辑技术的演进 https://zhuanlan.zhihu.com/p/452980520 探秘前端 CRDT 实时协作库 Yjs 工程实现 https://segmentfault.com/a/1190000041023337 PingCode Wiki 技术揭秘 https://juejin.cn/post/7074092429862764575 如何解决多人编辑场景下的内容覆盖问题

2024-11-02 - Shiina