大前端時代以及即將到來的5G
時代,3D
可視化,音視頻直播技術,IM
即時通信場景應用我以爲都是大有可爲的。前段時間爆款換臉應用出現,到近段時間頭像加🚩的火爆,這是好事。
不知不覺,九月就要過去,因爲這個月工做上,被C++
折磨得很難受,並且其餘時間都在學習,因此沒有時間寫文章,好在技術提高很大。今天準備好好談一談重型應用的架構以及技術選型,爲接下來個人正式架構設計作個鋪墊。前端
web
前端,只能發個ajax
請求,畫畫頁面。了不起寫個webApp
winter
老師,我自我感受已經良好,可是迷茫了。他回懟了我:想想你用你的技術作出了什麼nb
的東西把。例如微信,QQ
,Telegram
, 以及一些工具類的應用react
說到這些你們確定以爲,爲何不說是遊戲? 固然遊戲也算,但是我相信作出1000萬人天天都在用的產品是你們的夢想,起碼能吹一生吧linux
工具類的東西實際上是最難作的,好比vsCode
, Excel
,PhotoShop
這些。這也是爲何這麼多年出現成功的工具類產品這麼少。這裏不得不提到vsCode
,它其實就是用ELectron
開發,基於TypeScript
。固然確定使用了很多C++
插件,說到這裏,留下傷心的眼淚,最近也是被折磨得很難受git
QQ
開發了十幾年,你根本不用出去找工做,固然你應該也不會跑hold
住React-native
,可是你們有所瞭解的都應該知道,這個框架雖然生態比較成熟,可是在面對衆多手機的適配難度,以及性能方面存在的缺陷,若是用它製做重型應用我以爲是不合適的,若是要作重型應用,移動端應該使用原生。PC
桌面端,而國內首先考慮的是移動端。國內移動端開發人員,在我看來已經人目前已經夠多了,若是說你如今不會React-native
和Flutter
,我也不建議你去深刻學習,特別是Flutter
.
爲何要這麼說?程序員
React-native
剛出來的時候,坑多吧。如今Flutter
也是,但是當你從RN
最初的版本踩坑踩到如今,以前踩的坑大都沒有意義(說這些話想過被噴,可是...此處省略一萬字,建議去了解下原理和基本使用,不要耗費太多時間)github
一個技術你去使用,並非它多流行,只要它足夠流行。 ---來自某位國內大佬
技術的學習,應該多往底層鑽研,若是你走錯了路,鑽錯了方向,浪費了時間得不償失,我以前有說過,前端最核心的幾個基礎知識點,應用層的東西曆來不會很難。前提你的基礎足夠紮實web
前端20個真正靈魂拷問,吃透這些你就是中級前端工程師 【上篇】面試
前端20個靈魂拷問 完全搞明白你就是中級前端工程師 【中篇】ajax
前端20個靈魂拷問 完全搞明白你就是中級前端工程師 【下篇】數據庫
這些文章不少同窗應該都看過,爭議也很大,在我如今看也寫得很爛,可是它裏面的知識點是夠的。固然你必需要去結合起來,而後深刻學習每一個知識點。
既然說了移動端沒有合適的重型跨平臺應用開發框架,那麼只有PC
端了。還有多少小夥伴在PC
端開發呢?
Electron
開發,來了我不止一次提到過這個框架,我以爲它真是一個很是棒的框架,爲何這麼說呢?
APP
,不會寫原生,那麼你確定達不到某種境界。由於你始終有不少不少的黑盒過程,但是Electron
就會大大下降這個機率。linux
和Mac
以及Windows
三者均可以運行,除了Mac
上某些特殊場景須要本身設計下菜單快捷鍵之類,以及一些文件IO
等MAC
默認行爲Node
版本、運行的V8
環境以及最新的谷歌瀏覽器一塊兒被打包,最新的技術和API
均可以用,無需適配擔憂兼容性,真正放飛自我,能夠隨時隨刻用Node.js
實現功能,甚至調用大量C++
插件,著名的VSCode
就是這樣而來你甚至能夠當作Electron
給web
網頁套上一層殼,你能夠在主進程寫你的Node.js
去實現功能,渲染進程你怎麼寫怎麼寫,還能夠呼叫封裝好的原生接口。遇到特別複雜的需求,用C++
插件去實現吧
最終打包出來的安裝包跟正常的桌面應用是同樣的,正常安裝卸載等,都已經封裝好。
目前GitHub
上已經有77.2K
的star
應用層面的東西,大都不會太難,Electron
的文檔已經很是全面,基於它出現了不少複雜,並且成功的工具類重型應用。我相信它
whatsApp
也是基於它,國外還有一些很NB
的應用也是。這裏不作過多闡述,能夠肯定它是一個成熟並且成功的框架
可能不少人看到這裏又要說標題黨了,別急,下面來乾貨。
一個好的開發,它必定能懂一些產品,甚至測試,固然他也應該會炒河粉,35歲之後好維持生活
咱們今天舉一個例子,IM
,即時通信,Telegram
,20萬人超級羣端到端加密的核心賣點產品
電報Telegram
:
如今回答上面三個問題:
項目自己的最重要功能是什麼
答案:即時通信,信息的收發
項目自己出發點是爲客戶提供什麼方便
使用產品進行消息傳遞
項目的核心競爭力是什麼
20萬人的超級羣,端到端加密,隱私足夠安全
核心競爭力,每每表明了這個應用產物的技術最難點,由於誰都能作,那麼就不是核心競爭力了
因此咱們其餘的都忽略,關注第三點,開始進行技術選型,架構。
Node.js
和JavaScript
重型應用架構設計要想寫好這個架構,我以爲你首先在自身的擅長領域不能有太多的黑盒過程。例如框架源碼,庫原理實現,瀏覽器和Node.js
的事件EventLopp
以及他們的缺陷,你要熟知在心。由於像這種應用,一個小方向可能就會掏空你的技術棧,耗盡你的精力,例如音視頻、圖片處理等。
單線程的Node.js
以及js
主解析引擎,讓咱們又愛又恨。
這款應用的核心競爭力,是20萬人超級羣,那麼數據量很大,大批量渲染壓力和頻繁加解密計算耗時、頻繁數據庫寫入壓力都是不可避免的,那麼咱們的Node.js
擅長異步非阻塞,以及前端渲染進程的異步就顯得尤其重要
前端架構總體的核心除了技術選型以及大致框架外,就是任務調度。
這裏的任務調度分兩種:
1.渲染任務調度
2.非渲染任務調度
1.React
框架中,屢次傳入對象,setState
會自動合併到一次執行,其實就是一種節流思想
2.React
的Fiber
架構思想,把若干個任務分割成多個小任務執行,中間根據你的任務優先級安排去選擇時機執行
3.淘寶的分片渲染方案,跟上面第二條有一些相似
我以前說過,應用層的東西都不難,只要你基礎足夠紮實,能手寫出簡單的框架,以及庫。你絕對能很是輕鬆應對前端百分80以上的性能問題和需求,技術最終都是類似的
上面只是說了別人的一些比較簡單的優化方案,下面纔是開始咱們本身的渲染任務調度:
回到咱們的Telegram
架構設計方案:
渲染任務架構過程須要着重考慮的幾個問題:
1.渲染數據量特別大
2.更新特別頻繁
3.儘量手動回收垃圾,避免消息量過大,v8
垃圾回收的時間不肯定性致使內存被白白佔用,引發卡頓
4.考慮大批量數據到達渲染進程的用戶應用體驗,肯定用戶交互屬於高優先級任務,其餘的哪些是低優先級-但必須執行的任務,哪些是中優先級任務,這裏說的任務,都是渲染任務。
今天在學習一篇小冊,裏面有一句話引發了個人共鳴,在計算機的世界,若是有解決不了的問題,那就加一箇中間層,若是還不行,那就加兩個。 -後面這句是我加的
這個是我本身編寫的React
: mini-react源碼地址
PReact
源碼中,是將須要更新的組件放入隊列中,而後一次清空,僞代碼:
if (setStateQueue.length === 0) { //清空隊列的辦法是異步執行 defer(flush); } setStateQueue.push({ stateChange, component }); function defer(fn) { //requestIdleCallback的兼容性很差,對於用戶交互頻繁屢次合併更新來講,requestAnimation更有及時性高優先級,requestIdleCallback則適合處理能夠延遲渲染的任務~ // if (window.requestIdleCallback) { // console.log('requestIdleCallback'); // return requestIdleCallback(fn); // } //高優先級任務 return requestAnimationFrame(fn); } while ((component = renderQueue.shift())) { renderComponent(component); }
上面這段代碼其實很重要,核心思想就是:
每當進入這個函數,若是發現隊列隊列裏沒有任務就去執行defer
函數
defer
函數執行是異步,此時defer
下面的setStateQueue
已經被push
了進去數據,這樣達到一幀完成一次渲染任務調度
固然上面僅僅一個小的任務調度,這個必需要了解,才能往下看
requestAnimationFrame
和requestIdleCallback
使用:
你須要深刻了解React
框架的Fiber
架構,這塊尤爲重要,是性能優化,任務調度的基礎,上面有提到,React
在每次diff
對比階段,將任務分割成若干個小任務,此時若是有RAF
和RID
的任務,就要考慮去執行了
RAF
的任務會每次在下一次小任務前執行
RID
的任務只有在下一次小人物前,有空餘時間纔會執行,因此它不必定會執行。(特別高頻必須執行的任務)
Fiber
架構配合單個任務分割已經介紹完畢,下面出思惟導圖出總體的任務調度
核心的兩點:
1.釋放主線程的佔用,讓用戶的操做最快獲得響應
2.合理調度任務,分高、中、低三種優先級別任務
理清思路:
1.數據經過IPC
通訊到達渲染進程
2.所有交給子線程去進行計算,組裝數據,經過異步的postMessage事件通訊,拿到渲染數據
3.調度渲染任務,用戶操做交互
4.釋放主線程
這裏特別提示,爲何我一直強調不要使用定時器,一旦應用變得很複雜,若是任務調度不合理,定時器裏的代碼是要好久好久才能執行的。固然,只有重型應用會這樣
渲染任務調度這塊,主要是微任務,RAF
,RID
分片渲染以及同步代碼,隊列調度等手段。
核心思想跟渲染進程大概一致:
1.儘可能釋放主進程,保持空閒,讓用戶的操做即時獲得反饋,由於不少操做會調用主進程的接口
2.異步調度任務,寫入數據庫異步,解密計算可使用nextTick
等方式去調度添加隊列
這裏提到,任務調度的核心一點就是,頻繁觸發的任務必須加入隊列,異步清空,不然像解密這種同步計算耗時,一旦被頻繁觸發就會引發阻塞。即便交給了其餘進程,也要作隊列
1.技術選型時,儘可能選擇本身熟悉它原理的庫,以及能用Demo
測試模擬場景的技術,測試經過再選用,不一樣技術之間解決問題出發點不同,可能會有衝突
2.隊列和多進程、多線程的開啓,並非必定須要的,你能夠本身設定一套規則,當一段時間的任務到達多少次被觸發時候選擇開啓多線程,多進程。不然就是浪費
3.重型應用架構遠不止這些,因此標題是淺談,等下個月技術做者再度飛速提高一波,再來談這些。
這裏推薦關注做者的微信公衆號:
前端巔峯
發送加羣,我會將你拉進segmentFault
的前端交流羣,不少小姐姐哦~
技術氛圍槓槓滴~ 關鍵漂亮的sf小姐姐
也在裏面哦~