之前主要說的是,我是如何產生這個圈子小程序的想法和如何上線的。有興趣的朋友可以回去參考前面兩篇文章。這次來給大家講講,在技術上是如何實現的。
如何快速把想法變成產品
分享作為獨立開發者經歷和一些上線經歷
技術棧
前端主要是基于Taro++dva框架實現的,后端基本上是以Ruby on Rails為主。
這里說下為什么要做這樣的技術選型,關于技術選型,在《奔跑吧,程序員》一書中有很詳細的分析,后面我會我在我的讀書筆記系列把這本書做一次分享。
這里主要說下技術選型主要判斷,如果是快速成型的項目,應該選擇更加輕量的語言和有大量社區組件支持的,另外一個就是自己熟悉的。
前端
為什么用Taro?主要是以往自身經歷決定的,以為本身我做了13年技術研發,雖然后面幾年自己動手的時間少了,但也算在一線工作。前幾年React Native剛興起的時候,對于有著js開發經驗和安卓開發經驗的我很快就上手。借著之前餓了么做hybrid和移動端動態模板渲染的經驗,讓我迅速理解了React的設計理念和原理。
所以這次就順利的用了以React為主的Taro前端開發框架,雖然uni-app大名鼎鼎,但畢竟要重新了解vue。原先redux那一套回憶起來相對比較快。這里不去爭論對錯,能讓你舒舒服服的快速完成,那么就是對的。
說回,記得以前寫js碰到最大的問題是無法提示,對于我們這種全棧開發來說,切換太快了,所以會花很多時間查他下面有哪些方法等,為了節省代碼量,有段時間還瘋狂的寫coffee script。雖然項目里寫的還不是很規范,但確實解決了我很大一塊問題。
看到這里肯定有人想說,那是你沒用對。就好像Vim、Emacs一樣,很多人覺得太方便了,為此我還專門花了時間去學vim的快捷鍵。但是最后用起來還是習慣不了,切換模式dd刪除,我還是比較喜歡在VS Code里用`command + x` 來當刪除用,十幾年的習慣,不是說改就改的。
還是那句,沒有對錯,只有你自己習慣就好。
后端
其實這幾年寫的比較多少的還是Java,但這里就不多說了,現在的項目也沒做過太大的壓測,但如果用戶量大到扛不住,那么再說甜蜜的煩惱問題。重新花時間調研了下Ruby on Rails,發現新增了很多特性,如Job、、Webpack、等等,對于全棧開發來說支持越來越好了。
最重要的是Ruby on Rails對測試的支持非常好,我個人習慣就是如果代碼沒有測試覆蓋,我很容易改出問題,因為時間久了或者對這塊業務不熟悉了,很容易有問題出現。
小程序
項目結構
先丟張基本的結構圖讓大家了解下
大概的流程是這樣的,這里不做過多講解,有興趣的朋友自己去看dva框架和redux。
下面主要這次開發圈子小程序碰到的一些問題和我解決的思路和方式,如果你有更好的,歡迎找我交流。
登錄
說真的,登錄是非常煩人的一件事。之前一直有一定的概率出現**Error: error::digital ::bad decrypt**,后來在官方的文檔中找到:
在 等返回加密信息的回調中調用 wx.login 登錄,可能會刷新登錄態。此時服務器使用 code 換取的 不是加密時使用的 ,導致解密失敗。建議開發者提前進行 login;或者在回調中先使用 進行登錄態檢查,避免 login 刷新登錄態。
所以后來我調整成
在進入頁面后,會進行一次login,然后把獲取的code保存起來當用戶點擊登錄按鈕,會再一次進行檢查,避免登錄態失效然后把獲取到的`code`, ``, `iv`全部提交到服務器進行解密和校驗
穿透問題
圈子小程序里有個功能,用戶可以評論某個人的帖子,然后會導致一個問題,就是底層的輸入框會在彈層上層。具體可以參考下面這張圖,我當時沒截圖。無論你怎么設置z-index都沒用。
導致這個問題的原因是,是原生組件,層級會高于網頁組件,所以我是這樣解決的。
當失去焦點后,把內容存儲到內存里隱藏,并顯示一個View填充之前緩存的內容
不過這樣做又會導致另外一個問題,有可能因為焦點問題,緩存里沒內容,用戶直接點了發送按鈕,這個時候就需要判斷提交的內容里有沒內容,有就直接提交,沒有就用緩存里的。都沒有就做非空提示。
還有就是有同學提到,輸入框會被鍵盤蓋住的問題。類似下圖
這里解決方式也相對比較好解決,參考官方文檔這個屬性
dva-model-extend和model層
往往在實現邏輯的時間發現很蛋疼的問題,就是幾個頁面邏輯差不多,但有有點不太一樣,然后這個頁面又耦合了一些其他模塊的邏輯。最常見的例如下面這個。
上圖里面幾塊業務就涉及了圈子、帖子、用戶、贊、評論邏輯,還有自己頁面的一些邏輯,那么我們應該怎么去劃分呢?大家可以參考下圖
業務基礎類
主要是負責通用邏輯實現的,比如獲取用戶相關的,帖子相關的等等,但他們沒有自己的,不能直接調用,只能作為基類存在。
業務類
就是負責通用業務真正被調用的,比如用戶類、帖子類等等。這樣做有什么好處,那就是任何頁面都可以去調用。
比如我想在帖子列表的頁面里獲取每個人的用戶信息,那么我可以直接一個user的type。他的邏輯相對標準。
界面類
就是為每個頁面提供特性服務的類,比如上面圖里,我有定制對帖子的返回內容要單獨存一個state,那么我就可以繼承基礎業務類,然后更改他的
的action實現。并且每個界面類都會關聯一個page。
數據類
為什么數據類單獨的?這有什么用。在前端,我們碰到的很大的一個問題就是,比如A頁面用了用戶信息,B頁面也用了用戶信息。如果按照以往的做法,每個頁面單獨維護一個用戶信息,然后通過來更新到每個頁面,這樣做的問題是大量的冗余數據放在內存里,然后event滿天飛,最后也不知道這個頁面的數據被哪個地方觸發改變了。
所以需要以前數據層來維護,有點像前端的內存關系型數據庫,界面拿到一堆ID,然后在要顯示的時候才會去數據層查詢具體的數據,然后渲染界面。
數據渲染
上面提到,以往我們都是直接渲染數據的,然后通過改。這樣還會碰到一個很麻煩的問題。
還是圈子小程序的例子,如果我要刪除一張帖子里的評論,我需要怎么做?
找到帖子該帖子的數據找到帖子里的評論數據因為評論可能是子評論,還需要在先找到上級評論后再找到當前評論。防止其他頁面數據未更新,發送事件通知其他頁面也需要重復一次以上操作
最開始一度讓我很奔潰,根本沒有辦法繼續持續下去,而且還很容易出問題,測試的工作量也倍增。
然后我找到了前端神器,這個庫可以幫我們完成上面數據層說的工作。具體流程可以參考下圖。
為節約篇幅,這里不做過多解釋。因為所有頁面都是引用性質,所以一旦數據發生變化,所有頁面都會跟著變化。并且處理數據只需要處理一層的關聯,不需要處理多層的數據結構,因為它幫你把數據進行扁平化處理了。
總結
上面分享了項目的基本結構、邏輯分層、數據處理的一些思路,相信應該對大家開發小程序有一定幫助。
后端
說完前端的基本架構,現在來說說后端。對于初期的項目來說,前端只要處理好數據和邏輯的架構,其他都是一些界面的問題和css相關體力活和不斷的多設備兼容調優。
后端的事情比較了多了,比如監控、數據處理、微服務、容災等等,這些年或多或少接觸了一些,但作為新項目,這些東西反而不是最重要的。
實現一個新項目,最重要是如何更快的迭代和提供新接口。crud仔的名聲不是隨便說說的。
從早年的到現在的微服務,概念一直在更新,但本質上沒有太大的改變。都是希望降低風險,早年我在小秘書的時候就開始做SOAP和WSDL,但對于創新業務來說,技術不應該作為阻礙效率的存在。
當我聽到為了一張表而專門創建一個服務的時候,我反而覺得是為了微服務而搞微服務。當我想改一個問題的時候,我需要從網關一路改到最后層的服務,明明幾分鐘能解決的事情,在調試上硬花了一整天。
每個人觀點不一致,技術沒有對錯。面對不同的背景,每個人選擇不一樣。我見過很多技術架構很好,但迭代慢死掉的公司。也見過很多內耗很嚴重,但依然發展很好的公司。
前面稍微說的有點偏題了,回到主題。初創項目主要處理好幾件事情。當然你有其他觀點,歡迎討論。里面有些地方參考了ruby-china的源碼,非常感謝。
接口及響應模板
怎么理解接口及響應模板呢?說白了就是你的接口能返回數據。
這次我沒有采用Grape的Gem,而是直接使用了Rails Api和的渲染模板。
首先我創建了一個父級渲染模板
# app/views/layouts/api/v1/.json.
json.code 200
json.message @message.blank? ? ‘’ : @message
json.data JSON.parse(yield)
也就是無論如何都會返回code,message,data這三個key,data可能為Array或者Object
然后在er.rb里指定父layout
layout ‘api/v1/'
然后在的目錄里為每一個實體做一個通用的模板,如_user.json.,通過參數判斷是簡易還是復雜對象。
比如你在列表里user可能主要3個值,,id,avatar,當你具體查看某個人的資料時,你可能需要知道他的其他信息,例如age,gender,等等。
然后相應的接口渲染可以參考下面的
json.partial! ‘user’, user: @user, detail: true
基本上你接口的響應就到這里就結束了。補充一點,如果你是使用Rails Api的話,使用需要加入以下引用
class r < ::API
include ::Layouts # if you need layout for .
include :: # if you need render .
錯誤捕獲及告警
這里分為幾塊
錯誤碼
你可以選擇新建一個專門的類來維護錯誤碼
module Api
module V1
module Code
*請認真填寫需求信息,我們會在24小時內與您取得聯系。