主頁 > 企業開發 > 智能可視化搭建系統 Atom 服務架構演變

智能可視化搭建系統 Atom 服務架構演變

2020-09-23 18:40:42 企業開發

作者:凹凸曼 - Manjiz

Atom 是什么?Atom 是集結業內各色資深電商行業設計師,提供一站式專業智能頁面和小程式設計服務的平臺,經過 2 年緊湊迭代,專案越來越龐大,需求不斷變更優化,內部邏輯錯綜復雜,維護成本急劇拉升,同時,Atom 將要承載的業務越來越多,要向更多的內部用戶和商家提供服務,為了適應這些變化,架構升級成為當時緊迫的事項,我們將解構服務端模塊,讓服務輕量化、模塊化,更便捷地拓展業務場景,

Atom 服務端經歷了三個版本的迭代,本文著重剖析第三個版本,

架構 1.0

這是 Atom 最古老的一個版本,在這一版本中,只規劃了頻道頁的功能,目的是把開發人員從繁復的頻道頁開發中解放出來,因為功能目的純粹,所以系統復雜度較低,服務端直接使用了 Koa 框架上手開發,這是一個單體架構的服務,所有的代碼都在一個行程中運行,

在部署方面,運用的是非常原始的手工操作:開發人員登入機器,拉取代碼后進行類似本地環境的安裝啟動,然后在不同機器重復這個程序,

另外,Quark 的舊版本使用的是具名組件,具名組件一定程度限制了 Quark 自身的擴展性,這里不作展開,

架構 2.0

從頻道頁搭建平臺到多場景頁面搭建平臺,Atom 用了不到一年時間,更豐富的組件,更多的模板,更多的場景,更多參與進來的設計師,更多的用戶,產品開發逐漸專業化,簡單的手工運維已經不再適用,于是前端和服務端都進行了一次大換血,服務端用 Salak 重構,Salak 是個非常好上手的服務端框架,同時為我們帶來了介面檔案的自動化生成功能,前端和服務端都改為依靠 Talos(一容器式部署內部平臺)來部署,服務端逐漸邁入工業時代,

然而,這個階段仍然沒解決粗放的開發方式,缺乏宏觀上的規劃,日益暴露了以下這些問題:

  • 高度集中

    90% 以上服務集中于一個單體架構中,業務越來越復雜,代碼量越來越大,代碼的可讀性、可維護性和可擴展性下降,開發人員接入成本劇增,業務擴展的代價成指數上升,持續交付能力難以維持,隨著用戶越來越多,程式承受的并發越來越高,單體架構的應用的并發能力有限,由于系統復雜度的提高,測驗的難度也越來越大,

  • 耦合度高

    單體中的各個模塊間互相依賴,互相影響,互相掣肘,導致代碼重用性低,新功能開發往往由于忌憚耦合邏輯中的隱藏彩蛋,而選擇重新撰寫,這不是我們希望看到的!

  • 邏輯混亂

    除了耦合導致的邏輯混亂,Atom 作為一個從零成長起來的平臺,本身就淤積了大量的歷史需求,有些是不再使用的,有些是幾乎不被使用的,這些代碼邏輯給開發人員一個極大的挑戰:在進行代碼維護的時候不敢輕易改動代碼,另外在迭代中需要向下兼容,讓服務端有沉重的歷史包袱,

  • 代碼冗余

    由于框架在前期沒有定義好規范標準,在開發程序比較嚴格遵守代碼校驗,代碼的邏輯、常量等等重復定義,這也同時讓專案變得難以維護,比如修改一個常量需要在保證沒有遺漏的前提同時修改多處,

新架構目標

根據原有架構的優劣,我們設定了本次架構升級的目標:

  • 服務模塊化
  • 服務通用化
  • 插拔式站點
  • 插拔式場景
  • 標準與規范

名詞解釋:

  • 站點:即把服務端與平臺解耦,從原來的服務即平臺,到可以為互相隔離的多個平臺提供相同的服務,

站點

  • 場景:為應對不同業務型別而設定的概念,不同場景有不同的管理方式和流程等,

整體架構

整體架構分為 Web 應用層、介面層、服務層 和 資料層 4 部分,這樣拆分能做到入口統一,在部署上的單點部署讓發布更加的便捷,獨立部署則降低對服務整體的影響:

  • Web 應用層:包括 Atom 平臺及其他的平臺應用
  • 介面層:提供網關服務,應用層的請求經由網關作權限控制及請求轉發
  • 服務層:
    • 服務通信:異步通信使用 MQ,RPC 通信使用 HTTP
    • 業務模塊:核心代碼,拆解眾多小模塊應用
    • 基礎服務:統一把控用戶與權限
    • 服務管理:提升服務的穩定性、健壯性、靈活性
  • 資料層:核心資料存盤

整體架構

其中網關作為整個服務端的流量入口,對所有流量進行處理,攔截非法請求,決議登錄態并傳遞到下游,校驗介面權限以及超時回應等,統一把控,同時減輕下游的壓力,

網關

實施

計劃/籌備/評估

在正式進入升級開發前,小組通過會議探討架構升級的必要性和可行性,促使我們進行升級的直接原因是平臺新增的站點需求和場景需求,如要在原有架構上實作這個需求,勢必會在原已混亂的邏輯上增添更多的耦合邏輯,而間接原因,亦即升級必要性,則是要讓系統模塊化、標準化、通用化,讓系統的邏輯更加清晰,提升整個系統的可維護性,

經過我們反復的探討,對原系統按照功能進行分割,在功能的基礎上再按照通用性進行進一步拆分,附加新架構的支撐性作業,評估這些作業的作業量和預計用時,最后對任務進行分配下達,

實施

模塊化

為什么要模塊化?隨著平臺越做越大,我們想要讓各個部分的功能更加獨立、明確、清晰,把各部分之間的影響降到最低,對各部分單獨運維,避免牽一發而動全身的情況,

這次升級按照功能和通用性把專案劃分為 10+ 個模塊:如專門負責編譯的模塊,專門負責模板管理的模塊,負責定時任務的模塊,作為入口的網關等等,

其中拆分出來若干通用服務,通用服務作為獨立于 Atom 系統之外的服務,可以為 Atom 以及其他系統提供服務,

模塊劃分

對專案進行模塊拆解,最為頭疼的是斬斷關聯邏輯,模塊的剝離和修復必然會導致一個問題——相同的代碼在不同的模塊重復出現,為了解決這個問題,我們把部分這些代碼放到工具 npm 包中,這些代碼包括了:常量、TypeScript 型別定義、權限映射、Mongoose Schema 定義、Salak 插件和工具方法等等,

另一個問題,在原架構中,模塊間可以通過代碼直接呼叫,那新架構中如何“還原”這個功能?為了保證解耦度,新架構中僅有少數需要即時呼叫的功能在模塊間通過介面進行直接呼叫,其他的都是通過 MQ 訊息佇列和資料庫進行互通,

對于 MQ 通信,這里舉個例子:編譯,服務端編譯通常需要的時間比較長,長時間占用連接對服務性能有所影響,而且編譯結果并不需要同步回應,對編譯模塊來說,如果來者不拒,對服務有不小的壓力,于是我們決定使用訊息佇列來完成各個模塊之間的通信:

  1. 由專案模塊通過介面直接呼叫發布模塊發起發布操作;
  2. 發布模塊向訊息池推送一條“我要編譯”;
  3. 編譯模塊接收到訊息后由自身情況判斷是否可以進入編譯,否則先不予以回應;
  4. 編譯的各個狀態也通過訊息推送;
  5. 最后專案模塊在接收到編譯狀態的訊息后作各種處理,

編譯訊息

通用化

前面提到在模塊化的作業中,我們拆出了 4 個通用的服務模塊,通用服務獨立于 Atom 系統之外,可以為 Atom 以及其他系統提供服務,模塊的通用化是出于兩點考慮:

  1. 豐富部門的服務,減少重復開發功能
  2. 排除 Atom 非核心代碼,讓系統瘦身

伴隨而來的一個問題值得我們思考,如何考量一個功能是否值得抽離通用化?我們應該盡量避免陷入一個誤區:系統模塊化就是把系統拆得越細越好,如果拆分過細,勢必增加運維作業量,在拆分模塊的時候,我們考量的是一個模塊內的功能是否完整且獨立,以及部門或公司對這個通用服務的需求度,真正地做到低耦合高內聚

標準化

代碼層面,下面做了個簡單的對比:

對比項 舊架構 新架構
主要語言 JavaScript TypeScript
代碼檢測 未遵守 必需
介面名稱 花樣百出 統一形式
介面輸出 百花齊放 統一形式

TypeScript 的好,前端人都知道,它為我們帶來了自動補全、可選的型別系統,使我們能夠用上更加新的 JavaScript 特性等等,更多可以參考《為什么選擇 TypeScript》,出現后面三點的原因是什么?舊架構經歷了從零到一的程序,專案在最初規劃欠缺以及中后期沒有足夠的時間對系統進行修正,時間和需求的變更的雙重作用導致代碼淤積,

為此,我們在新架構的開發中就強調代碼的標準化,對每次提交都要經過代碼檢測,然后是對五花八門的介面進行統一:

  • 介面路徑統一:舊架構中,一個串列介面的路徑可能是 /xxx/list,也可能是 /xxx/xxxes 等等,我們在新架構中基于 RESTful API 規則,用資源名詞組成的路徑和語意化的 HTTP 協議統一介面的定義;
  • 引數名統一:比如串列入參中每頁數量可能叫 pageSize 也可能叫 count,于是我們把它統一成一個名字,要求在開發中遵守這個約定;
  • 輸出統一:在資料輸出到前端前對資料進行處理篩選,剔除包括 _id__v 等無關資料,在輸出形式上也做了統一,要求輸出中所有的 _id 都替換以 id 的名字出現等等,

Behavior

代碼標準化的好處是讓代碼更加好維護,開發人員很快就能定位到對應的介面代碼,對前端而言則減少對介面的識別記憶,

插拔式站點

前面提到,這次架構升級的直接原因是站點需求和場景需求,如果在舊架構下迭代站點需求,只會進一步增加耦合度,為此,我們增加了站點管理模塊,在幾乎所有的資料項中增加了站點欄位,給幾乎所有的資料庫查詢都帶上了站點引數,通過這些努力,現在新增站點只需要通過站點模塊新增站點,再做一些初始化配置即可完成,

站點概念除對 Atom 功能有了更高要求,也對原來的權限體系形成了新的挑戰,在升級前的版本中用戶的權限僅有一個集合,要實作每個站點擁有不同的權限只能從兩個角度出發:

  1. 權限含義拆分(為每個站點分別提供一套獨立的權限)
  2. 用戶權限增加一層抽象(用戶的權限改變為多個集合根據站點進行切換)

在比較了兩種修改形式后,拆分權限含義雖然在理解上比較容易代碼也改動不多,但卻大大提升了維護權限表的難度,相當于新增場景就需要增加一套權限,無法做到可插拔,最后在網關層增加了根據用戶訪問站點
切換權限集合的邏輯,

插拔式場景

場景是站點下面一個緯度,現有活動、頻道、心理學測驗、SNS、店鋪幾大場景,如果在舊架構下新增一個場景,需要排期進行開發,而且代碼上恐怕也會增加不少針對不同場景的 if-else,為了更便捷省心地擴展和維護場景,我們對場景相關的代碼從資源管理的角度做了拆解,

ATOM下每個場景擁有的資源主要有 模板/專案/標簽/權限 四種:

標簽       頁面
 |         |
模板------>專案

權限     

首先介紹專案模塊目錄的結構,專案模塊的代碼基于 策略模式 組織,每個場景的業務邏輯拆分到單獨檔案,由調度器直接呼叫,避免不同場景間邏輯摻雜,

  • 調度器檔案命名為 base_資源_service
  • 場景策略檔案命名為 場景小寫_資源_service
  • 通用策略檔案命名為 common_資源_service

當用戶查詢進來時,調度器根據查詢的條件直接呼叫對應策略檔案中的方法(一般不允許直接呼叫指定場景的策略除非確認不會關聯到其他場景的資料),當調度器沒有沒有找到對應場景下的策略時,默認會呼叫 common_service 的邏輯,所以各場景需要繼承 common_service,以頁面管理服務為例,調度器為 src/service/page 目錄下的 base_page_service,通用邏輯為 common_page_service,頻道頁場景邏輯為 ch_page_service

出于對場景下公有方法的統一抽象,服務中常用的 CRUD 方法介面 放置在 AbstractServiceClass 檔案中

├── src
│   ├── service
│   │   └── {resource}
│   │       ├── base_{resource}_service 策略檔案呼叫器,controller/mq 直接呼叫
│   │       ├── common_{resource}_service 通用策略檔案,例如串列查詢共用的引數處理
│   │       └── {scene}_{resource}_service 場景策略檔案,場景特殊的

部署

資料遷移

鑒于這次升級的巨變,在新舊版本間的切換務必慎重,除了前端與服務端為此做的大量的聯調外,我們還對資料進行了兼容性遷移,主要做法是通過遷移腳本把舊資料根據新架構的需要做多重處理,爾后寫入新資料庫中,

不中斷部署

在單體架構中,每一次服務的發布部署都會造成幾分鐘的空窗,

不中斷部署之前

為避免這種情況,在生產環境,我們保證每個模塊至少擁有兩個容器,在部署的時候,把部分容器從負載均衡摘除,然后回圈檢測容器是否還有流量,直至沒有流量進來才進行更新操作,服務啟動后重新添加到負載均衡,然后對剩下的容器進行同樣的操作,這樣做的好處是,保證了整個部署程序,服務是不中斷的,避免了部署程序中的空檔情況,

不中斷部署

運維

為避免再重蹈舊架構下糟糕的運維體驗及專案代碼管理,我們為新架構梳理了一個運維檔案,包括快速接入、開發、除錯、部署方方面面的細節都盡可能詳盡地記錄下來,

運維檔案目錄

為系統增加了監控,監控每個介面的性能和可用性,

方法性能監控

效果

經過這次升級,基本達成計劃中的效果:

  • 清晰:邏輯梳理、去除冗余、TS 重構、ESNext
  • 模塊化:解耦 10+ 模塊,獨立運作;HTTP、MQ、資料層等多通信方式
  • 標準化:強代碼規范;介面統一;回應統一
  • 通用化:4+ 通用模塊,平臺無關;抽取公共庫、配置、插件、中間件等
  • 易遷移:一鍵初始化;一鍵、單點、獨立部署;入口統一
  • 易擴展:+新增站點拓展能力;調整場景拓展;節省人力時間成本 95%+
  • 易維護:追加日志;一鍵部署;不中斷部署
  • 易對接:完備的 Joi 檔案;詳盡的介面變更記錄;盡可能的向上兼容

工具/方法/協作

工具對專案的順利進行有非常重要的影響,因此在這次升級中,我們嘗試了多種工具,

為了保證專案成員對自己負責模塊有清晰的了解以及對模塊的改造有明確的圖樣,團隊引入流程圖工具用于梳理舊架構的模塊并分工,梳理勾畫新架構各個模塊內部的邏輯等等,

梳理的內部邏輯圖

在排期方面,我們實踐使用到了甘特圖,用甘特圖按照模塊對任務進行拆分,然后指派給對應的負責人并設定計劃的進行時間,每天同步整體的進度,從甘特圖可以清晰地了解專案的資源分配與排期,也能看到專案計劃與實際的對照,有助于專案整體的進度把控,

甘特圖

甘特圖對專案升級的任務進行了初步的劃分,對于更細化的劃分,我們放到了 IssueBoard,IssueBoard 像是一個簡化版的任務看板,但對我們來說已經綽綽有余了,另外,選擇它的理由還包括:它支持跟 git 提交進行聯動,適合開發人員使用,可以通過每次提交來關閉相應的 Issue,

IssueBoard

總結反思

在這次升級程序中,也暴露了一些不足,主要體現在排期與預期以及在前期的溝通上,

  • 排期與預期

    在升級籌劃初期的排期過于樂觀,而且在升級程序中沒有再進行修正,當然這是客觀原因造成的,團隊要在有限的需求空窗期內完成升級以避免同時維護兩個版本,這導致的后果是團隊必須每天比計劃花更多的時間,

  • 溝通

    在服務端進行升級時,沒有跟前端溝通具體的細節,而這次升級又是非完全向下兼容的,所以在聯調的時候給造成前端一定的困擾和不便,

參考

  • Atom:https://ling.jd.com/atom
  • Salak:https://salakjs.github.io/docs/docs/zh-cn/introduction.html
  • RESTful API:http://www.ruanyifeng.com/blog/2014/05/restful_api.html

原文地址:https://aotu.io/notes/2020/04/21/atom-services-upgrade/


歡迎關注凹凸實驗室博客:aotu.io

或者關注凹凸實驗室公眾號(AOTULabs),不定時推送文章:

歡迎關注凹凸實驗室公眾號

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/113702.html

標籤:JavaScript

上一篇:CSS字體屬性

下一篇:Javascript判斷客戶端是Android還是IOS,判斷瀏覽器型別

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more