前言
本篇文章的主要目的是,對(duì)未開發(fā)過(guò)小程序的同學(xué)或者對(duì)小程序感興趣的同學(xué)嗡贺,能夠通過(guò)自己的文章忱叭,對(duì)小程序和小程序的開發(fā)流程有一定的了解
小程序簡(jiǎn)介
什么是小程序(mini program)
說(shuō)到小程序,其實(shí)大家并不會(huì)很陌生梢卸,我們?nèi)粘I钪幸矔?huì)在經(jīng)常用累魔,比如我們現(xiàn)在每天都會(huì)用的健康寶小程序摔笤;
定義
小程序簡(jiǎn)單來(lái)說(shuō)就是一種不需要下載安裝即可使用的應(yīng)用,它實(shí)現(xiàn)了應(yīng)用觸手可及的夢(mèng)想薛夜,用戶通過(guò)掃一掃或者搜一搜即可打開應(yīng)用籍茧,體現(xiàn)了用完即走的理念,用戶不用太擔(dān)心安裝軟件太多問(wèn)題梯澜;
小程序發(fā)展史
字節(jié)小程序發(fā)展前景
平臺(tái)條件
小程序想要發(fā)展起來(lái)寞冯,就離不開大的流量平臺(tái),而我們公司的巨頭產(chǎn)品抖音晚伙、頭條等擁有大量流量吮龄;因此,字節(jié)跳動(dòng)小程序的平臺(tái)條件無(wú)疑是很好的咆疗。
平臺(tái)方向及發(fā)展意圖
字節(jié)掌握大量的流量和內(nèi)容漓帚,會(huì)流量變現(xiàn),目前更多的變現(xiàn)方式是通過(guò)廣告午磁,開辟了一個(gè)新的領(lǐng)域尝抖,打造自己獨(dú)立的電商體系,而小程序可以通過(guò)綁定頭條各產(chǎn)品完成變現(xiàn)閉環(huán)迅皇,小程序是做電商最好的載體昧辽。
小程序和web端開發(fā)的區(qū)別
相同點(diǎn)
- 使用 js 開發(fā)邏輯層、使用 css 控制樣式登颓、使用html 進(jìn)行頁(yè)面渲染
不同點(diǎn)
- web 開發(fā)中每個(gè)頁(yè)面的 js 線程與渲染線程是互斥的搅荞;小程序中 js 的運(yùn)行進(jìn)程和渲染進(jìn)程是獨(dú)立的,視圖的渲染更新不會(huì)影響并不會(huì)阻塞 js 的執(zhí)行框咙;js的邏輯執(zhí)行同樣不會(huì)阻塞頁(yè)面的視圖渲染更新咕痛;
- 運(yùn)行環(huán)境不同:web 運(yùn)行環(huán)境為瀏覽器,需要處理不同瀏覽器之間的差異喇嘱;小程序的環(huán)境差異主要是指不同小程序的宿主與不同的操作系統(tǒng)間的差異;
- 啟動(dòng):web開發(fā)打開頁(yè)面可直接通過(guò) http 地址直接訪問(wèn); 舉例:小程序通過(guò)協(xié)議(如:snssdk1374://microapp)調(diào)起小程序后茉贡,小程序會(huì)以包的形式下發(fā)到當(dāng)前打開小程序的 APP 上,并且裝載本地的 js/xml/css等文件打開小程序者铜,因此小程序不能像 web 端一樣使用 location 等方式跳轉(zhuǎn)頁(yè)面腔丧,也不存在跨域构蹬;
- 小程序的 js 是運(yùn)行在 jscore 中的而非 webview 中,所以無(wú) DOM BOM 對(duì)象悔据,無(wú)法使用 window 等瀏覽器提供的全局變量;小程序中也無(wú)法使用 Npm
- 代碼上傳:web 開發(fā)中代碼一般會(huì)部署在自己的 CDN 或者 自己的服務(wù)器中俗壹,對(duì)于上傳代碼沒(méi)有特殊限制科汗;字節(jié)小程序代碼是統(tǒng)一上傳到字節(jié)服務(wù)器上統(tǒng)一進(jìn)行管理,下發(fā)也是通過(guò)自己服務(wù)器統(tǒng)一下發(fā)的绷雏,所以開發(fā)過(guò)程中需要使用字節(jié)開發(fā)者工具進(jìn)行代碼上傳
小程序開發(fā)流程
開發(fā)前準(zhǔn)備
- 在字節(jié)開發(fā)者平臺(tái)上注冊(cè)一個(gè)賬號(hào)
image.png
2.創(chuàng)建小程序
image.png -
主體認(rèn)證 & 完善信息
image.png - 配置開發(fā)協(xié)作者
-
配置好相關(guān)接口域名白名單
image.png -
安裝字節(jié)開發(fā)者工具(這里簡(jiǎn)要介紹一下開發(fā)者工具的使用方式)
image.png
開發(fā)調(diào)試
- 新建項(xiàng)目
- 開發(fā)者工具關(guān)聯(lián)小程序
- 編寫代碼
- 預(yù)覽調(diào)試
- 上傳代碼
打包編譯測(cè)試& 提交審核
小技巧:程序目前最大打包體積是 4 M 如果項(xiàng)目中有很多靜態(tài)圖片头滔、字體文件等需要上傳至 CDN & 去除項(xiàng)目中不必要的依賴包 最好都是按需引入
- 上傳代碼
- 本地編譯
- 小程序開發(fā)者工具點(diǎn)擊上傳代碼,發(fā)布測(cè)試版本
- 生成二維碼
- 宿主 APP 進(jìn)行掃碼測(cè)試
- 測(cè)試版本無(wú)問(wèn)題后涎显,提交上線審核(一般1~2個(gè)工作日坤检,需要提供小程序主要功能截圖&勾選發(fā)布線上宿主,目前只有抖音頭條等已上線的宿主期吓,若發(fā)現(xiàn)申請(qǐng)上線的宿主不包含本次上線宿主早歇,需要溝通小程序運(yùn)營(yíng)修改配置)
完成以上幾個(gè)步驟,恭喜你的第一個(gè)小程序就完成了 L智凇<!
小程序開發(fā)實(shí)踐
基礎(chǔ)概念
scheme:
一種模式潭千,App內(nèi)統(tǒng)一頁(yè)面的跳轉(zhuǎn)的跳轉(zhuǎn)定義的路由規(guī)則谱姓,通過(guò) scheme 吊起 App 的頁(yè)面跳轉(zhuǎn);一般規(guī)則為:scheme://host/path?query=value
舉例(巨量App):snssdk1374://host/path?query1=value1&query2=value2
jsbridge:
小程序和 Native 之間通信的橋梁
webview:
一種組件刨晴,用來(lái)承載網(wǎng)頁(yè)的容器屉来;目前小程序的一個(gè)特點(diǎn)是無(wú)法外跳 H5 頁(yè)面,通過(guò) webview 組件可以切入到小程序內(nèi)部狈癞,鋪滿這個(gè)頁(yè)面
小程序開發(fā)語(yǔ)言
邏輯層
主要工作:數(shù)據(jù)綁定茄靠、事件分發(fā)、生命周期亿驾、路由管理的操作
- app.js:小程序入口
- Page(): 頁(yè)面入口
- Component(): 組件入口
小程序原理
小程序架構(gòu)
小程序架構(gòu)分為視圖層和邏輯層嘹黔,視圖層每一個(gè)page都會(huì)是一個(gè)獨(dú)立的 webview,小程序不允許打開超過(guò) 5 個(gè)以上的頁(yè)面,會(huì)引起性能問(wèn)題莫瞬;視圖層和邏輯層的數(shù)據(jù)通過(guò) jsbridge 來(lái)進(jìn)行實(shí)現(xiàn)儡蔓;邏輯層如果需要更新某些數(shù)據(jù)通過(guò)jsbridge更新到視圖層,視圖層進(jìn)行更新疼邀;同理視圖層有事件產(chǎn)生通過(guò)jsbridge實(shí)現(xiàn)傳遞到邏輯層觸發(fā)對(duì)應(yīng)事件喂江; 小程序的邏輯層可以調(diào)用一些API,如果是webview支持不了的旁振,是由native支持的获询,native支持的過(guò)程也是通過(guò)jsbridge實(shí)現(xiàn)的涨岁;邏輯層主要運(yùn)行在一個(gè)沒(méi)有DOM BOM 對(duì)象的沙箱環(huán)境中,只能通過(guò)調(diào)用API 來(lái)實(shí)現(xiàn)和視圖層和 Native 層交互吉嚣;
小程序編譯
為什么需要編譯呢梢薪?
我們的 view button 組件如何渲染到頁(yè)面上以及頁(yè)面如何加載 ttml ttss ,簡(jiǎn)單理解為把原始代碼轉(zhuǎn)換為可以運(yùn)行的代碼稱之為編譯
小程序的源文件由 ttml (模板文件) ttss(樣式文件) js 組成尝哆;視圖層主體為page-frame.html秉撇,邏輯層主體為app-service.js
功能
- 基礎(chǔ)功能
- 編譯 ttml ttss js json
- 業(yè)務(wù)能力
- 熱更新
- 生成二進(jìn)制文件
- 本地調(diào)試
模板文件
所有.ttml文件最終會(huì)被編譯成一個(gè)js函數(shù),函數(shù)的返回結(jié)果就是這個(gè).ttml結(jié)構(gòu)文件對(duì)應(yīng)的vdom對(duì)象秋泄,舉例:
此處是將 TTML 轉(zhuǎn)換成一系列的 render 函數(shù)琐馆,放于視圖層中,待傳入路由后調(diào)用特定的 render 函數(shù)來(lái)渲染為真正的dom節(jié)點(diǎn)
ttml 文件
<view class="foo" data-var="{{ bar }}">Hello, {{ user }}</view>
小程序經(jīng)過(guò)編譯后恒序,會(huì)在 page-frame 中生成一個(gè) 對(duì)應(yīng)的函數(shù)
` var render = function (ttData) {
var bar = ttData.bar,
user = ttData.user;
return [__h(
"tt-view",
{ className: "foo", "data-var": bar },
"Hello, ",
user
)];
render函數(shù)就是 page/index 對(duì)應(yīng)的vdom對(duì)象生成函數(shù)瘦麸;當(dāng)render函數(shù)接收到數(shù)據(jù)ttData變化時(shí),就會(huì)進(jìn)行diff -> patch -> render的歧胁,傳統(tǒng)的vdom更新操作滋饲。其中的標(biāo)簽“tt-view”,是使用的polymer的自定義標(biāo)簽組件与帆。渲染出tt-view之后了赌,又交給polymer渲染出真實(shí)dom。
JS編譯
js部分將會(huì)和API玄糟、通信模塊等一起打包到app-service.js為主體的文件中
babel編譯
- 解析(parse): 代碼字符串轉(zhuǎn)換成抽象語(yǔ)法樹
- 轉(zhuǎn)換(transform): 對(duì)抽象的語(yǔ)法樹進(jìn)行轉(zhuǎn)換(插件處理)
- 生成(generate): 根據(jù)變化后的抽象語(yǔ)法樹生成代碼字符串
ttss編譯
Postcss編譯過(guò)程:
- 解析: 將 css 字符串解析成抽象語(yǔ)法樹
- 轉(zhuǎn)換: 對(duì)抽象語(yǔ)法樹進(jìn)行轉(zhuǎn)換操作勿她,主要是通過(guò)( postcss插件)
- 生成 : 根據(jù)變換后的抽象語(yǔ)法樹再生成新的 css
json轉(zhuǎn)換
主要是將多個(gè) json 文件最終合并轉(zhuǎn)換為一個(gè) config.json文件
目錄結(jié)構(gòu)
生命周期
應(yīng)用生命周期
onLaunch
監(jiān)聽小程序初始化
當(dāng)小程序初始化完成,觸發(fā)onLaunch, 全局只觸發(fā)一次
onShow
監(jiān)聽小程序顯示
當(dāng)小程序啟動(dòng)阵翎,或者從后臺(tái)進(jìn)入前臺(tái)顯示
onHide
監(jiān)聽小程序隱藏
小程序從前臺(tái)到后臺(tái)
PS: 前臺(tái)逢并、后臺(tái)定義: 當(dāng)用戶點(diǎn)擊左上角關(guān)閉,或者按了設(shè)備 Home 鍵離開郭卫,小程序此時(shí)并沒(méi)有直接銷毀砍聊,而是進(jìn)入了后臺(tái);當(dāng)再次進(jìn)入或再次打開小程序贰军,又會(huì)從后臺(tái)進(jìn)入前臺(tái)玻蝌。
頁(yè)面生命周期
onLoad
頁(yè)面加載時(shí)調(diào)用,一個(gè)頁(yè)面只會(huì)調(diào)用一次
onShow
頁(yè)面顯示词疼,每次打開頁(yè)面都會(huì)重新調(diào)用一次
onReady
頁(yè)面初次渲染完成俯树,一個(gè)頁(yè)面只會(huì)調(diào)用一次,頁(yè)面已經(jīng)準(zhǔn)備妥當(dāng)贰盗,可以與視圖層交互
onHide
頁(yè)面隱藏许饿,當(dāng)切換路由navigateTo或者切換底部 tab 時(shí)調(diào)用
onUnload
頁(yè)面卸載,當(dāng)redirectTo或navigateBack的時(shí)候調(diào)用
組件
組件類型
內(nèi)置組件
基礎(chǔ)組件舵盈,比如 button陋率、view球化、text 等大部分組件,直接在頁(yè)面引入使用即可
自定義組件
- 定義:內(nèi)部組件的能力封裝給開發(fā)者瓦糟,讓開發(fā)者可以封裝符合業(yè)務(wù)的組件進(jìn)行復(fù)用, 主要還是由 ttml ttss js json 文件構(gòu)成筒愚。
- 創(chuàng)建:在 json 文件中將 component 設(shè)置 true
-
注冊(cè):在自定義組件的 js 文件中需要使用 Component 來(lái)注冊(cè)組件
image.png -
使用:需要在頁(yè)面的 json 文件中進(jìn)行引用聲明,此時(shí)需要提供每個(gè)自定義組件的標(biāo)簽名和對(duì)應(yīng)的自定義組件文件路徑
image.png
路由
小程序啟動(dòng)
運(yùn)行機(jī)制
小程序啟動(dòng)會(huì)有兩種情況菩浙,一種是「冷啟動(dòng)」锨能,一種是「熱啟動(dòng)」。 假如用戶已經(jīng)打開過(guò)某小程序芍耘,然后在一定時(shí)間內(nèi)再次打開該小程序,此時(shí)無(wú)需重新啟動(dòng)熄阻,只需將后臺(tái)態(tài)的小程序切換到前臺(tái)斋竞,這個(gè)過(guò)程就是熱啟動(dòng);冷啟動(dòng)指的是用戶首次打開或小程序被主動(dòng)銷毀后再次打開的情況秃殉,此時(shí)小程序需要重新加載啟動(dòng)坝初。
注意:
- 小程序沒(méi)有重啟的概念
- 當(dāng)小程序進(jìn)入后臺(tái),客戶端會(huì)維持一段時(shí)間的運(yùn)行狀態(tài)钾军,超過(guò)一定時(shí)間后會(huì)被主動(dòng)銷毀
小程序運(yùn)行環(huán)境
字節(jié)跳動(dòng)小程序鳄袍,運(yùn)行在字節(jié)跳動(dòng)提供的小程序 SDK 上,但是由于 SDK 嵌入的宿主不同吏恭,小程序 SDK 提供的能力集合可能會(huì)根據(jù)宿主的不同而變化拗小。
在 iOS 中,小程序的邏輯層 javascript 代碼運(yùn)行在 webWorker 中樱哼,視圖層由 WKWebView 進(jìn)行渲染哀九。 在 Android 中,小程序的邏輯層 javascript 代碼運(yùn)行在 V8 中搅幅,視圖層由 Mobile Chrome 進(jìn)行渲染阅束。
小程序與宿主交互
小程序在宿主上打開流程
- 需要知道小程序相關(guān)信息,包括appid茄唐,代碼包地址等息裸,這些信息可以保存在一個(gè)scheme中。該scheme一般由服務(wù)端下發(fā)沪编,格式如下scheme://host/path?query=value
- 客戶端拿到 scheme 后呼盆,就可以調(diào)用sdk中的MiniAppOpenTool.openAppbrand(..),進(jìn)行打開小程序
- MiniAppOpenTool.openAppbrand最終會(huì) 打開MiniappTabActivity0或MiniappTabActivity1漾抬,2宿亡,3,4纳令。這里每個(gè)小程序和小游戲都是在各自的獨(dú)立進(jìn)程中運(yùn)行挽荠,目前最多只能打開5個(gè)新的進(jìn)程克胳。要打開第6個(gè)進(jìn)程時(shí),會(huì)先殺死最早創(chuàng)建的進(jìn)程圈匆,再重新創(chuàng)建新的進(jìn)程運(yùn)行小程序或小游戲漠另。
- 打開MiniappTabActivityX,該Activity是一個(gè)代理Activity跃赚,實(shí)際會(huì)調(diào)用具體的Activity笆搓。如果是小程序,會(huì)調(diào)用TTAppbrandTabUI纬傲;如果是小游戲满败,會(huì)調(diào)用TTAppbrandGameActivity
小程序和宿主通信
通過(guò) bridge 進(jìn)行通信
小程序踩坑&經(jīng)驗(yàn)總結(jié)
開發(fā)者工具
- 開發(fā)者工具上樣式和功能顯示正常,但是真機(jī)調(diào)試時(shí)叹括,有時(shí)會(huì)出現(xiàn)偏差
- 解決辦法: 最終測(cè)試都需要以真機(jī)測(cè)試為準(zhǔn)
-
開發(fā)者工具中為方便調(diào)試開發(fā)算墨,可提前配置好編譯模式
image.png - 開發(fā)者工具中提供的真機(jī)測(cè)試二維碼有效期為 1d
開發(fā)
- 布局盡量使用彈性布局,使用彈性布局能夠更好的從整體上達(dá)到效果汁雷,兼容會(huì)更好
- 由于小程序性能的問(wèn)題净嘀,在動(dòng)態(tài)改變?cè)氐膶捀呋蛭恢脮r(shí),會(huì)出現(xiàn)動(dòng)畫卡頓侠讯,可以使用 throttle挖藏,提高穩(wěn)定性
- 頁(yè)面中的自定義 component 過(guò)多時(shí),會(huì)導(dǎo)致頁(yè)面渲染有點(diǎn)卡頓
- 解決辦法:可以使用 hidden 代替 tt:if 來(lái)避免重新渲染組件厢漩,一般來(lái)說(shuō)tt:if 有更高的切換消耗而 hidden 有更高的初始渲染消耗膜眠。因此,如果需要頻繁切換的情景下溜嗜,用 hidden 更好柴底,如果在運(yùn)行時(shí)條件不大可能改變則 tt:if 較好
- tt.chooseImage 上傳圖片api,當(dāng)用戶首次拒絕授權(quán)時(shí)粱胜,不會(huì)二次調(diào)起相冊(cè)柄驻,需要主動(dòng)提示用戶
- tt.uploadFile 各字段對(duì)應(yīng)參數(shù)要注意& 在使用前需要配置域名白名單
-
字體文件需要在 app.js中引入
image.png - 相關(guān)接口Api 權(quán)限申請(qǐng)要提前,審核流程比較慢
- 提前下載好 charles 抓包工具焙压,方便調(diào)試時(shí)定位問(wèn)題
- 真機(jī)調(diào)試時(shí)鸿脓,右上角配置里可以開啟小程序調(diào)試模式
- 部分接口 API 在安卓、ios 支持度和返回參數(shù)可能不一致涯曲,需要以每個(gè)機(jī)型真機(jī)測(cè)試為準(zhǔn)
- 小程序 SDK 支持人臉識(shí)別功能野哭,通過(guò)調(diào)用 tt.startFacialRecognitionVerify,有以下注意點(diǎn)
- 需要宿主 APP 提前接入小程序 SDK
- 需要宿主 APP 接入 Ailab 活體識(shí)別 SDK
- setData傳輸數(shù)據(jù)過(guò)多。導(dǎo)致更新卡頓幻件。
- 盡量減少setData的傳輸數(shù)據(jù)拨黔,只傳輸視圖使用到的數(shù)據(jù),裁剪其他冗余數(shù)據(jù)
打包編譯
- 執(zhí)行打包編譯命令后绰沥,需要手動(dòng)復(fù)制project.config.js文件到 dist 中
- 字節(jié)小程序打包體積最大為 4M ,建議項(xiàng)目中靜態(tài)文件和字體文件等上傳CDN篱蝇,使用的組件庫(kù)等也建議按需引入贺待,減少打包體積
小程序開發(fā)痛點(diǎn)
- 打包編譯部署發(fā)布測(cè)試包比較麻煩,是否可以自動(dòng)化部署(正在調(diào)研零截,近期會(huì)與 addone 平臺(tái)同學(xué)了解一下)
- 基礎(chǔ)種類還不夠豐富
- 跨界面數(shù)據(jù)傳遞(多頁(yè)面應(yīng)用)
- 使用全局變量
- 使用本地緩存
- 使用url query-string
- 不支持 NPM
- 直接將需要引用的包直接復(fù)制到項(xiàng)目中
- ES6 ES7 支持不完整
- ES6支持大部分
- ES7 不支持
- 不支持的有: includes麸塞、async、await涧衙、Proxy
- ttss
- 無(wú)法使用本地資源
- 無(wú)法使用級(jí)聯(lián)
- 不支持 less sass
主流開發(fā)框架
Taro實(shí)現(xiàn)多端編譯原理
Taro1 & 2
整體思想:采用的是編譯原理的思想哪工,對(duì)一個(gè)輸入的源代碼進(jìn)行語(yǔ)法分析、語(yǔ)法樹構(gòu)建弧哎,之后對(duì)語(yǔ)法樹進(jìn)行轉(zhuǎn)換操作再解析生成目標(biāo)代碼
實(shí)現(xiàn)過(guò)程:
Taro3
整體思想:不同于 1 和 2 版本雁比,采用的是解釋型架構(gòu),主要是通過(guò)在小程序端模擬實(shí)現(xiàn)DOM撤嫩、BOM的API來(lái)讓前端框架直接運(yùn)行在小程序環(huán)境中章贞,從而達(dá)到小程序和H5統(tǒng)一的目的,對(duì)于生命周期非洲、組件庫(kù)、API蜕径、路由等差異两踏,采用定義統(tǒng)一標(biāo)準(zhǔn),各端負(fù)責(zé)各自實(shí)現(xiàn)的方式來(lái)抹平差異兜喻。
整體架構(gòu):
參考鏈接
https://www.infoq.cn/article/wawopvwhxb5nwq8f9sw4 (我眼中的小程序前世今生)
https://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650833967&idx=1&sn=e94b3e45ee1646ce0e8647d272a1eb8e&chksm=80b750b1b7c0d9a790740c4d896ec61a3e529b71c8ebe6f9c54367e35af8afc7e2aa87f01e2d&scene=27#wechat_redirect (App vs 小程序)
https://drive.google.com/file/d/18DSzrmSpYD7kcZj-BpBhrSW_DH2oJcLj/view(深入淺出小程序渲染)
https://drive.google.com/file/d/10lLDBK4txqvlCV2IU1g9xFGvu19UPn4t/view(小程序渲染)
https://drive.google.com/file/d/1ZKekXpBaUU6KWVgS_JINYw8CD6aCrup7/view(小程序及開發(fā)原理簡(jiǎn)介)
https://drive.google.com/file/d/1_hQ4lleqL8EkeDpp9luNxMfcjw6ZgFpL/view(小程序的編譯設(shè)計(jì)與實(shí)踐)
https://drive.google.com/file/d/1q7Bc_1TSLXHShtmwIWimNmHNVYy1B_Pi/view(字節(jié)小程序組件的實(shí)現(xiàn))
https://drive.google.com/file/d/1kK-3DYryJFdM5182KcoH9fhq-geWKzNm/view(小程序 TTML 解析原理)