一、日常工作
1)開會
由於公司規模並不大,因此一有事情就會拉個會議,例如需要大會、技術評審、匯報周會、突發會議等。一周中大概有20%~30%的時間會花在大大小小的會議上。
公司會議難免會出現接鍋的情況,雖然自己不想做鍋靖,但是有些邊界定義比較模糊的鍋(既可以給后端,也可以給前端),在時間允許的時候,都會自己接下,因為服務端資源很有限,日常雜活太多,大家打工人都不容易。
雖然比較費時,但會讓自己有更多的參與感。公司辦公都是用mac pro最新款,攜帶也比較方便,開會的時候帶個筆記本,也可以在會議中處理一些工作的事情。
在團隊成員來齊后,每周五的10點,自己還會組織一個團隊短會,一般控制在30分鍾內。不是工作匯報,而是:
- 回顧一下本周遇到的難點或費時的事情,若還未解決,可在會議上當場討論思路。避免下次碰到又要花費太多精力。
- 發表一下自己這周遇到的困惑,無論是技術還是公司,都可以隨意發表。互相了解一下團隊成員的想法。
- 我也會傳達一些公司信息,例如本周或下周的重點任務、公司的新政策等,及時與團隊成員同步。
- 若有時間還會做個簡短的 Code Review,或者做技術分享,無論是當前前沿技術,或者是經典案例,都行。
2)任務分配
目前公司兩條產品線,加上我是3個人,他們各自負責一條線。若一些需求沒時間做的時候,我也會幫忙寫。
並且與組內成員要保持任務信息的同步,大家都得清楚現在做什么,未來還有哪些活需要處理。
新同學剛來沒多久,還在適應期,給他的任務都不是緊急的。當抽不出人手時,也會讓他搞,不過我和另一個同學也會協助他。
當有緊急需求時,我會將優先級不高的任務延后,並安排給合適的人處理。
自己除了開會之外,也要寫代碼,一些難弄麻煩費時的功能都留給了自己,例如那些跨團隊的、或是測試環境不容易部署的功能。
每天也會關注一下組員的進度,遇到問題可以幫忙出解決方案或應對策略,以免卡在一個地方,既影響心情,也影響開發進度。
3)錯誤調試
我們Web小組不僅維護着一個龐大的后台管理系統(前后台都做),還參與過許多后端服務(例如定時任務、金額結算)、H5活動頁面、微信公眾號、小程序等。
因此,很多時候線上出問題,都會與我們組有關。經常是某個人找到我,向我反饋問題,嚴重的話我就得停下手中工作,立刻去拍錯。
我花了很多時間去做各種錯誤調試,並且經常會出現跨團隊的場景,而我排錯的過程一般是幾步:
- 頁面樣式出錯,那毫無疑問是我們組的問題,除非那人看錯了,將客戶端的頁面報到了我們這邊。
- 若是調用的接口問題(所有的前端接口都會通過Node服務做一層中轉),那么會將接口路徑拿到VS Code中做一次項目搜索,查看代碼邏輯。
- 若內部核心邏輯是調用服務端內部接口,那么就需要將問題反饋給他們,再做聯調和定位是誰的問題。
- 若接口中的邏輯沒有調用內部接口,都是直接操作數據庫的,那么就要查找數據庫寫入的邏輯。若沒有,那么就去找誰在維護這張表。
之前就遇到過一個問題,說是后台的一張重要的統計報表沒數據了。查了半天,發現是一個定時任務在做寫入,而在這個定時任務中又會涉及MongoDB的寫入、客戶端的上報、第三方平台和服務端的讀取。在一一排除后,最終發現是服務端在寫入其中一個數據源時,日期寫的不對(由於時區的問題)。斷斷續續花了4天的時間,期間與運維、客戶端、服務器、測試還有第三方平台的技術人員先后做過溝通,這種排錯很費成本。
后面又遇到一個問題,也是與后台有關,說是一張統計表看不到了。這次也是先查寫入的代碼,發現沒有,馬上與服務端聯系,他們那邊也沒有。於是就找到測試組,因為他們組目前是公司內最了解整個管理系統的人,果然找對了人,他就說是AI算法組在維護的。找到他們之后,才查出是他們的一個定時任務掛了,怪不得沒有數據。之后在周會上,我就提出讓他們統計出自己維護的數據庫表,並且是那些與我們組相關的數據庫中的表。
4)完善文檔
文檔有兩大關鍵的意義:
- 第一個是幫助梳理思路,消除個體對於事物的不確定性。
- 第二個是傳遞信息,消除團隊中對於事物的不確定性。
先前的 WIKI 已有部分文檔,但內容非常分散,不成體系,我花了點時間重新梳理,並整理到合適的位置。
書寫之前沒有的文檔,尤其是現在比較重要的業務或功能,完善業務流程,甚至將相關的 SQL 查詢語句都整理了出來,方便調試。
邀請其他組的成員幫忙書寫相關的文檔,例如讓客戶端組完善 JSBridge 文檔,而測試組是目前掌握最多業務細節的人,讓他們幫忙寫些發生突發情況或意外故障的處理過程。
二、工作優化
日常的工作除了做業務需求(俗稱寫BUG)之外,其實就是發現問題,再解決問題,有時間的話,找出合理的優化手段,避免重復踩坑。
1)MongoDB可視化界面
若要查詢MySQL,可以借助DMS可視化界面。但要查詢MongoDB,那么只能先連上跳板機,然后再通過跳板機進入MongoDB服務器,這一來一回經常要耗上點時間。
因此,后面就着手自己寫了一個簡易的可視化界面,只提供查詢功能。Node代碼中的ORM系統采用的是Mongoose庫,那么就從其find()方法着手。
界面中需要傳入一個Model名稱,多行文本中只要傳入 where 條件即可,語法參考的是 db.collection.find(),下圖灰色使用了 <pre> 標簽,為了能在頁面中顯示空行和換行。
在后台管理系統中,原先有個查詢redis的界面,但只查了一個庫,數據類型也只列了4種,后面將庫修改為可配,並且新增了一個數據類型。
從而就能避免通過跳板機來讀取redis中的緩存,可直接在頁面中查詢。
腳本文件的執行,原先除了上傳代碼之外,還得進入服務器中,手動輸入命令執行。
這么操作略微繁瑣,自己做了點加工,做成半自動,代碼還是要發,不過在后台管理系統中有個按鈕,點擊后就能執行指定的腳本,下面是執行接口,調用了 fork() 方法。
router.get('/scripts/exec', async (ctx) => { const path = require('path'); const { fork } = require('child_process'); const exactPath = path.resolve(__dirname, 'scripts/index.js'); fork(exactPath); ctx.body = { code: 0 }; });
2)微信公眾號配置封裝
調用微信公眾號的JS-SDK之前,都是需要先引入配置文件的。先前的做法是先在前端腳請求一個接口,響應得到timestamp、noncestr和signature等參數。
然后調用wx.config()進行配置,最后在wx.ready()調用微信的onMenuShareTimeline()、onMenuShareAppMessage()等方法。
const wx = require("weixin-js-sdk"); const wxUrl = encodeURIComponent(location.href.split("#")[0]); getWeixin(wxUrl).then((e) => { wx.config({ // debug: true, appId: "wx....", // 必填,公眾號的唯一標識 timestamp: e.timestamp, // 必填,生成簽名的時間戳 nonceStr: e.noncestr, // 必填,生成簽名的隨機串 signature: e.signature, // 必填,簽名 jsApiList: [ "onMenuShareTimeline", "onMenuShareAppMessage", ], }); }); wx.ready(function () { wx.onMenuShareTimeline({ title: "", desc: "", link: "", imgUrl: "", success: function () {}, }); wx.onMenuShareAppMessage({ title: "", desc: "", link: "", imgUrl: "", success: function () {}, }); });
一旦需要用到微信JS-SDK就要調用這么一坨,但其實這些可以都放到服務端去執行。
后面我將上述配置封裝到后端的一個router方法中,路由成一個JS文件(例如bridge.js),前端只要調用它,然后傳遞一些參數做一些簡單的變量聲明即可,完全不需要配置appid、signature等參數。
3)后台管理系統界面優化
后台管理系統都會包含左邊的菜單欄,剛接手的時候,每次頁面刷新,菜單欄默認就會閉合,不會展開當前URL路徑所處的菜單。
在調試的時候,改一下腳本就會自動刷新窗口,一刷新菜單就會閉合,導致我要換旁邊的菜單時,又要一步步的點擊。
於是就着手開始優化,在查看代碼時發現,菜單數據被抽象成了多叉樹結構,而選中某個頁面的菜單,其實就是用深度優先算法來匹配指定路徑,下面用代碼簡單的實現了這個功能。
//深度優先 搜索當前菜單 let defaultSelectedKeys = [], //默認選中的菜單 defaultOpenKeys = [], //默認需要展開的菜單路徑 isFind = false; const dfs = (node, keys) => { keys.push(node.id); if(node.routers == props.path) { isFind = true; defaultSelectedKeys.push(node.id); defaultOpenKeys = keys; return; } node.children && node.children.forEach(value => { if(isFind) return; dfs(value, [...keys]); }); }; dfs(menuTree[0], []);
其實算法離我們平時的業務並不遠,只要用心發現就能挖掘出各類算法。
4)發布系統問題
公司買了第三方平台的一套發布系統服務,每次發布時,都會比較耗時,卡在某一步,少則7、8分鍾,多則10幾、20多分鍾。
向運維也反饋過很多次,但每次都沒有找到針對性的解決辦法。
最后無奈,只得和運維商量,在測試環境,自己寫個文件傳輸工具,直接把build后的代碼傳到指定目錄,跳過發布系統。
畢竟測試環境要經常發代碼,老這么延遲,實在是會讓人困擾。運維的意思是他們提供腳本,我們在跳板機上運行腳本,實現文件傳輸。
雖然沒有一鍵傳輸方便,但聊勝於無,總比干等好,同意了這個方案,后續跟進。
期間還碰到了另一個棘手的問題,那就是測試和正式環境的Node版本過低,比當前穩定版本低了6個版本。
這就導致很多庫不能直接安裝,得另想辦法或者用該庫比較老的版本。
現在也不能立馬更新,一更新就出錯,測試也沒有額外的資源幫忙一起調試。時間與資源的矛盾暫時還不能妥善解決。
5)性能分析日志
公司購買了阿里雲的日志服務,之前幾個純前端的項目雖然開通了日志服務,但並沒有妥善使用起來。
這次正好想到可以開通阿里雲的WebTracking的采集功能,將性能參數推送到阿里雲日志服務器中,參數搜集的庫采用了之前自己封裝的pineapple.js。
<head> <title>性能參數demo</title> <meta charset="utf-8"> <script> window.pineapple || (pineapple = {}); pineapple.param = { "token": "a0b923820dcc509a" }; </script> <script src="pineapple.js"></script> </head>
在參數搜集好后,就能借助阿里雲強大的查詢分析功能,分析頁面性能了,目前還沒想好分析維度。