某大型電商滿一年的時(shí)候,我離職了
我是 2020 年 10 月 22 入職的某大型電商,到明天就滿一年了。但也在這幾天,我提了離職。其實(shí)做出這個(gè)決定我也很糾結(jié),放棄了很多東西,但我還是決定走了,這篇文章就來(lái)講一下為什么。
回顧某公司一年
某公司跨端引擎團(tuán)隊(duì)做什么
我入職的是跨端引擎團(tuán)隊(duì),某公司有自己的跨端引擎,也就是通過(guò) c++ 給 v8、javascript core 擴(kuò)展了很多 api,這些 api 由安卓、ios 分別實(shí)現(xiàn),包括渲染 dom 和 css,使用各種設(shè)備能力的 api。
因?yàn)榛?js 引擎實(shí)現(xiàn)了 w3c 標(biāo)準(zhǔn)的 dom api 和 css,那跨端引擎上就可以跑 html、css、js 代碼,通過(guò)它們組織邏輯,然后由 natvie 實(shí)現(xiàn)渲染和交互。
這之上還有一個(gè)類(lèi)似 react 的前端框架,是我們修改以后的,最終渲染用的 dom api 是跨端引擎提供的那些。
這樣,業(yè)務(wù)線就可以通過(guò)一個(gè)個(gè) react 組件來(lái)組織頁(yè)面,通過(guò)各種跨端引擎提供的 api 完成頁(yè)面交互和業(yè)務(wù)邏輯。
這個(gè)跨端引擎上跑的代碼是有自己的一套規(guī)范的,業(yè)務(wù)線寫(xiě)代碼會(huì)用 less、typescript、es next 等語(yǔ)言,然后轉(zhuǎn)成跨端引擎支持的寫(xiě)法,所以需要自研編譯器來(lái)做這種轉(zhuǎn)換。
我們基于 babel、less compiler 實(shí)現(xiàn)了編譯器,遞歸的分析依賴(lài),編譯每一個(gè)文件,然后打包到一起。我們并不需要 webpack 一樣的 chunk 分組,因?yàn)椴皇菫g覽器平臺(tái),只需要壓縮到一塊就行。打包的產(chǎn)物是一個(gè)二進(jìn)制文件,叫做 bundle。
編譯只是讓源代碼能夠在跨端引擎上跑起來(lái),但跑起來(lái)之后會(huì)有日志、報(bào)錯(cuò)等信息,會(huì)需要做 dom、css 的調(diào)試、 js 的 debugger 等,這就需要自研調(diào)試工具,我們基于 chrome devtools protocol 實(shí)現(xiàn)了自己的調(diào)試工具。
編譯、調(diào)試都是和寫(xiě)代碼強(qiáng)相關(guān)的,所以又基于 vscode 定制了 ide,集成自研編譯器、自研調(diào)試工具等,也實(shí)現(xiàn)了很多寫(xiě)代碼相關(guān)的 vscode 插件,比如路徑提示,js、css 的智能提示等,因?yàn)榭缍艘嬷С值臉邮胶?js api 都是不一樣的,需要自己實(shí)現(xiàn)。
跨端引擎上的代碼是一個(gè)個(gè) bundle 的形式存在的,而 bundle 和 bundle 之間會(huì)有依賴(lài),因?yàn)檫\(yùn)行平臺(tái)是自研跨端引擎,不支持 node_modules 那一套,所以自研了依賴(lài)管理工具。包括通過(guò)一個(gè) bundle.json 聲明依賴(lài),遞歸的下載依賴(lài),全局的緩存等。
此外,跨端引擎提供的各種 api 對(duì)于 c++、安卓、ios、文檔都要保持統(tǒng)一,怎么保證統(tǒng)一呢?我們是通過(guò) ts 作為 dsl 來(lái)描述文檔和接口,然后編譯成 java、oc、markdown 等,通過(guò)這種方式完成了多端 api 還有文檔的的統(tǒng)一、可編譯。
除了這些,還有依賴(lài)分析工具,分析所有跨端引擎相關(guān)的源代碼,包括安卓、ios、c++、js 代碼,提取各種數(shù)據(jù)供分析。
跨端引擎是 c++、安卓、ios 負(fù)責(zé)維護(hù)的,而編譯器、ide、調(diào)試工具、依賴(lài)管理工具、多端 api 和文檔統(tǒng)一工具、依賴(lài)分析工具都是我們前端同學(xué)維護(hù)的。我入職這一年就在維護(hù)這些。
我這一年做了什么
其實(shí)仔細(xì)一看就會(huì)發(fā)現(xiàn),擴(kuò)展 js 引擎、源碼到源碼的編譯、ts 轉(zhuǎn)多端代碼和文檔、依賴(lài)分析等都和編譯技術(shù)強(qiáng)相關(guān),這一年我在前端領(lǐng)域的編譯技術(shù)方面的提升特別大。
我做了編譯器的 sourcemap 的統(tǒng)一:
之前編譯的每一步都是割裂的,也就是每一步都是 js/ts 代碼 parse 成 AST,轉(zhuǎn)換成新的 AST,再生成 js 代碼和 sourcemap 這樣來(lái)一遍,但沒(méi)有對(duì)每一步產(chǎn)生的 sourcemap 做關(guān)聯(lián),這就導(dǎo)致了最終跑在跨端引擎的代碼并不能通過(guò) sourcemap 映射到源碼。
我修改了整個(gè)編譯流程,每一步都把 AST 傳遞下去,這樣修改完一遍之后再生成 sourcemap,這時(shí)候的 sourcemap 就是能映射到源碼的,可以直接調(diào)試源碼。
我做了依賴(lài)安裝工具的升級(jí):
最初的依賴(lài)安裝工具是分析 bundle.json,遞歸解析依賴(lài)然后下載到 xxx_modules 目錄下,并沒(méi)有做全局的緩存,這就導(dǎo)致一個(gè)依賴(lài)的多次下載耗時(shí)是一樣的。而且我們會(huì)修改下載下來(lái)的依賴(lài) bundle,多個(gè)項(xiàng)目的同個(gè) bundle 需要分別做修改,不能只修改一份。
我做了全局緩存,第一次下載會(huì)把依賴(lài)緩存到全局目錄,然后復(fù)制到本地,后續(xù)下載該依賴(lài)直接從緩存拿,提升下載速度。我做了依賴(lài)提升到父級(jí)目錄,然后 link 到本地,這樣多個(gè)項(xiàng)目修改的是同一份 bundle。
我做了 css 的智能提示和顏色預(yù)覽:
跨端引擎支持的 css 是 w3c 標(biāo)準(zhǔn)的子集,而且也有不一樣的地方,業(yè)務(wù)開(kāi)發(fā)同學(xué)需要經(jīng)常查文檔,一不小心就寫(xiě)錯(cuò)了,受這些影響,寫(xiě) css 的效率是不高的。
于是我做了編譯器的 css lint 功能,可以在編譯期間檢查出錯(cuò)誤,后來(lái)想,為什么不提前到寫(xiě)代碼的時(shí)候呢?于是又做了一個(gè) vscode 插件,基于 language service protocol 實(shí)現(xiàn)了語(yǔ)言服務(wù),支持 css 的提示、錯(cuò)誤檢查、hover 時(shí)展示文檔,這樣免去了查文檔。還做了一個(gè)顏色預(yù)覽的插件,給我們支持的一些顏色常量直接展示顏色,比較直觀。
我做了 api 和 文檔生成工具的升級(jí)
我們是通過(guò) ts 的 namespace、module、function 等語(yǔ)法描述接口,然后編譯成 java、oc、markdown 等的文件來(lái)做多端 api 和文檔統(tǒng)一的。我們做了一個(gè)命令行工具,解析配置文件指定的 ts,對(duì) AST 做一系列分析,之后生成各種代碼和文檔。
我擴(kuò)展了語(yǔ)法的支持,實(shí)現(xiàn)了 enum、interface、class 等語(yǔ)法的解析,使接口描述方式更多樣。修改了 markdown 文檔的格式,使之更易讀。還做了本地預(yù)覽功能,可以本地生成 markdown 來(lái)看效果,之前是不支持的。
其它
這一年主要是做這些,當(dāng)然還有其余的一些功能,編譯器的、ide的、等等。其實(shí)一年下來(lái),我對(duì)前端領(lǐng)域的編譯相關(guān)技術(shù),包括 babel、typescript、postcss、eslint、terser 等都有了比較深的掌握,對(duì) node 也更得心應(yīng)手。
除了工作以外,我還寫(xiě)了 《Babel 插件通關(guān)秘籍》 的小冊(cè),去早早聊、字節(jié)、掘金、華為等做了一些分享,創(chuàng)立了“神光的編程秘籍”的公眾號(hào),寫(xiě)了很多原創(chuàng)文章。也定下三年內(nèi)寫(xiě)一本前端編譯的書(shū)的打算。
離職原因
其實(shí),我對(duì)現(xiàn)在的工作內(nèi)容和學(xué)習(xí)狀態(tài)是非常滿意的,但我還是選擇這個(gè)時(shí)候離職了。
為什么呢?這就涉及到了一個(gè)支線劇情。
二月份的時(shí)候,我在知乎問(wèn)了一個(gè)問(wèn)題:前端轉(zhuǎn) c++ 編譯器開(kāi)發(fā)靠譜不?因?yàn)楫?dāng)時(shí)發(fā)現(xiàn)自己對(duì)編譯技術(shù)很感興趣,但是因?yàn)楸旧黼x這個(gè)比較遠(yuǎn),不知道該怎么過(guò)渡。

得到了很多大佬的建議,其中有華為的楊海龍大佬。我之前也去華為的 deeplang 社區(qū)做過(guò)分享,講前端領(lǐng)域的編譯技術(shù)。然后也加了編程語(yǔ)言實(shí)驗(yàn)室負(fù)責(zé)人的微信。
就在最近,華為的編程語(yǔ)言實(shí)驗(yàn)室那邊聯(lián)系我說(shuō)那邊開(kāi)放了一些崗位,問(wèn)我是否感興趣。
我想了下,如果我繼續(xù)在某公司待下去,后面的故事應(yīng)該是這樣的:
陸續(xù)寫(xiě)了 eslint、typescript 源碼、postcss 等小冊(cè),寫(xiě)了 vscode 插件小冊(cè),兩年后寫(xiě)了一本前端編譯的書(shū)。工作上對(duì) vscode、編譯相關(guān)工具、調(diào)試相關(guān)工具更加熟悉了,做了很多重大功能,然后成功晉升 p7,在社區(qū)也積累了一定的影響力。
這些是確定性很強(qiáng)的。
如果去華為,有這樣三點(diǎn)不一樣:
去中國(guó)最頂尖的編程語(yǔ)言和編譯器團(tuán)隊(duì),能夠大幅提升編譯相關(guān)技術(shù)的理解和掌握,除了一直做的源碼轉(zhuǎn)源碼的轉(zhuǎn)譯器的小打小鬧,還能深入解釋器、編譯器等技術(shù)。這些在某公司是接觸不到的。
可以深入 c++ 等幾門(mén)編程語(yǔ)言,自己學(xué)和在公司里寫(xiě)相關(guān)代碼是不一樣的,那邊有場(chǎng)景可以深入使用 c++,可以轉(zhuǎn)型成 c++ 工程師。
那邊做的也是編譯的事情,雖然估計(jì)不是寫(xiě) js 代碼,但思想不會(huì)差很多,這樣我打算寫(xiě)的前端編譯相關(guān)的小冊(cè)和書(shū)并不需要丟下,可以繼續(xù)搞。
但是去華為是不確定性很強(qiáng)的。
先不說(shuō)我能不能順利通過(guò)算法面試,順利去了的話也不一定能夠干好,而且那邊團(tuán)隊(duì)很多碩士博士,很多國(guó)內(nèi)外頂尖大牛,我去了大概率只是一個(gè)小透明。
但是,我還是打算拋棄在某公司的未來(lái),去華為探索新的可能性,人生就是要有一些不確定才精彩,不是么?
所以,我在某大型電商一年的時(shí)候,離職了。
未來(lái)
后續(xù)公眾號(hào)會(huì)寫(xiě)一些 c++,寫(xiě)一些編譯的內(nèi)容,這些和前端的關(guān)聯(lián)性不大,但我會(huì)盡量和前端關(guān)聯(lián)起來(lái)寫(xiě),也會(huì)盡量寫(xiě)的通俗易懂一些。感興趣的同學(xué)可以繼續(xù)關(guān)注。最近一段時(shí)間我就不恰飯了,專(zhuān)心寫(xiě)技術(shù)文章了,因?yàn)榭偢杏X(jué)突然轉(zhuǎn)型對(duì)公眾號(hào)粉絲不太負(fù)責(zé)。
這就是我這一年的某公司經(jīng)歷和我離職的原因。
站在 2021 年的 10 月 20 往前看,未來(lái)依然還是充滿著不確定性,但也充滿了希望,繼續(xù)加油吧。
