閒魚易用高可擴的文章發佈工具建設

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"背景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"閒魚會玩社區是一個以分享個人趣味生活爲主的內容社區,在社區的運營過程中,經常有一些文章形式的內容在會玩廣場上投放。此前文章創作是在一個主要承載營銷搭建的平臺上完成的,這種方式首先不是專門爲文章場景服務的,導致搭建出來的頁面是一個靜態頁面,數據無法被理解,也無法進入審覈和分發鏈路。而且搭建工具無法對外使用,從而無法讓外部的創作者參與文章創作。因此,我們想從零開始開發一個能快速發佈且高可擴展文章結構形式的發佈工具。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/24\/24c03fe002fe6d50105d8ed7c9a28bdf.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"調研"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"業界也有許多同類型的產品,如常見的知乎、掘金、微信公衆號等。微信公衆號的文章無論從發佈體驗、消費體驗以及內容結構擴展上都做得很好。我們總結微信公衆號文章有以下幾個特點:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.文章內容形式豐富度高;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.瀏覽體驗極好;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3.支持第三方內容模版;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"閒魚會玩文章希望能在內容形式,瀏覽體驗上儘可能對齊微信公衆號文章的標準。但閒魚會玩文章與微信公衆號也有一定的區別,微信公衆號面向不同的自媒體,不同垂類的自媒體對文章的展示調性是不同的,因此對文章的內容樣式不會做太多限制,而閒魚的社區有着自己的調性以及自己的品牌主題色,內容形式會更加收斂。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/31\/319a01d1ceb0245a876921b2cecf0e51.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"目標"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"文章內容結構自由度高,內容排列可以是標題、文字段落、圖片以及交互組件(如投票器、鏈接卡片等)的排列組合,因此高可擴展性非常重要。此外,發佈器作爲文章創作入口,需要存儲創作者全部內容信息,包括字體、字號、顏色、段落、圖片等。還有展示頁在端上的性能體驗也是非常重要的指標。因此我們定了以下幾個系統的關鍵目標:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.信息還原度百分之百"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.內容結構可擴展"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3.展示頁秒開體驗"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"文章發佈鏈路大致流程如下所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0d\/0d61c59c9a6f6a53df648f6b33a8a21d.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"方案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圍繞既定的設計目標,如何實現呢?我們的方案是根據一套約定的schema協議來表達文章內容的所有信息,協議記錄和表達所有需要在客戶端還原展示的信息,最後通過這套協議把發佈器和展示頁連接起來。可以看出,設計一套通用、簡潔的文章內容協議是方案的關鍵。文章發佈器負責產生schema,結構化存儲後,文章展示頁獲取到該schema然後在端上解析協議並展示出對應的內容信息。方案大圖如下所示,標橘黃色表示協議相關的部分,它出現在了幾乎整個鏈路中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/c2\/c2cc22a584260ba82b1925587c2c7a1e.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"協議設計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"梳理出協議設計目標如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.規則簡潔易懂。規則越簡單,則根據協議創建schema數據以及解析schema數據就越容易。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.可擴展。未來的文章形式可以是非常豐富的,要求用這套協議表達任意的內容形式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3.結構化存儲。將圖文內容可以進行結構化抽取和存儲,文章內容的schema可能非常大,而數據庫存儲"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"字段一般會有字符上限,需要壓縮schema。此外文章的實體內容需要進入安全審覈鏈路,這也要求我們必須進行內容結構化抽取。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圍繞着以上三個訴求,我們我們基於釘釘的富文本協議,定製了一套符合要求的協議規則。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"協議邏輯"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/d2\/d263d0e9a6d946a3a839962fec6fb0d4.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"現有元素標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"•root - 根元素"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"•p - 正文標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"•span - 文字標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"•img - 圖片標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"•h2 - 二級段落標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"•card - 卡片標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"•idleVideoCard - 視頻卡片"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"現有屬性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.常規屬性"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/36\/3617a9a54b00c7c75e628d3453c4fdc0.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.圖片屬性"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/76\/76678dbc191f9c6aa55ae82d9d4a217c.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3.視頻屬性"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/3e\/3e1a85a5913cb6e77db2c3e5dd67c77c.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"如何擴展"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們規定未來所有新增的插件,都作爲一種子類的卡片,可以自定義卡片類型,卡片數據統一放到metadata字段中,然後端上根據卡片類型做對應的組件,並將metadata中的卡片數據信息作爲參數導入組件中去,從而做到未來任意插件,都能映射到協議裏。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"結構化存儲"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"協議是一種json schema,這種在關係型數據庫中存儲是一個比較頭疼的問題。圖文內容存儲會將內容分成三個字段,分別是文本、圖片數組和自定義擴展字段。文本和圖片的結構化信息會用於安全審覈以及算法推薦識別,自定義字段用來存儲業務上的其他信息。我們的第一版方案是將文本和圖片內容提取出來單獨存儲,並將整個json字符串全部放到自定義字段中,這樣只需要一存一讀就可以了。然而,真實場景中,自定義字段有字符數限制。因此需要對json字符串進行一定的轉譯和壓縮,只保留必要的樣式和排版信息即可。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/b1\/b1fab4df4fb15679c2120e989ad5f8e4.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"發佈器"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"發佈器的核心是一個富文本編輯器,市場上主流的react編輯器有開源的slate.js、facebook的draft.js,阿里內部比較成熟的富文本工具有語雀富文本編輯器和釘釘文檔團隊的we-editor。從協議的複雜度和可擴展性上考慮,我們選型了釘釘的we-editor。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/93\/93aed76795e698b5c0de207781defb96.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"富文本編輯器的使用上,除了要處理在編輯器上手寫文章場景外,從外部粘貼內容進編輯器的場景複雜度會更高。因爲內容本身就帶有富文本樣式,從而導致文章樣式不可控,生成的富文本協議內容混亂,不利於結構化審覈和端上展示頁渲染。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"粘貼場景處理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"粘貼進來的內容是帶上內聯樣式屬性的標籤,如div、span、a、h1、h2、img、video等。我們的做法是,在粘貼的時候,將所有的內聯樣式清除,並只處理格式範圍內的標籤。對於img、video標籤,則需要更多的處理,因爲img和video的src是一個地址鏈接,這些鏈接如果是站外連接,就會存在訪問跨域,同時對平臺來說也存在安全風險。做法是對站外資源做轉存處理,即將站外鏈接下載後通過內部服務將資源轉存到可靠的資源服務器上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/b8\/b8b84f1d180409742eeb9ab84588eee9.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"插件擴展"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"插件擴展通過定製編輯器插件來完成。我們只保留了基礎的redo\/undo、字體加粗、字體對齊、添加圖片等編輯器自帶能力,其他如視頻、連接能力通過自定義插件完成。通過對we-editor插件體系封裝,開發者可以像開發react組件一樣開發插件。封裝過程是將擴展插件都當作一種卡片,在schema裏指定工具欄內容,對應點擊事件,以及插入富文本的卡片樣式等,即可插入任意插件。以一個插入視頻的插件爲例:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ad\/ad60fcab22945a7ae29c3ae19dab6355.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"點擊該插件工具欄按鈕的時候,選擇插入idleVideoCard類型的卡片即可。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/b0\/b0bbfdec6588590df86afe6e3e6f53e7.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/58\/58c7f6f6c5dfefd33c3b3121971e1496.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"函數服務層"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在發佈器的發佈鏈路中,我們設計了一層faas函數服務層。主要考慮以下幾個原因。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.安全問題。結構化信息抽取算法應該放到服務端計算,否則會存在刷接口繞過安審鏈路的漏洞。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.抽取和還原都通過js實現。從而保證一套規則技術棧統一。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下圖爲大致的數據流轉示意圖:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1a\/1a0bd13feaa19938d6431ea3c9103ce6.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"文章展示"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"文章展示的原理是通過協議規則將經過處理的schema還原成真正的schema信息,並解析信息轉化成對應的可視化組件。我將重點講協議解析和性能優化。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"協議解析"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"理論上只要能正確解析出富文本schema協議表達的富文本信息,在端上可以還原成任意對應的設計規範,這也是未來我們可以做集團統一文章發佈工具的基礎。即只要保證協議一致,端上的展示可以大不相同。還原函數僞代碼如下所示:"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/d3\/d3ca11e7ecb9f87a475c888bb3028d03.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"體驗優化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前端的性能性能優化話題是一個老生常談的話題,限於篇幅有限,這裏只講這次在文章詳情頁的幾個主要優化方案。性能數據結果上,跨端首屏渲染時間從1700ms優化到1000ms左右,做到了秒開。先上優化前後效果對比:"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ba\/ba492fd399e478d06d6170047523ae27.gif","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在講具體方案前,我們先來看一下一個h5頁面在webview裏是加載流程:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ba\/ba28b28622593a9ec159cb76d0028a5e.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個鏈路中,最消耗時間的是各種資源的IO,包括頁面文檔的IO,樣式文件、js文件和圖片的IO以及數據接口請求的IO。其次耗時的是webview的啓動耗時。因此我們的優化主要圍繞減少IO以及提前IO的思路去進行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"資源combo"}]},{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"頁面加載中除了包含業務的js文件之外,還包含jstracker的資源,rax的框架資源,安全相關的js等,將這些資源合併成一個資源請求,則可以減少很多次請求IO,從而降低首屏渲染時間。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"圖片懶加載"}]},{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"文章中一般會有很多圖片,這些圖片大部分不會在第一屏中就出現,因此可以將未出現在屏幕中的圖片先不加載,等用戶下滑至該圖片出現在屏幕中時,才請求該圖片資源。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"本地資源緩存"}]},{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"文檔資源下載以及js資源一般來說是一個長時間不變的東西,如果這些資源提前在客戶端空閒的時候就已經下載好,等到請求這些資源的時候,客戶端發現本地已經有了同名的資源,就攔截這次資源請求,返回本地緩存好的資源,則可以大大降低首屏渲染時間。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"text","text":"數據預取"}]},{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"首屏渲染的時間長短有一部分取決於第一次調用的接口的返回速度,而接口請求一般要等到js邏輯觸發接口請求時才發出。如果首屏需要獲取的請求是一個確定的參數,那麼是否可以將請求接口這個時機提前呢?我們數據預取的方案就是在用戶點開頁面的請求URL中就帶上首屏需要請求的接口參數,然後客戶端獲取到這個參數後異步地請求這個數據,將結果緩存到客戶端上。等到js邏輯需要發出請求的時候,判斷當前請求是否已經被請求過,若請求過,則直接返回緩存在客戶端上的接口數據。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":9,"align":null,"origin":null},"content":[{"type":"text","text":"去掉客戶端loading"}]},{"type":"paragraph","attrs":{"indent":0,"number":10,"align":null,"origin":null},"content":[{"type":"text","text":"客戶端loading本來是webview自帶的能力,表示當前頁面還有資源在加載,但其實雖然有資源在加載,但首屏的頁面信息其實已經加載出來的。去掉客戶端的loading,可以給用戶帶來更快的體感,雖然實際上並沒有加快這個流過程。優化後的加載流程如下圖所示:"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/b2\/b273e5c05a56912f473b61f83df321f1.png","alt":"圖片","title":"null","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"性能優化無止盡,因此文章展示頁的優化也會一直做下去,可以考慮提前啓動webview容器,ESR、NSR等方式優化。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"展望"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到目前爲止已經完成了文章發佈工具從0到1的建設,未來需要做的事情還有很多。基於這套高可擴展的協議,可以擴展出更多更豐富的文章內容形式以及交互玩法,如投票器、彈幕、文章模版等,最終可以沉澱出一套可開放的基於當前協議的模版插件開發體系,以適應不同的文章內容體系。此外,性能體驗優化會繼續以高標準的要求不斷進行優化。 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再往上層看,文章內容只是會玩社區內容的其中一種承載形式,我們希望有一個包含更多創作能力的創作者站點工具。pc側的創作者中心和手機端上的創作者發佈中心呈一個互補的態勢。普通的創作者更傾向於即來即發,隨手發,隨時發,而對內容質量有更高追求的一些pgc創作者則更關注內容質量,發佈效率,內容消費數據等比較專業的指標。 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此在完成了基本的發佈能力後,我們會逐漸完善整個創作者發佈鏈路,集普通圖文創作、視頻內容創作、文章創作、內容管理、數據中心、熱點內容發現於一體的完整專業創作者發佈工具。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文轉載自:閒魚技術(ID:XYtech_Alibaba)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文鏈接:"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s\/-zUzA_mg0wZkZA_6_qP56g","title":"xxx","type":null},"content":[{"type":"text","text":"閒魚易用高可擴的文章發佈工具建設"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章