兩個月前,我們發佈了 Taro v3.6 的 canary 版本,在技術委員會和社區範圍內提供跨端路由庫、跨框架組件等主要能力和重要修復的測試,併發起社區投票正式確定了當前版本的代號 —— Reach。
日前 Taro v3.6 正式版本已經發布,下文將圍繞 3.6 版本內的跨端、平臺能力支持等多個方面展開,快速瞭解在 v3.6 中各個重要特性。
一、跨端能力支持—
支持各類跨端能力,抹平多端研發之間的體驗差異,是 Taro 一直以來嘗試去實現的,基於 Taro 3 適配多端前端 UI 框架的邏輯,通過在小程序端模擬實現框架所需的 BOM / DOM API 就能達成對於各類跨端能力的適配。
1. 支持路由庫
在 Web BOM 中,History & Location 對象是重要組成部分,它們是實現前端路由的關鍵。Taro 爲支持前端路由庫的使用,在運行時中引入了 histroy
location
對象的實現,同時儘可能與 Web 端規範對齊。通過在 window
對象上訪問到 history
和 location
對象,並支持監聽 hashchange
和 popstate
事件,爲跨端使用路由庫提供基礎。
// 統稱: 頁面路由狀態
window.history
window.location
// 支持監聽事件
window.addEventListener('hashchange', () => {})
window.addEventListener('popstate', () => {})
小程序天然支持多頁面(pages
數組配置),因此 Taro 並非以整個應用爲一個路由系統,而是順應小程序規範以頁面維度進行路由管理。每當切換頁面時,會將當前頁面的頁面路由狀態緩存。跳轉至新頁面後會重新創建頁面路由狀態,並掛載在 window
對象上。當返回上一級頁面時,會將上一級頁面的頁面路由狀態重新掛載到 window
對象中。
至此,可以在小程序中使用成熟的前端路由庫了,包括 react-router
和 vue-router
。在路由庫中,諸如 <Link>
組件內部會動態生成 <a>
標籤,因此需要引入 `@tarojs/plugin-html`[1] 插件以支持在 Taro 中使用 html
標籤開發組件。
{
"plugins": ["@tarojs/plugin-html"]
}
在 Taro 編譯過程中,當 DOM 序列化數據的 nn 字段爲 HTML 標籤時,標籤會映射爲對應的小程序組件名稱。由於無法提前預知動態標籤,因此需要應用顯式告知可能會使用到的動態標籤。例如在應用中塞入一個無樣式的標籤名即可:
<View>
<a></a>
</View>
更多細節可以查看 官方文檔[2],也可以查看官方提供的 DEMO 獲知更多用法。
2. 支持網絡請求庫
與適配各路由庫類似,通過對運行時補充就能支持絕大多數的網絡請求庫,所有請求庫在底層都是通過使用 XMLHttpRequest[3] 或 Fetch[4] 提供能力支持的,而請求庫大多都兼容 XMLHttpRequest
對象,也即是在提供 XMLHttpRequest
對象實現的基礎上,就能支持絕大多數的第三方庫。
支持這些成熟的網絡請求庫(例如 axios[5] 等)就能爲開發者在跨端研發場景下,提供更好的研發體驗。通過引入 @tarojs/plugin-http 插件,爲小程序環境提供網絡請求庫所需的運行時環境支持。
{
"plugins": ["@tarojs/plugin-http"]
}
“注意:當前 @tarojs/runtime 在小程序環境中缺少
”Blob
、FormData
、File
對象,這在網絡請求庫的文件上傳特性中是必須的,故暫不支持。
在支持網絡請求庫的同時,考慮到部分用戶,特別是 web 轉小程序的項目中依賴 cookie
實現鑑權,@tarojs/plugin-http 插件模擬實現了 document.cookie
api 以及通過 http 響應頭 Set-Cookie
來設置客戶端 cookie
值 ,行爲和 web 中保持一致。此功能默認設置爲關閉,需要的可通過 enableCookie
配置開啓。
參數名 | 類型 | 默認值 | 說明 |
---|---|---|---|
enableCookie | Boolean | false | 支持 document.cookie 、 通過後端返回 Set-Cookie 響應頭來設置 cookie |
disabledFormData | Boolean | true | 是否禁用 FormData 全局對象 |
disabledBlob | Boolean | true | 是否禁用 Blob 全局對象 |
在 @tarojs/plugin-http 插件中,以 axios
作爲基準庫完成測試,如果在使用其他請求庫時遇到適配問題,可在社區或通過 issues[6] 反饋相關信息。
二、平臺能力支持—
拓展更多端平臺,適配支持各端能力與特性,是跨端解決方案不斷髮展的重要組成部分之一。
1. 支持鴻蒙端平臺插件
在 Taro 與 OpenHarmony 建立官方合作關係,並受邀成立 CrossPlatformUI Sig[7](跨平臺前端框架興趣小組)後,讓 Taro 支持支配鴻蒙就一直在議程上,鴻蒙的方舟開發框架提供類 Web 範式編程,支持使用 JS 開發 UI 層,其語法與小程序相接近,可以沿用 Taro 現有的架構適配鴻蒙。
持續關注 Taro 的開發者可能還記得,在 v3.5-canary 版本時,我們曾推出支持 Taro 應用適配到鴻蒙平臺的插件,但最終沒有合入 v3.5 版本主幹並順勢推出該能力。
在 @tarojs/plugin-platform-harmony
端平臺插件經過一段時間的打磨,相關能力與特性也在社區推進下持續優化,框架編譯的項目在鴻蒙開發板上得到進一步驗證,同時在 Taro v3.5 新增的 @tarojs/webpack5-runner
編譯內核也能夠爲鴻蒙項目編譯提供支持,終於我們在 v3.6 中再次爲社區開發者提供了適配鴻蒙的端平臺插件。
// config/index.js
config = {
// 配置使用插件
plugins: ['@tarojs/plugin-platform-harmony'],
// harmony 相關配置
harmony: {
// 【必填】鴻蒙應用的絕對路徑
projectPath: path.resolve(process.cwd(), '../MyApplication'),
// 【可選】HAP 的名稱,默認爲 'entry'
hapName: 'entry',
// 【可選】JS FA 的名稱,默認爲 'default'
jsFAName: 'default'
}
}
具體使用方法可查看官方文檔[8],需要注意鴻蒙插件不在 Taro 項目內維護,所以並不會每次發佈同版本號版本,直接使用 minor 與 Taro 版本號相同的版本即可。
特別感謝以下同學爲鴻蒙適配作出的貢獻:
@AdvancedCat[9]、@jiaozitang[10]、@huozhongyi123[11]、@troy-sxj[12]、@JSZabc[13]、@crazyonebyone[14]、@evernoteHW[15]、@soulhat[16]、@xueshuai[17]、@LuMeiling[18]
2. React Native 能力
爲了讓整體開發體驗跟 RN 更加一致,減少開發者的理解成本。我們對 @tarojs/rn-runner 的代碼進行了重構。將 Taro RN 需要的所有編譯邏輯,都封裝到了 metro 配置中,與 RN 項目集成會更加靈活。
新版本在項目根目錄下會創建入口文件 index.js 和配置文件 metro.config.js。如項目本身有這兩個文件,則不會生成,需要參考模板[19]進行添加或合併。另外 Taro RN 的相關配置,集中在 resolver 和 transformer 中,可根據相關源碼自行覆蓋調整。
React Native 0.70 版本已於 2022-9-5 正式發佈[20],在 0.70 版本中 Hermes 已成爲默認的 JS 引擎,
v3.6 版本將與 RN 默認配置保持一致,如不需要可自行關閉。Hermes 也帶來了 RN 性能的較大提升,特別是啓動場景,詳細內容參考官方文章[21]。
Taro 將與 RN 社區保持同步,將默認的 RN 版本設置爲 0.70。相關依賴也已同步至最新版本,仍然可使用 yarn upgradePeerdeps
進行更新。@react-native-community/clipboard
及 @react-native-community/cameraroll
已被棄用,舊版本升級後需要刪除。
“注意:升級後將不再支持 iOS 12,詳細內容請參考 discussions[22]。同時 Taro Playground[23] 作爲 RN 端的調試工具及跨端 Demo 同步更新至 v3.6。
”
3. Web 端能力
通過在社區中收集的相關問題反饋,Taro Web 各類特性也一直在不斷推進,讓開發者在多端研發的體驗能夠儘可能達成一致。面對各類自定義 Web 端能力的需求,雖然有很多方案可以提供組件、API 等能力的補充,但類似小程序端平臺插件這樣的能力在 Web 端中並沒有得到支持。
在 3.6 版本中,我們將 Web 端各類定製化的能力從 runner 中轉移到 @tarojs/plugin-platform-h5
插件中提供,譬如通過配置 useHtmlComponents
模式替換使用的組件庫;註冊 Web Components 組件庫,配置各前端 UI 框架組件適配器;移除不必要的 API 等等特性。
class H5 extends TaroPlatformWeb {
// ...
}
export default (ctx) => {
ctx.registerPlatform({
name: 'h5',
useConfigName: 'h5',
async fn({ config }) {
const program = new H5(ctx, config)
await program.start()
},
})
}
和小程序端一樣,藉助於插件或 TaroPlatformWeb
基類,開發者可以很容易橫向或縱向拓展 Web 端的各項能力,詳情可參考文檔[24]。
Web 端也一直在補充各類開發者常用的組件與 API 抹平與小程序端的差異。在 v3.6 版本中新增生命週期、WXML 相關的 API 支持若干,例如:createIntersectionObserver
、createMediaQueryObserver
等,同時新增 movable-area
、movable-view
等組件支持。
在社區開發者交流時,我們也發現了部分研發場景下需要監聽各 API、組件不支持事件,相比於支持 canIUse 方法在跨端轉換場景中能夠更有效定位問題,所以通過支持 __taroNotSupport
事件滿足相關需求,可以參考以下示例使用。
interface IOption {
name: string // 不支持的組件或 API 名稱
type: 'method' | 'component' // 'method': API; 'component': 組件
category: 'permanently' | 'temporarily' | 'weixin_corp' // 'weixin_corp': 僅在微信公衆號 JS-SDK 環境下支持
args?: any[] // API 傳入參數
instance?: unknown // 組件實例
}
Taro.eventCenter.on('__taroNotSupport', (option: IOption) => {
console.warn('調用不支持的 API 或組件', option)
})
三、跨框架組件庫—
藉助於 stencil,Taro 3 得以通過 Web Components 實現一套跨框架組件庫,通過適配器將 Taro 的組件庫提供給各個前端 UI 框架使用,開發者也可以基於這些封裝上層組件,提供更多有趣的能力。
1. Web 端適配器
出於降低開發者維護門檻,與 stencil 組件庫打包流程更好兼容等多方面考慮,在 3.6 版本中我們在升級 stencil 依賴版本的同時,通過官方提供的 ds-output-target[25] 工具替換了原有的自定義適配器。
該版本適配器更好的抹平各個框架組件使用差異,補齊過往版本迭代過程中部分特性兼容性的缺失問題,爲開發者提供更好的體驗。在 3.6 中依舊保留過往版本各框架適配器,可以參考以下示例通過配置別名替換組件庫適配器(不建議使用,後續不會維護舊版適配器,可能無法得到新的組件或特性支持)。
// config/index.js
const config = {
h5: {
webpackChain(chain) {
chain.resolve.alias.set(
// 當前版本適配層地址 @tarojs/components/dist/[framework]
'@tarojs/components/dist/react',
// 舊版本適配層地址 @tarojs/components/dist/[framework]/component-lib
'@tarojs/components/dist/react/component-lib'
)
},
},
}
2. 虛擬列表
作爲從 Taro 3 開始支持的上層組件,虛擬列表應當是很多開發者都熟悉的特性,在過往版本中也有過數次升級,支持包括 unlimitedSize、relative 定位模式等特性,在 v3.6 版本中我們再次對虛擬列表做出了調整,將其從 @tarojs/components
包中抽離到 @tarojs/components-advanced 中維護(開發者依舊可以通過 @tarojs/components/virtual-list 引用虛擬列表組件),也歡迎大家一同參與上層組件庫的維護與共建,沉澱更多跨端可用的能力。
在新版本中,虛擬列表支持在選擇 preact、vue3 框架構建的項目中使用,同時在使用各個前端 UI 框架的項目中都支持使用選擇 absolute
、relative
不同定位方式,unlimitedSize 模式與傳入 itemSize 函數等特性也得到支持。
以 Vue 爲例,我們需要在入口文件聲明使用:
// app.js 入口文件
import Vue from 'vue'
import registerVirtualList from '@tarojs/components/virtual-list'
// Note: 使用以下路徑導出插件可以在 vue 中獲得更好的類型支持
// import registerVirtualList from '@tarojs/components-advanced/dist/components/virtual-list/vue'
Vue.use(registerVirtualList)
一個最簡單的長列表組件會像這樣,virtual-list
的 5 個屬性都是必填項:
<! –– row.vue 單項組件 ––>
<template>
<view :id="id" :class="index % 2 ? 'ListItemOdd' : 'ListItemEven'"> Row {{ index }} : {{ data[index] }} </view>
</template>
<script>
export default {
props: ['id', 'index', 'data'],
}
</script>
<! –– page.vue 頁面組件 ––>
<template>
<virtual-list
wclass="List"
:height="500"
:item-data="list"
:item-count="list.length"
:item-size="100"
:item="Row"
width="100%"
>
<! –– Vue 中支持列表首尾使用的插槽,對應 React 中的 renderTop、renderBottom 參數 ––>
<template v-slot:top>
<view>top</view>
</template>
<template v-slot:bottom>
<view>bottom</view>
</template>
</virtual-list>
</template>
<script>
import { markRaw } from 'vue'
import Row from './row.vue'
function buildData(offset = 0) {
return Array(100)
.fill(0)
.map((_, i) => i + offset)
}
export default {
data() {
return {
Row: markRaw(Row),
list: buildData(0),
}
},
}
</script>
“需要注意的是,爲抹平多框架參數差異便於維護,舊版本中部分命名會統一修改,比如在 React 版本中通過 children 傳入的子節點組件改爲 item;Vue 中的 wclass、wstyle 這類寫法也不再支持。
”
在新版本中,根據需求和研發場景合理設置 itemSize
、overscanCount
、placeholderCount
等參數優化長列表,可以獲得比舊版本更加順滑的體驗,更多詳情可以參考官方文檔[26]。
四、研發生態—
1. 小程序持續集成 CI
去年 Taro 提供小程序持續集成插件 @tarojs/plugin-mini-ci
,幫助開發者提供更好的研發體驗,經過一年的項目沉澱和反饋,在本次版本重構了去年的所有代碼,並提供了更優秀體驗和靈活的配置。
-
本次新增特性支持獨立的 open
、preview
、upload
命令,操作自定義目錄適用於將 taro 作爲項目一部分(混合開發)的開發場景; -
同步更新各個小程序端的 CI API 變更(阿里系、抖音小程序變化最大) -
新增釘釘小程序 CI 集成; -
新增京東小程序 CI 集成; -
統一所有平臺 CI 構建後的輸出數據,並將數據傳遞給新增的 onPreviewComplete
、onUploadComplete
兩個鉤子用戶可以編寫新的插件,基於這個鉤子實現 飛書、釘釘 的 CI 推送功能等等。
以下爲當前各平臺支持的功能情況表:
平臺/功能 | 自動打開 IDE | 輸出預覽二維碼 | 輸出體驗二維碼 |
---|---|---|---|
weapp | ✅ | ✅ | ✅ |
qywx | ✅ | ✅ | ✅ |
alipay | ✅ | ✅ | ✅ |
dd | ✅ | ✅ | ❌ |
swan | ✅ | ✅ | ✅ |
jd | ✅ | ✅ | ✅ |
ps:該插件在 taro3.6.0 版本以下亦可支持單獨使用,插件版本號無需保持與其他包同步。
更多詳情可以參考官方文檔[27],同時要特別感謝 @bigMeow[28] 爲 CI 自動化腳本做出的貢獻~
2. PostCSS 版本升級
在 Taro 項目持續迭代的過程中,部分依賴穩定沒有實時跟進各個社區內的特性與優化,並升級相關依賴,PostCSS 就是其中之一。如果開發者想要通過新版本的特性來優化構建流程與最終產物,相對會很困難且可能會存在一定問題阻塞。
爲此在 3.6 canary 通過梳理項目內相關插件與依賴,對 PostcCSS 版本進行梳理並升級,升級後版本爲 v8.4.18。本次升級主要包含以下內容:
-
對 Taro 內部的 PostCSS 插件使用 PostCSS 8 版本 API 進行改寫,降低代碼量同時減少插件對 CSS 掃描次數進而提高構建速度; -
使用 peerDependencies 管理 postCSS 依賴,降低用戶的 node_modules 體積和複雜度; -
對 Taro 全量模板的 PostCSS 版本同步進行更新,方便開發者對新特性的使用。
特別感謝 @xueshuai[29] 爲相關工作做出的貢獻,希望開發者可以因此獲得更好的研發體驗。
3. 類型與文檔自動同步
快速同步各平臺支持的類型,一直以來都是十分頭疼的問題之一,想要實時跟進各個平臺以提升用戶體驗十分困難,更多時候我們都通過開發者提交的 PR 或 issue 對這些平臺的類型更新維護。如果能夠根據各個小程序平臺官方提供的文檔自動化生成類型,這對於框架維護和開發者來說會是一個很棒的體驗。
通過在 Taro 社區中的積極探討[30]和論證,我們引入了自動同步各小程序平臺組件類型的腳本機制,並通過與 GitHub CI 讓機器人爲 Taro 倉庫提交類型更新 PR。組件類型的自動化同時讓 Taro 的文檔在類型更新時,同步這些平臺組件的變更,爲開發者提供更好的文檔索引能力。同時我們也在文檔提供了 canIUse[31] 頁面,供開發者快速檢索組件、特性在各個平臺支持的程度。
希望後續也能夠通過和各平臺合作的方式優化該能力,爲開發者提供更好的體驗。在這裏特別感謝 @rebinv8[32] 爲組件類型自動化腳本做出的貢獻~
4. Taro Playground 同步升級
作爲 RN 端的調試工具及跨端 Demo,Taro Playground[33] 同步更新 v3.6 更新。此次更新無法保證向下兼容,使用舊版本 Taro 的開發者,如需調試 Android,可在 releases[34] 中下載舊包進行調試。在 App Store 中,我們只上架最新版本,需要舊版本的開發者請不要開啓應用自動更新。如不慎升級,需自行打包編譯,或聯繫我們加入測試組。
五、升級指南—
1. 創建 v3.6 版本項目:
# 安裝 v3.6.0 的 CLI 工具
npm i -g @tarojs/cli@latest
# 創建項目
taro init taro_project
# 也可以跳過安裝 CLI 工具使用 npx 創建項目
npx @tarojs/cli@latest init taro_project
2. 已有項目升級到最新版本:
-
將 package.json 文件中 Taro 相關依賴修改爲 3.6.0
版本; -
Taro v3.6 將 web 端插件化,需要新增依賴 @tarojs/plugin-platform-h5
,同時@tarojs/router
、@tarojs/taro-h5
不再需要額外聲明依賴,可自行移除; -
重新安裝依賴,如果安裝失敗或打開項目失敗,可以刪除 node_modules
、yarn.lock
、package-lock.json
後重新安裝依賴重新嘗試。
最後—
自 Taro 引入技術委員會[35]等機制後,與社區互動愈加頻繁,Taro 也得益於諸多貢獻者[36]的幫助有能力去實現更多有意思的特性,給開發者帶來更好的用戶體驗,這也是 Taro v3.6 在代號「Reach」中的期待。感謝各位參與到 Taro 開源生態共建的同學們,所有的努力都讓 Taro 的生態更加美好,爲建立更加完善、更加可持續的 Taro 開源生態,貢獻力量!
參考資料
@tarojs/plugin-html
: https://nervjs.github.io/taro-docs/docs/use-h5
官方文檔: https://nervjs.github.io/taro-docs/docs/router-extend
[3]XMLHttpRequest: https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
[4]Fetch: https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API
[5]axios: https://axios-http.com/
[6]issues: https://github.com/NervJS/taro/issues
[7]CrossPlatformUI Sig: https://gitee.com/openharmony-sig/taro
[8]官方文檔: https://nervjs.github.io/taro-docs/docs/harmony
[9]@AdvancedCat: https://github.com/AdvancedCat
[10]@jiaozitang: https://github.com/jiaozitang
[11]@huozhongyi123: https://github.com/huozhongyi123
[12]@troy-sxj: https://github.com/troy-sxj
[13]@JSZabc: https://github.com/JSZabc
[14]@crazyonebyone: https://github.com/crazyonebyone
[15]@evernoteHW: https://github.com/evernoteHW
[16]@soulhat: https://github.com/soulhat
[17]@xueshuai: https://github.com/xueshuai
[18]@LuMeiling: https://github.com/LuMeiling
[19]模板: https://github.com/NervJS/taro-project-templates/tree/v3.6/react-native
[20]React Native 0.70 版本已於 2022-9-5 正式發佈: https://reactnative.dev/blog/2022/09/05/version-070
[21]官方文章: https://reactnative.dev/blog/2022/07/08/hermes-as-the-default
[22]discussions: https://github.com/NervJS/taro/discussions/12468
[23]Taro Playground: https://github.com/wuba/taro-playground
[24]參考文檔: https://nervjs.github.io/taro-docs/docs/next/platform-plugin/how#web-%E7%AB%AF%E5%B9%B3%E5%8F%B0%E6%8F%92%E4%BB%B6
[25]ds-output-target: https://github.com/ionic-team/stencil-ds-plugins/blob/master/README.md
[26]官方文檔: https://nervjs.github.io/taro-docs/docs/next/virtual-list#vue
[27]官方文檔: https://nervjs.github.io/taro-docs/docs/plugin-mini-ci
[28]@bigMeow: https://github.com/bigmeow
[29]@xueshuai: https://github.com/xueshuai
[30]探討: https://github.com/NervJS/taro/discussions/11740
[31]canIUse: https://nervjs.github.io/taro-docs/canIUse/
[32]@rebinv8: https://github.com/robinv8
[33]Taro Playground: https://github.com/wuba/taro-playground
[34]releases: https://github.com/wuba/taro-playground/releases
[35]技術委員會: https://nervjs.github.io/taro-docs/docs/team/#%E6%8A%80%E6%9C%AF%E5%A7%94%E5%91%98%E4%BC%9A
[36]貢獻者: https://nervjs.github.io/taro-docs/docs/team/role-committer
本文分享自微信公衆號 - 凹凸實驗室(AOTULabs)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。