別全解析:選型邏輯與互相內(nèi)嵌實(shí)操)
微信小程序和HTML5有什么區(qū)別如何互相內(nèi)嵌使用你有沒有過這種糾結(jié)公司推一個(gè)運(yùn)營活動(dòng)產(chǎn)品經(jīng)理說“做個(gè)小程序吧”你一看需求就是個(gè)落地頁加表單明明H5一天就能上線反過來業(yè)務(wù)要沉淀會(huì)員、要發(fā)訂閱消息你卻說不如寫個(gè)H5套個(gè)殼結(jié)果在微信里被各種能力限制折磨到懷疑人生。這種糾結(jié)我太熟了。我前前后后做了十幾個(gè)小程序也寫了大量H5活動(dòng)頁最常被問的問題就是“微信小程序和HTML5到底有什么區(qū)別能不能互相內(nèi)嵌”。這兩個(gè)東西看著都在手機(jī)里打開但設(shè)計(jì)思路、運(yùn)行環(huán)境、能力邊界完全是兩套玩法。這篇文章我不打算來一段教科書式的對(duì)比而是直接站在干活的人角度把區(qū)別講清楚把選型的判斷邏輯說透再把內(nèi)嵌的實(shí)操姿勢和踩坑經(jīng)歷全部分享出來。打算做微信生態(tài)項(xiàng)目的研發(fā)、前端或者正在為畢設(shè)選型的學(xué)生都能從里面找到可以直接用的東西。1. 微信小程序和HTML5的定位差異不只是“運(yùn)行環(huán)境”不同1.1 一個(gè)是生態(tài)里的“公民”一個(gè)是互聯(lián)網(wǎng)的“通用語言”很多人理解兩者的區(qū)別停留在“小程序跑在微信里H5跑在瀏覽器里”。這話沒錯(cuò)但沒說到根上。真正的差異是小程序是微信生態(tài)里的“公民”H5則是互聯(lián)網(wǎng)上的“通用語言”。為什么這么說小程序從出生開始就被微信的規(guī)則體系包圍著需要注冊(cè)、審核、類目資質(zhì)要遵守微信的使用規(guī)范有包體積限制甚至因?yàn)檫`規(guī)會(huì)被暫停支付功能。我見過不少項(xiàng)目前腳代碼寫得沒問題后腳因?yàn)轭惸坎粚?duì)被限制了支付能力用戶在頁面里下單半天就是彈不出收銀臺(tái)。這種約束在H5世界里是不存在的——任何一個(gè)人只要有服務(wù)器和一個(gè)備案過的域名就能把頁面鏈接甩到任何渠道。但這不代表自由就好。H5最大的痛點(diǎn)是“身份缺席”。它在微信內(nèi)置瀏覽器里是一張網(wǎng)頁沒辦法像小程序那樣直接拿到用戶在小程序里的身份也調(diào)不到那些微信專屬能力。你可以用公眾號(hào)網(wǎng)頁授權(quán)的形式搞到openid但做不到小程序那種“點(diǎn)開就用”的輕快感。你要是做過微信生態(tài)里的H5一定被“請(qǐng)?jiān)谖⑿趴蛻舳舜蜷_”“當(dāng)前頁面無法使用微信支付”這類提示支配過。所以從定位上講如果你要做的是交易閉環(huán)、服務(wù)閉環(huán)并且希望用戶在微信里完成整個(gè)流程小程序天然更合適如果你做的是內(nèi)容展示、外部渠道引流、活動(dòng)落地頁H5幾乎是無腦選擇。1.2 運(yùn)行機(jī)制、加載體驗(yàn)、開發(fā)體驗(yàn)的差異差異不光在“身份”上技術(shù)底層的差異也直接影響產(chǎn)品體驗(yàn)。小程序雖然是運(yùn)行在微信客戶端里的但它不是簡單的“網(wǎng)頁套殼”。微信小程序采用雙線程模型邏輯層跑在JSCore或V8引擎上UI層由WebView渲染。邏輯層不直接操作DOM而是通過一套數(shù)據(jù)綁定機(jī)制跟UI層通信。這種架構(gòu)帶來的好處是頁面切換更接近原生App的流暢度部分頁面可以降低加載成本。代價(jià)是你不能像寫網(wǎng)頁那樣隨手操作DOM一切數(shù)據(jù)更新都要通過setData來完成數(shù)據(jù)量太大還會(huì)明顯卡頓。H5就是另一套邏輯。它直接跑在瀏覽器或WebView里HTML、CSS、JavaScript一把梭但頁面的渲染性能、切換流暢度完全取決于宿主WebView的優(yōu)化程度。微信內(nèi)置瀏覽器還做了很多白名單和緩存限制你辛辛苦苦寫的PWA離線能力在微信里經(jīng)常會(huì)失效。很多H5頁面體驗(yàn)不如小程序不是寫H5的人技術(shù)不行而是這個(gè)運(yùn)行環(huán)境本身就決定了它的上限。開發(fā)體驗(yàn)上差別也很大。小程序的語法是自定義的WXML、WXSS、JS和JSON配置雖然現(xiàn)在也能用TypeScript和一些編譯型框架但整體調(diào)試離不開微信開發(fā)者工具發(fā)布流程要走審核、灰度、全量發(fā)布。H5則可以用任何現(xiàn)代前端框架Vue、React隨便選部署到自己的服務(wù)器發(fā)版不需要等任何人審批。這一點(diǎn)在出線上尤其實(shí)用——我做過一個(gè)H5活動(dòng)頁上午改完代碼中午就能把新鏈接發(fā)給運(yùn)營小程序想做到這種效率難度大得多。1.3 從高頻熱搜看真實(shí)痛點(diǎn)和選型信號(hào)你看網(wǎng)上關(guān)于小程序和H5的高頻熱搜很少直接是“哪個(gè)好”更多是具體問題比如“小程序微信支付v3對(duì)接”“swiper嵌套video全屏錯(cuò)位”“頂部導(dǎo)航欄高度”“自定義標(biāo)題上邊距怎么弄”。這些詞背后藏著真實(shí)開發(fā)者的痛苦不是不知道怎么選型而是選了之后發(fā)現(xiàn)某個(gè)能力做不出來或者做出來以后一堆坑。拿“頂部導(dǎo)航欄高度”來說這個(gè)問題在小程序里幾乎人人都會(huì)遇到。小程序原生導(dǎo)航欄和H5頁面里的header不是一回事微信各版本、各機(jī)型的導(dǎo)航欄高度有細(xì)微差異自定義導(dǎo)航欄時(shí)還得手動(dòng)適配狀態(tài)欄高度。你要是沒處理過真機(jī)上一跑標(biāo)題要么頂?shù)綘顟B(tài)欄里要么被膠囊按鈕遮擋。類似這種細(xì)節(jié)在H5里反而不是很常見——瀏覽器本身已經(jīng)幫我們處理了大部分。再說“小程序微信支付v3對(duì)接”為什么這個(gè)問題這么火因?yàn)楹芏嗳四J(rèn)“小程序內(nèi)嵌H5之后H5里也能直接調(diào)起微信支付”結(jié)果繞了一大圈發(fā)現(xiàn)根本沒有那么簡單。小程序內(nèi)嵌的H5頁面受限于運(yùn)行環(huán)境支付能力和普通瀏覽器里的H5完全不一樣。這些問題不是孤立的它們會(huì)直接影響選型決策。你在設(shè)計(jì)階段就得想清楚核心功能要讓微信原生小程序來做還是可以放到網(wǎng)頁里2. 到底該選小程序還是H5我常用的取舍邏輯2.1 三個(gè)判斷維度能力依賴、獲客路徑、迭代速度我不喜歡給出一張萬能的“選型表”因?yàn)槊總€(gè)項(xiàng)目的約束條件不一樣。但在實(shí)際工作中我基本用三個(gè)維度去衡量大家可以照著做自己的決策。第一個(gè)維度是“是否強(qiáng)依賴微信生態(tài)能力”。如果你的產(chǎn)品要用微信登錄、微信支付、訂閱消息、藍(lán)牙、NFC、掃碼、地理位置這種能力而且要求體驗(yàn)鏈路完整那直接上小程序不要想著用H5硬磕。H5在微信內(nèi)置瀏覽器里能調(diào)的JS-SDK能力是有限的有些能力還要用戶手動(dòng)授權(quán)體驗(yàn)非常割裂。第二個(gè)維度是“用戶從哪里來要到哪里去”。如果流量主要靠公眾號(hào)文章、群聊分享、搜索引擎、短信、外部廣告投放那H5天然更有優(yōu)勢因?yàn)橐粋€(gè)鏈接就能鋪到幾十個(gè)渠道。小程序雖然也有二維碼和分享卡片但很多非微信渠道里點(diǎn)開小程序鏈接是很別扭的。反過來如果流量來自線下掃碼、微信搜一搜、導(dǎo)購聊天場景小程序更順。第三個(gè)維度是“迭代速度和違規(guī)風(fēng)險(xiǎn)”。小程序從代碼提交到線上審核哪怕一切順利也要預(yù)留幾天時(shí)間遇到版本駁回、類目資質(zhì)問題時(shí)間根本不可控。H5沒有上線審核這一步出了問題當(dāng)天就能修復(fù)。但H5在微信里也并非絕對(duì)自由尤其涉及到支付、分享類功能時(shí)風(fēng)控?cái)r截一樣存在。2.2 典型業(yè)務(wù)場景怎么選拿電商舉個(gè)例子。核心用戶在微信公眾號(hào)、朋友圈觸點(diǎn)里看到內(nèi)容然后跳轉(zhuǎn)到商品詳情頁購買這種情況我一般建議小程序?yàn)橹?、H5為輔。小程序有微信支付、模板消息這類促轉(zhuǎn)化的能力“下單后服務(wù)號(hào)推送一條發(fā)貨通知”的體驗(yàn)是網(wǎng)頁很難做到的。H5可以在廣告投放、外部渠道承擔(dān)引流落地頁的角色。至于內(nèi)容社區(qū)、資訊閱讀這類場景H5會(huì)更舒服。內(nèi)容類產(chǎn)品講究快速迭代、低門檻分享一個(gè)鏈接發(fā)出去誰都能看不需要下載也不需要先登錄個(gè)微信。如果后續(xù)要做付費(fèi)訂閱、會(huì)員體系再考慮把用戶的留存部分遷到小程序里用來發(fā)通知、做每日簽到。工具類應(yīng)用比如課程表、考證刷題、成績查詢我傾向用小程序。因?yàn)檫@類產(chǎn)品核心是“低頻但必須提醒”小程序的訂閱消息功能太合適了。很多畢設(shè)項(xiàng)目比如“基于微信小程序的駕校模擬考試系統(tǒng)”“校園跑腿系統(tǒng)”選小程序不是因?yàn)樾〕绦蚨喔呒?jí)而是這些需求天然包含表單填寫、列表查詢、支付、消息通知小程序把這些串成了一個(gè)完整閉環(huán)后端用SpringBoot提供接口就行。還有一個(gè)場景很多人忽略企業(yè)內(nèi)部系統(tǒng)、運(yùn)營后臺(tái)。這類頁面經(jīng)常要改用H5放在內(nèi)網(wǎng)或加了權(quán)限控制的服務(wù)器上簡直不要太爽。你要是非把它做成小程序每次改需求都走審核運(yùn)營和產(chǎn)品會(huì)把你“供”起來的。2.3 技術(shù)棧的影響uniapp兩套都能出不代表不用取舍現(xiàn)在很多團(tuán)隊(duì)喜歡用uniapp一把梭一套代碼同時(shí)發(fā)布成小程序和H5。這個(gè)思路本身沒毛病能極大降低中小團(tuán)隊(duì)的成本。我之前有個(gè)項(xiàng)目就用uniapp開發(fā)小程序端和H5端共用一套業(yè)務(wù)代碼效率確實(shí)高。但要有個(gè)清醒認(rèn)識(shí)uniapp解決的是“工程層面的復(fù)用”解決不了“平臺(tái)能力的差異”。哪怕同一套代碼編譯成兩端你在小程序端可以爽快使用藍(lán)牙、NFC等原生能力H5端該沒有還是沒有。更麻煩的是兩邊會(huì)互相拖累為了兼容H5UI層可能沒法充分使用小程序的原生組件為了兼容小程序H5端又沒法使用部分瀏覽器特性。所以我的建議是用uniapp立項(xiàng)沒問題但開場之前就要明確主戰(zhàn)場在哪里。主打微信生態(tài)就優(yōu)先保證小程序端體驗(yàn)H5端保證功能和數(shù)據(jù)同步即可。千萬別追求兩端“完全一致”那是給自己挖坑。3. 互相內(nèi)嵌怎么做兩種主流姿勢都給你捋清楚技術(shù)選型不是非黑即白很多時(shí)候兩邊要配合著用。下面這段是整篇文章的實(shí)操核心我會(huì)把兩種內(nèi)嵌方向的做法講清楚同時(shí)把過程中的關(guān)鍵限制也說破。3.1 小程序里嵌入H5web-view組件全流程小程序官方提供了web-view組件可以直接把整個(gè)頁面鋪成一個(gè)內(nèi)嵌瀏覽器窗口。用法看起來很簡單但前置條件特別多我一步步說。第一步你要有一個(gè)HTTPS且已經(jīng)ICP備案的域名域名要支持從小程序的web-view里訪問。為什么強(qiáng)調(diào)HTTPS因?yàn)樾〕绦驅(qū)Π踩髽O高非HTTPS域名在實(shí)機(jī)上大概率加載不出來。第二步在小程序管理后臺(tái)的“開發(fā)-開發(fā)設(shè)置-業(yè)務(wù)域名”里把你這個(gè)域名配置進(jìn)去。配置的時(shí)候需要下載一個(gè)校驗(yàn)文件放到網(wǎng)站根目錄微信會(huì)去驗(yàn)證歸屬權(quán)。這一步很容易被忽略我見過有人代碼完全沒問題就是業(yè)務(wù)域名沒校驗(yàn)web-view一直白屏。第三步在頁面的WXML里寫web-view srchttps://yourdomain.com/pages/activity?id123456tokenxxx bindmessageonMessage/web-viewsrc就是要加載的H5地址你可以通過URL參數(shù)的方式往頁面里傳一些初始數(shù)據(jù)。bindmessage用來接收頁面里通過postMessage傳回來的消息。這里有幾個(gè)關(guān)鍵限制要提前了解。web-view組件會(huì)自動(dòng)占滿整個(gè)頁面它不是頁面里的一個(gè)普通組件沒法放在什么“上半屏”“下半屏”里。還有web-view里面加載的H5頁面運(yùn)行環(huán)境本質(zhì)上是網(wǎng)頁環(huán)境不是小程序環(huán)境所以H5頁面里無法直接調(diào)用wx.requestPayment這類小程序原生API。那怎么在小程序和web-view之間通信方向是從H5往小程序傳H5頁面里引入微信JSSDK然后調(diào)用wx.miniProgram.postMessage({ data: { type: orderSucceed, orderId: 202501012345 } });小程序端通過bindmessage事件收取消息。但這里藏著一個(gè)巨大的坑postMessage傳回來的消息不是實(shí)時(shí)觸發(fā)小程序的而是在特定時(shí)機(jī)才會(huì)上報(bào)比如用戶分享、返回上一頁、組件銷毀等。你要是想在支付成功后立刻拿到回調(diào)去更新小程序原生界面用這個(gè)方案會(huì)非常痛苦。正確的姿勢應(yīng)該是H5把狀態(tài)發(fā)給后端后端再通過一些消息通道告訴小程序或者干脆只在進(jìn)入下一頁面時(shí)攜帶狀態(tài)參數(shù)。3.2 H5里喚起小程序URL Scheme、URL Link和開放標(biāo)簽反方向的內(nèi)嵌——H5頁面里喚起小程序也有幾種官方姿勢根據(jù)觸發(fā)場景不同要選不同的方案。第一種是URL Scheme/URL Link。你可以調(diào)用微信的接口把一個(gè)小程序頁面地址轉(zhuǎn)換成一個(gè)可以識(shí)別的scheme或link然后在H5頁面里通過跳轉(zhuǎn)鏈接的方式喚起小程序。URL Scheme適用于微信內(nèi)H5、短信、郵件這類場景URL Link更適合在App或外部瀏覽器里喚起小程序。生成這個(gè)鏈接需要服務(wù)端調(diào)用微信接口需要AppID和AppSecret有的還需要先綁定關(guān)聯(lián)。第二種是微信JS-SDK里的開放標(biāo)簽叫wx-open-launch-weapp。這個(gè)只能在微信內(nèi)置瀏覽器里用好處是用戶不用離開當(dāng)前頁面就能直接喚起小程序體驗(yàn)不像跳轉(zhuǎn)scheme那么生硬。使用方式大概是wx-open-launch-weapp idlaunch-btn usernamegh_xxxxxxxx pathpages/index/index?fromh5campaignspring script typetext/wxtag-template style.btn { padding: 12px; }/style div classbtn打開小程序/div /script /wx-open-launch-weappusername是小程序的原始ID在公眾號(hào)后臺(tái)的“基本配置”里能找到path是打開的頁面路徑。重點(diǎn)說一下這個(gè)開放標(biāo)簽渲染出來的內(nèi)容必須用script typetext/wxtag-template包起來不能像普通HTML那樣直接寫子元素否則標(biāo)簽不生效。還有調(diào)用前要先通過wx.config注入配置把openTagList: [wx-open-launch-weapp]放進(jìn)去JSSDK才會(huì)認(rèn)識(shí)這個(gè)標(biāo)簽。我在項(xiàng)目里遇到過一個(gè)問題開放標(biāo)簽在開發(fā)者工具的“公眾號(hào)網(wǎng)頁測試環(huán)境”里點(diǎn)了沒反應(yīng)。后來排查發(fā)現(xiàn)這個(gè)標(biāo)簽對(duì)調(diào)用環(huán)境非常挑剔必須在真實(shí)微信客戶端里才能正常喚起。遇到這個(gè)問題不用慌直接拿手機(jī)、在微信里打開H5頁面掃碼測試就行。3.3 內(nèi)嵌場景的通信、鑒權(quán)和參數(shù)傳遞怎么做才穩(wěn)內(nèi)嵌最核心的技術(shù)難點(diǎn)不在“打開”而在“打通身份”。小程序用戶默認(rèn)是天然的微信登錄態(tài)但H5頁面沒有這個(gè)身份。最通用的做法是在小程序端拿到用戶登錄后的code或自定義token拼到web-view的URL參數(shù)里帶過去H5頁面通過這個(gè)token向后端換取自己的登錄態(tài)。舉個(gè)例子小程序端web-view srchttps://yourdomain.com/page?tokenxxx_encrypted_token/web-viewH5頁面加載后從URL里取出token再調(diào)用后端接口驗(yàn)簽驗(yàn)證通過后setCookie或者存localStorage后續(xù)請(qǐng)求都帶著登錄態(tài)。這里有幾個(gè)細(xì)節(jié)要注意。第一token不要塞太長URL長度有限制而且含有很多特殊符號(hào)時(shí)會(huì)導(dǎo)致地址解析失敗最好讓后端生成一個(gè)短token有效期也不宜過長。第二不要放太敏感的信息比如手機(jī)號(hào)、身份證這種放token就夠了其他信息讓H5通過接口去查。第三web-view里的H5是個(gè)獨(dú)立瀏覽器上下文它跟小程序之間沒有共享的storage和cookie你指望“小程序已經(jīng)登錄了H5自動(dòng)就是登錄態(tài)”是不現(xiàn)實(shí)的必須走一遍token傳遞和鑒權(quán)。反過來如果你想從H5里帶數(shù)據(jù)到小程序除了之前說的postMessage更簡單輕量的方式是用URL參數(shù)。小程序側(cè)可以先拿到一個(gè)后端生成的短鏈然后跳轉(zhuǎn)到承載該短鏈的H5頁面H5內(nèi)部操作完之后跳轉(zhuǎn)到另一個(gè)約定好的小程序頁面路徑把狀態(tài)參數(shù)帶回去。這種方式不依賴實(shí)時(shí)通信邏輯上也更清晰。4. 內(nèi)嵌后必踩的坑導(dǎo)航、支付、視頻與調(diào)試4.1 web-view里的導(dǎo)航欄問題返回箭頭、自定義標(biāo)題、上邊距我搜資料的時(shí)候發(fā)現(xiàn)“微信小程序內(nèi)嵌h5 工具欄左側(cè)返回箭頭沒有了”這個(gè)問題特別多人問。很多人以為把H5塞進(jìn)小程序就萬事大吉了結(jié)果頁面里面的返回邏輯全亂了。原因是這樣的小程序內(nèi)嵌web-view后頁面頂端那一條導(dǎo)航欄是小程序原生導(dǎo)航欄它默認(rèn)會(huì)根據(jù)頁面棧提供返回箭頭。但如果你在H5內(nèi)部進(jìn)行了多級(jí)跳轉(zhuǎn)或者H5頁面自己寫了history路由微信在部分場景下會(huì)出現(xiàn)“返回箭頭消失”或者“按返回直接退出小程序”的詭異行為。為什么因?yàn)閣eb-view的頁面棧是獨(dú)立的它跟小程序的頁面導(dǎo)航棧并不是完全同步的。尤其是在uni-app這類跨端框架里有些同學(xué)為了隱藏原生導(dǎo)航欄用了custom-navigation模式結(jié)果web-view一進(jìn)去整個(gè)頂部全沒了。我的建議很簡單如果嵌入式H5只是個(gè)單頁活動(dòng)在小程序里就保留原生導(dǎo)航欄設(shè)置好標(biāo)題返回按鈕交給系統(tǒng)處理別自己在H5里再加一個(gè)返回按鈕。如果H5內(nèi)部確實(shí)有跳轉(zhuǎn)層級(jí)那你就要在小程序原生導(dǎo)航欄上做自定義左上角按鈕或者干脆讓H5內(nèi)部完全接管導(dǎo)航小程序端隱藏導(dǎo)航欄。接著是“自定義標(biāo)題、上邊距”的問題。很多人做自定義導(dǎo)航欄的時(shí)候最常犯的錯(cuò)誤是拿一個(gè)固定像素值硬編碼。不同機(jī)型的劉海屏、狀態(tài)欄高度都不一樣正確做法是從系統(tǒng)API里取const windowInfo wx.getWindowInfo(); const statusBarHeight windowInfo.statusBarHeight; // 導(dǎo)航欄內(nèi)容的安全高度 statusBarHeight 導(dǎo)航欄本身高度再用padding-top: calc(環(huán)境變量 statusBarHeight 44px)去給內(nèi)容讓位才能保證iPhone和Android的頂部都不會(huì)被擋。小程序端還支持env(safe-area-inset-top)在劉海屏上更穩(wěn)妥。4.2 內(nèi)嵌頁里的支付問題微信支付v3與平臺(tái)證書支付是內(nèi)嵌場景里最頭大的事。很多人搜“小程序微信支付v3對(duì)接 無可用的平臺(tái)證書”我都替他們著急因?yàn)檫@個(gè)問題的解法往往根本不在小程序前端而在后端配置上。先說環(huán)境限制。小程序web-view里的H5頁面不能直接調(diào)用wx.requestPayment小程序支付也不能走普通網(wǎng)頁版的JSAPI支付流程。你如果嘗試在H5頁面里引入JSAPI拉起收銀臺(tái)大概率會(huì)遇到“當(dāng)前環(huán)境不支持”的報(bào)錯(cuò)。所以項(xiàng)目設(shè)計(jì)階段就要定好交易動(dòng)作盡量放在小程序原生頁面完成H5只負(fù)責(zé)展示和引導(dǎo)。如果實(shí)在必須在H5里支付那要看你的H5跑在哪里——普通微信外的H5用Native支付微信內(nèi)但非小程序運(yùn)行環(huán)境可以用JSAPI但內(nèi)嵌到小程序里后這條路往往走不通。再來說v3對(duì)接。微信支付v3的接口體系里最煩的就是證書體系。很多人遇到“無可用的平臺(tái)證書請(qǐng)?jiān)谏虘羝脚_(tái)-API安全申請(qǐng)使用微信支付公鑰”是因?yàn)関3要求商戶下載API證書并且用平臺(tái)證書去驗(yàn)證微信服務(wù)器的應(yīng)答。不少同學(xué)在本地測試沒問題上服務(wù)器就報(bào)錯(cuò)多半是證書路徑?jīng)]配好、或者SDK版本太舊導(dǎo)致無法自動(dòng)加載平臺(tái)證書。按微信支付的規(guī)范流程你需要在商戶平臺(tái)申請(qǐng)API證書拿到商戶私鑰、商戶證書序列號(hào)然后在服務(wù)端配置好。v3的流程本質(zhì)上是商戶用私鑰簽名請(qǐng)求微信用商戶公鑰驗(yàn)簽微信應(yīng)答時(shí)用平臺(tái)私鑰簽名商戶用平臺(tái)證書驗(yàn)簽。這里最容易踩的坑是有些人把“API證書”和“平臺(tái)證書”搞混或者本地和線上配置的證書不一致導(dǎo)致驗(yàn)簽失敗。我建議直接在服務(wù)端統(tǒng)一封裝一個(gè)支付模塊把證書加載和簽名邏輯放到一起像各種官方SDK或開源的wechatpay-java這類組件能省下很多時(shí)間。4.3 組件兼容與真機(jī)適配video嵌套、軟鍵盤、導(dǎo)航高度技術(shù)細(xì)節(jié)里的坑最折磨人。我之前做的一個(gè)項(xiàng)目首頁用swiper輪播每一個(gè)輪播圖里再嵌套一個(gè)video視頻在小程序開發(fā)者工具里表現(xiàn)完美一上真機(jī)iOS全屏播放時(shí)畫面直接錯(cuò)位、黑屏、甚至閃退回桌面。這個(gè)問題不是玄學(xué)根因是video組件在小程序和H5里的渲染機(jī)制差異極大。小程序里的video是原生組件層級(jí)天然在最頂層容易被其他組件遮擋也容易在轉(zhuǎn)屏和全屏?xí)r出現(xiàn)渲染錯(cuò)亂。雖然說現(xiàn)在有“同層渲染”能力但在iOS上配合swiper使用時(shí)全屏狀態(tài)下的坐標(biāo)計(jì)算經(jīng)常會(huì)出問題。我最終的解決方案是放棄“輪播視頻”這個(gè)布局改成第一屏播放封面圖點(diǎn)擊后跳轉(zhuǎn)到一個(gè)獨(dú)立的小程序頁面去全屏播放視頻。如果你不想改布局也可以嘗試去掉全屏播放能力、用cover-view給video封面但說實(shí)話最簡單粗暴的方案往往最穩(wěn)定。再說軟鍵盤遮擋問題。熱搜里有一條“uniapp微信小程序手機(jī)軟鍵盤會(huì)遮擋住查詢內(nèi)容”這種問題在小程序和H5里都很常見。解決思路一般是給輸入框設(shè)置cursor-spacing讓光標(biāo)離輸入框有一定間距或者監(jiān)聽鍵盤高度變化動(dòng)態(tài)上推頁面。小程序的原生textarea和input有相關(guān)屬性可以配置但如果是在web-view里加載H5瀏覽器本身的鍵盤彈起邏輯往往就夠用了只要不是特別變態(tài)的OS版本一般都能自動(dòng)滾動(dòng)。4.4 調(diào)試、發(fā)布與合規(guī)提醒最后聊點(diǎn)流程層面的東西。小程序內(nèi)嵌H5之后調(diào)試復(fù)雜了很多。開發(fā)者工具里雖然有web-view模擬環(huán)境但跟真實(shí)微信客戶端的差異還是很大的經(jīng)常出現(xiàn)“開發(fā)者工具正常、真機(jī)白屏”的情況。我的經(jīng)驗(yàn)是業(yè)務(wù)域名、校驗(yàn)文件、HTTPS證書、URL參數(shù)、微信JSSDK版本這五個(gè)因素一個(gè)個(gè)過一遍九成的白屏問題都能解決。說到調(diào)試有些同學(xué)喜歡用各種抓包工具去分析小程序或H5的請(qǐng)求。這里我得提醒一句抓包只建議用在自己開發(fā)的、有授權(quán)的應(yīng)用上為什么因?yàn)榫€上小程序是別人的線上服務(wù)未經(jīng)授權(quán)去抓取和解析請(qǐng)求數(shù)據(jù)輕則是不道德重則可能違反相關(guān)法律和平臺(tái)規(guī)則。做開發(fā)調(diào)試用官方開發(fā)者工具的網(wǎng)絡(luò)面板、遠(yuǎn)程調(diào)試功能已經(jīng)足夠覆蓋絕大多數(shù)場景沒必要上來就上各類代理工具。發(fā)布階段還要注意幾個(gè)合規(guī)問題。新備案的域名、過期證書、改動(dòng)過的校驗(yàn)文件都可能讓內(nèi)嵌頁面瞬間失效。最好在運(yùn)維側(cè)建一個(gè)“內(nèi)嵌頁面發(fā)布檢查清單”每次改動(dòng)域名或證書后先在體驗(yàn)版里跑通再放全量。小程序的線上違規(guī)問題比如“由于小程序違規(guī)支付功能暫時(shí)無法使用”這類提示通常是賬號(hào)資質(zhì)或內(nèi)容審核導(dǎo)致的跟代碼本身關(guān)系不大遇到后不要只盯著代碼修要去小程序管理后臺(tái)看具體的違規(guī)通知和申訴入口。說到底微信小程序和H5的關(guān)系不是“二選一”的對(duì)手關(guān)系而像一個(gè)院子里的一棟樓和一個(gè)花園各有用處。我自己現(xiàn)在做項(xiàng)目基本都會(huì)先畫一張用戶體驗(yàn)地圖用戶的入口在哪里、核心動(dòng)線是什么、哪些環(huán)節(jié)必須依賴微信能力、哪些內(nèi)容只需要鏈接分享。畫完之后小程序和H5的分工往往一目了然。這里也分享一個(gè)我這幾年摸索出來比較穩(wěn)的組合拳核心交易鏈路、用戶中心、消息提醒放在小程序原生頁面里活動(dòng)營銷、長文內(nèi)容、外部投放落地頁、不需要重交互的功能交給H5按需讓它們互相內(nèi)嵌小程序里的H5不要承載太重的業(yè)務(wù)邏輯保持它“內(nèi)容層”的定位。這樣既保住了體驗(yàn)又保住了迭代速度。如果你要問我具體的操作順序我的建議是先把業(yè)務(wù)域名、HTTPS證書、校驗(yàn)文件這三件套搞好再動(dòng)手開發(fā)內(nèi)嵌頁面這是最省時(shí)間的路徑。別一上來就寫H5頁面寫到一半發(fā)現(xiàn)域名沒過審那才是真的白忙活。