Taro小程序跨端開(kāi)發(fā)入門(mén)實(shí)戰(zhàn)(小程序跨端框架)
Taro小程序跨端開(kāi)發(fā)入門(mén)實(shí)戰(zhàn)(小程序跨端框架)
背景
一開(kāi)始我們只做微信小程序隨著我們的業(yè)務(wù)不斷擴(kuò)張和各大小程序平臺(tái)的崛起,針對(duì)每個(gè)平臺(tái)都去寫(xiě)一套代碼是不現(xiàn)實(shí)的。而且原生的小程序開(kāi)發(fā)模式有很多弊端。
為了讓小程序開(kāi)發(fā)更簡(jiǎn)單,更高效,我們采用 Taro 作為首選框架,我們將使用 Taro 的實(shí)踐經(jīng)驗(yàn)整理了出來(lái),主要內(nèi)容圍繞著什么是 Taro,為什么用 Taro,以及 Taro 如何使用(正確使用的姿勢(shì)),還有 Taro 背后的一些設(shè)計(jì)思想來(lái)進(jìn)行展開(kāi),讓大家能夠?qū)?Taro 有個(gè)完整的認(rèn)識(shí)。
Taro 3.0 已經(jīng)逐漸成熟,我們項(xiàng)目已經(jīng)進(jìn)行了Taro 3.0的升級(jí),因此本文代碼示例以 Taro 3.0 作為基礎(chǔ)。
什么是 Taro
Taro 是一個(gè)多端統(tǒng)一的開(kāi)發(fā)框架。使用 taro 它可以支持 React 的開(kāi)發(fā)方式,編寫(xiě)一次可以運(yùn)行多端的代碼,就能夠生成可以在各種小程序,h5 甚至 React Native 等多端應(yīng)用。
Taro 官方介紹:
Taro 是一個(gè)開(kāi)放式跨端跨框架解決方案,支持使用 React/Vue/Nerv 等框架來(lái)開(kāi)發(fā) 微信 / 京東 / 百度 / 支付寶 / 字節(jié)跳動(dòng) / QQ 小程序 / H5/ React Native 等應(yīng)用?,F(xiàn)如今市面上端的形態(tài)多種多樣,Web、React Native、微信小程序等各種端大行其道,當(dāng)業(yè)務(wù)要求同時(shí)在不同的端都要求有所表現(xiàn)的時(shí)候,針對(duì)不同的端去編寫(xiě)多套代碼的成本顯然非常高,這時(shí)候只編寫(xiě)一套代碼就能夠適配到多端的能力就顯得極為需要。
它的主要特點(diǎn)是:
快:可以快速開(kāi)發(fā)小程序: 解決小程序開(kāi)發(fā)各種痛點(diǎn);
多:可以實(shí)現(xiàn)多終端適配:一套代碼適配小程序、H5、RN 等多終端;
為什么用 Taro
隨著應(yīng)用變得龐大之后,復(fù)雜度越來(lái)越高,原生小程序開(kāi)發(fā)的痛點(diǎn)逐漸暴露出來(lái):
?代碼組織復(fù)雜:寫(xiě)一個(gè)頁(yè)面的文件結(jié)構(gòu)繁瑣(四個(gè)之多)
?規(guī)范不統(tǒng)一:組件、方法命名規(guī)范不統(tǒng)一、各種書(shū)寫(xiě)方式,語(yǔ)法結(jié)構(gòu)不一致像 React 又像 Vue
?孱弱的字符串模板:邏輯表現(xiàn)力不強(qiáng),不支持 eslint
?依賴(lài)管理混亂:缺少 npm 包依賴(lài)管理
?不完全的 ES Next:僅支持部分 ES Next 語(yǔ)法,比較新的 ES2020, ES2021 都不支持
?落后的開(kāi)發(fā)方式:前端工程體系不完善,webpack 打包,css 預(yù)處理等缺失,對(duì)于前端來(lái)說(shuō)比較落后的,對(duì)個(gè)人成長(zhǎng)也不利
可選技術(shù)方案可選技術(shù)方案
對(duì)于以上微信小程序開(kāi)發(fā)模式的痛點(diǎn),業(yè)界也給出了一些可選方案:
對(duì)比分析
- mpvue 是美團(tuán)研發(fā)的框架,多端適配效果不好,很久問(wèn)題都沒(méi)人維護(hù);
- WePY 是騰訊出的組件化框架,但是無(wú)法適配多端;
- Chameleon 在多端適配方面表現(xiàn)很突出,缺點(diǎn)是不支持京東小程序,無(wú)法轉(zhuǎn)換原生小程序(想用只能重寫(xiě)項(xiàng)目);
- Taro 優(yōu)秀的特性,遵循 React/Vue 語(yǔ)法規(guī)范,引入的現(xiàn)代化的開(kāi)發(fā)流程,讓開(kāi)發(fā)更專(zhuān)注核心代碼,提供健全的代碼檢查方式。
多端需求
Taro 支持平臺(tái)最全面,獨(dú)具轉(zhuǎn)換能力,性能方面優(yōu)于其它框架,總結(jié)特點(diǎn)如下:
- 可以實(shí)現(xiàn)微信小程序原生代碼轉(zhuǎn)換到微信平臺(tái),百度平臺(tái)等;
- Taro 框架是唯一一款實(shí)現(xiàn)京東小程序適配的框架;
- 支持 React/Vue 語(yǔ)法,更好的支持組件化和 TypeScript;
- 行業(yè)影響力大,社區(qū)活躍,京東內(nèi)部?jī)?yōu)秀團(tuán)隊(duì)研發(fā)的框架,支持有保障,研發(fā)團(tuán)隊(duì)靠譜非常支持我們的工作;
- 更加完善的UI組件庫(kù),支持多端同步調(diào)試能夠適配更多終端;
一處編寫(xiě),多端運(yùn)行
設(shè)計(jì)思想
主要采用 React 開(kāi)發(fā)方式
用 React 寫(xiě)多端應(yīng)用
核心思想
代碼轉(zhuǎn)換:使代碼可以在不同平臺(tái)上運(yùn)行
運(yùn)行時(shí)適配:使代碼在不同平臺(tái)上有相同表現(xiàn)
以微信小程序?yàn)槔晕⑿判〕绦驗(yàn)槔?/h1>
JSX
WXML
Taro 代碼編譯原理
Taro 的編譯原理:就是對(duì)輸入的源代碼進(jìn)行語(yǔ)法分析,語(yǔ)法樹(shù)構(gòu)建,隨后對(duì)語(yǔ)法樹(shù)進(jìn)行轉(zhuǎn)換操作再解析生成目標(biāo)代碼的過(guò)程。
首先是 Parse,將代碼解析(Parse)成抽象語(yǔ)法樹(shù)(Abstract Syntex Tree),然后對(duì) AST 進(jìn)行遍歷(traverse)和替換(replace)(這對(duì)于前端來(lái)說(shuō)其實(shí)并不陌生,可以類(lèi)比 DOM 樹(shù)的操作),最后是生成(generate),根據(jù)新的 AST 生成編譯后的代碼。
開(kāi)發(fā)時(shí)遵循 React 語(yǔ)法標(biāo)準(zhǔn),結(jié)合編譯原理的思想,對(duì)代碼文件進(jìn)行一系列轉(zhuǎn)換操作,最終獲得可以在小程序運(yùn)行的代碼。而 React 最開(kāi)始就是為了解決 Web 開(kāi)發(fā)而生的,所以對(duì)代碼稍加改動(dòng),也可以直接生成在 Web 端運(yùn)行的代碼,而同屬 React 語(yǔ)法體系下的 React Native,也能夠很便捷地提供支持。同理其他平臺(tái),如快應(yīng)用、百度小程序等,將源碼進(jìn)行編譯轉(zhuǎn)換操作,也能獲得該平臺(tái)下的對(duì)應(yīng)語(yǔ)法代碼。
可以看出小程序和 Web 端上組件標(biāo)準(zhǔn)與 API 標(biāo)準(zhǔn)有很大差異,這些差異僅僅通過(guò)代碼編譯手段是無(wú)法抹平的,例如你不能直接在編譯時(shí)將小程序的 直接編譯成
,因?yàn)樗麄冸m然看上去有些類(lèi)似,但是他們的組件屬性有很大不同的,僅僅依靠代碼編譯,無(wú)法做到一致,同理,眾多 API 也面臨一樣的情況。針對(duì)這樣的情況,Taro 采用了定制一套運(yùn)行時(shí)標(biāo)準(zhǔn)來(lái)抹平不同平臺(tái)之間的差異。
這一套標(biāo)準(zhǔn)主要以三個(gè)部分組成,包括標(biāo)準(zhǔn)運(yùn)行時(shí)框架、標(biāo)準(zhǔn)基礎(chǔ)組件庫(kù)、標(biāo)準(zhǔn)端能力 API,其中運(yùn)行時(shí)框架和 API 對(duì)應(yīng) @taro/taro,組件庫(kù)對(duì)應(yīng) @tarojs/components,通過(guò)在不同端實(shí)現(xiàn)這些標(biāo)準(zhǔn),從而達(dá)到去差異化的目的。
多端適配基礎(chǔ)標(biāo)準(zhǔn)
- 基礎(chǔ)框架(生命周期、組件API):以React的生命周期、組件api為基礎(chǔ),小程序的特性作為補(bǔ)充
- 標(biāo)準(zhǔn)組件庫(kù)(View、Button): 以微信小程序組件為標(biāo)準(zhǔn),各端模擬實(shí)現(xiàn)
- 標(biāo)準(zhǔn)Api (request、setState):擴(kuò)展的小程序標(biāo)準(zhǔn)Api,各端模擬實(shí)現(xiàn)
多端適配基礎(chǔ)架構(gòu)圖如下:
快速上手
初始化項(xiàng)目
環(huán)境準(zhǔn)備:需要有個(gè) node 環(huán)境,運(yùn)行 npm 命令:
開(kāi)始使用 Taro 編寫(xiě)頁(yè)面:
運(yùn)行項(xiàng)目
多平臺(tái)啟動(dòng)命令示例:
如果同時(shí)看三端效果:分別運(yùn)行以上命令即可;
微信原生小程序轉(zhuǎn)換 Taro 小程序
Taro 項(xiàng)目的組成
Taro項(xiàng)目目錄結(jié)構(gòu)
基本的目錄結(jié)構(gòu):
比較完整的多端項(xiàng)目結(jié)構(gòu):
完整的文檔請(qǐng)?jiān)L問(wèn):https://taro-docs.jd.com/
多端適配
多終端配置文件編寫(xiě)
?微信的配置文件 project.config.JSON,文件內(nèi)容可以自定義微信小程序的選項(xiàng),運(yùn)行的目錄和 appid 等;
?百度小程序的配置文件 project.swan.json 內(nèi)容和微信類(lèi)似;
?京東小程序的配置文件 project.jd.json 內(nèi)容和微信類(lèi)似;
?其它平臺(tái)的小程序都有獨(dú)立的配置文件便于運(yùn)行的調(diào)試;
多終端入口文件
每個(gè)平臺(tái)有不同的頁(yè)面配置信息:
?微信小程序頁(yè)面是全量的,有微信登錄頁(yè)面(其它平臺(tái)不需要);
?百度小程序有專(zhuān)門(mén)的登錄頁(yè)面有些頁(yè)面百度不支持需隱藏比如:圖片裁剪,達(dá)達(dá)同城,打印等;
?京東小程序:不支持批量寄,不需要登錄頁(yè)面,不支持分包,都要寫(xiě)入主包中;
差異化配置
- 不同平臺(tái)加載對(duì)應(yīng)的文件:
- 每個(gè)平臺(tái)差異化配置信息:
- 地圖類(lèi)型;
- 渠道信息;
- 請(qǐng)求頭信息;
- 。。。
代碼差異化處理
平臺(tái)特定 js 代碼塊兒實(shí)現(xiàn),在任意 js 代碼中加入如下語(yǔ)法:
平臺(tái)特定 css 代碼塊兒實(shí)現(xiàn), 在任意 css 代碼中加入如下語(yǔ)法:
提示:代碼在打包時(shí)不會(huì)增加包體積,針對(duì)不同平臺(tái)提取相應(yīng)代碼。
多端適配案例
一些典型的多端通用解決方案:
- 樣式解析:
- 微信是 rPX,百度小程序 vw,京東小程序 px;
- Taro 統(tǒng)一使用 px 通過(guò)框架處理轉(zhuǎn)換成對(duì)應(yīng)平臺(tái)的像素,因此 px 值不要使用單數(shù);
- 1px(像素)的邊框通常會(huì)轉(zhuǎn)換成平臺(tái)對(duì)應(yīng)單位會(huì)導(dǎo)致無(wú)法顯示, 可以使用大寫(xiě)的PX單位,例如: 1PX ;
- 百度小程序和京東小程序不支持 externalClasses,其它小程序也可能不支持避免使用;
- 模塊導(dǎo)入和導(dǎo)出:
- 導(dǎo)入模塊需要使用ES6 的 import, 不要使用 require 到 JS 文件(有些平臺(tái)不支持);
- 內(nèi)聯(lián)本地圖片資源可以使用 require 動(dòng)態(tài)導(dǎo)入;
- 導(dǎo)入外部資源的 url 必須使用 https,有些平臺(tái)或機(jī)型不支持 http ;
- 小程序插件導(dǎo)入可以使用 require 但是要做多平臺(tái)適配和兼容性處理;
- 組件開(kāi)發(fā)細(xì)節(jié):
- 組件 key 取值,不要使用 index ,對(duì)象的 id 屬性要先解構(gòu)出來(lái);
- 組件渲染條件取 length 屬性頁(yè)面不更新;
- dataset 問(wèn)題:百度和微信獲取的不一樣,都要用小寫(xiě)來(lái)保持代碼一致: 這種駝峰的:data-goodsIndex={index} ,微信會(huì)轉(zhuǎn)成全小寫(xiě) goodsindex, 百度會(huì)保留駝峰 ,正確地寫(xiě)法:data-goodsindex={index} ;
百度小程序開(kāi)發(fā)注意事項(xiàng):
- 層次較深的狀態(tài)不會(huì)更新時(shí),需要解構(gòu)變量;
- 轉(zhuǎn)換成 vw 樣式有偏差,確保樣式的通用性;
- 個(gè)別組件 height: auto 有bug,不寫(xiě)沒(méi)事;
- line-height 居中有偏差,用 flex 比較穩(wěn)妥;
- fixed 布局居底要設(shè)置 left: 0, bottom: 0 ,不寫(xiě)默認(rèn)會(huì)有問(wèn)題(默認(rèn)在中間渲染);
- mask 組件層級(jí)較深時(shí),可能不會(huì)更新?tīng)顟B(tài),可以使用 tt-modal 代替;
- 圖片裁剪,語(yǔ)音識(shí)別,打印功能等依賴(lài)原生 API 不支持;
- 狀態(tài)更新從有到無(wú)需要顯性設(shè)置 null ,例如將列表組件隱藏:this.setState({list: null}) {list && <組件實(shí)例>};
京東小程序開(kāi)發(fā)注意事項(xiàng):
- 不支持全局覆蓋組件樣式,如果想兼容需要單寫(xiě)加上拼接樣式名;
- 不支持小程序分包,需要單獨(dú)配置頁(yè)面路由信息;
- showModal 彈窗不能定制 confirmColor 屬性;
- storagesync 不支持存儲(chǔ) json 數(shù)據(jù),讀取需要自己手動(dòng)JSON.parse;
- 不支持 canvas繪畫(huà)API:微信自定義分享功能,圖片裁剪,訂單條形碼等功能都做不了;
- 不支持同層渲染,原生組件上只能使用 Cover 組件;
- ios 內(nèi)嵌H5,如果url帶參數(shù),需要手動(dòng)做一下urlencode編碼;
- H5頁(yè)面使用小程序 webview 不具備全部京東 app webview 功能,有些功能不支持;
- 京東小程序分享 URL 和 其它小程序分享的 URL 不一樣,要注意路徑的差異區(qū)分:例如:shareURL: 京東小程序: page/index/index 微信小程序:/pages/index/index
多端同步調(diào)試
在 config/index.js 配置:outputRoot: dist/${process.env.TARO_ENV}
生態(tài)與規(guī)劃
物流風(fēng)格的 Taro UI組件庫(kù)—Tarot(已適配Taro3.0)
定制化 Taro 模板工程定制化 Taro 模板工程
模板工程主要特性:
?自帶按需引入的 Tarot 組件庫(kù)及組件使用示例。
?自帶 pandora-tools 中的工具,如網(wǎng)關(guān)調(diào)用插件等。
?登陸適配多端,小程序端自動(dòng)引入京東無(wú)線(xiàn)登陸插件,h5端自動(dòng)跳轉(zhuǎn)無(wú)線(xiàn)統(tǒng)一登陸M頁(yè)d等。
?網(wǎng)關(guān)調(diào)用適配多端,自帶 Demo 示例;
?包含 TypeScript 和 Redux等更多高級(jí)API及用法示例;
?其它功能持續(xù)更新……
小程序 Mini Debug 工具
MiniDebug 是一款多端小程序調(diào)試工具,旨在提高小程序開(kāi)發(fā)、測(cè)試效率的工具庫(kù)
功能介紹:
主要功能包括環(huán)境切換、身份Mock、應(yīng)用信息獲取、位置模擬、緩存管理、掃一掃、H5跳轉(zhuǎn)、更新版本等。工具部分頁(yè)面如下圖所示:
目前已經(jīng)在 GitHub 上開(kāi)源(歡迎 issue):https://github.com/jdlfe/minidebug
物流風(fēng)格的小程序可視化拖拽平臺(tái)(規(guī)劃中)
京東商城已經(jīng)實(shí)現(xiàn)了小程序可視化拖拽平臺(tái):https://ling.jd.com/atom/cms/pc/06599
結(jié)語(yǔ):
Taro V3.0.0 目前支持 React、Nerv、Vue 三類(lèi)框架,在未來(lái) Taro 將開(kāi)放拓展能力,使得開(kāi)發(fā)者可以通過(guò) Taro 拓展更多的框架支持,(比如:適配 Flutter 將成為可能 )。目前Taro框架完善社區(qū)活躍,即使沒(méi)有多端需求,僅用 Taro 開(kāi)發(fā) H5 也是個(gè)不錯(cuò)的選擇(未來(lái)可以 0 成本接入小程序平臺(tái)),想了解更多 Taro 3.0 實(shí)踐經(jīng)驗(yàn)歡迎線(xiàn)下交流。