Web頁面出現(xiàn)白屏的原因眾多,本文列舉了若干常見白屏問題的排查步驟,供開發(fā)者快速定位。
1.首先排查權(quán)限和網(wǎng)絡(luò)狀態(tài)。
2.通過使用DevTools工具調(diào)試前端頁面定位具體報(bào)錯(cuò)類型(跨域、資源404、JS異常)。
3.在復(fù)雜布局場(chǎng)景中,排查渲染模式及組件約束條件的問題。
4.處理H5代碼兼容性問題。
5.從日志中排查生命周期和網(wǎng)絡(luò)加載相關(guān)關(guān)鍵字。
檢查權(quán)限和網(wǎng)絡(luò)狀態(tài)
如果應(yīng)用未開啟聯(lián)網(wǎng)或文件訪問權(quán)限或者設(shè)備網(wǎng)絡(luò)狀態(tài)不佳,將導(dǎo)致Web組件加載失敗或頁面元素缺失,進(jìn)而引起白屏。
驗(yàn)證設(shè)備的網(wǎng)絡(luò)狀態(tài),包括是否已連接網(wǎng)絡(luò),設(shè)備自帶的瀏覽器能否正常訪問網(wǎng)頁等(在線頁面場(chǎng)景)。
確保應(yīng)用已添加網(wǎng)絡(luò)權(quán)限:ohos.permission.INTERNET(在線頁面必需)。
// 在module.json5中添加相關(guān)權(quán)限
"requestPermissions":[
{
"name":"ohos.permission.INTERNET"
}
]
開啟相關(guān)權(quán)限:

// xxx.ets
import{ webview }from'@kit.ArkWeb';
@Entry
@Component
structWebComponent{
controller: webview.WebviewController=newwebview.WebviewController();
build() {
Column() {
Web({src:'www.example.com',controller:this.controller})
.domStorageAccess(true)
.fileAccess(true)
.imageAccess(true)
.onlineImageAccess(true)
.javaScriptAccess(true)
}
}
}
修改UserAgent后再觀察頁面是否恢復(fù)正常。
// xxx.ets
import{ webview }from'@kit.ArkWeb';
import{BusinessError}from'@kit.BasicServicesKit';
@Entry
@Component
structWebComponent{
controller: webview.WebviewController=newwebview.WebviewController();
@StatecustomUserAgent:string=' DemoApp';
build() {
Column() {
Web({src:'www.example.com',controller:this.controller})
.onControllerAttached(() =>{
console.log("onControllerAttached");
try{
letuserAgent =this.controller.getUserAgent() +this.customUserAgent;
this.controller.setCustomUserAgent(userAgent);
}catch(error) {
console.error(`ErrorCode:${(errorasBusinessError).code}, Message:${(errorasBusinessError).message}`);
}
})
}
}
}
使用DevTools工具進(jìn)行頁面內(nèi)容驗(yàn)證
在確保網(wǎng)絡(luò)與權(quán)限配置無誤后,若仍出現(xiàn)白屏,則應(yīng)利用DevTools工具調(diào)試前端頁面以及監(jiān)聽Web相關(guān)錯(cuò)誤上報(bào)接口,來定位具體報(bào)錯(cuò)類型。
1.查閱控制臺(tái)的錯(cuò)誤信息,定位具體的資源加載失敗問題。資源加載失敗會(huì)導(dǎo)致頁面元素缺失,布局紊亂,圖片和動(dòng)畫效果失效等,嚴(yán)重時(shí)可能導(dǎo)致渲染進(jìn)程崩潰,頁面呈現(xiàn)空白。如圖所示,依次排查:
(1)元素是否完整,html元素、結(jié)構(gòu)是否正確。
(2)控制臺(tái)是否有報(bào)錯(cuò)。
(3)網(wǎng)絡(luò)里面是否有資源加載時(shí)間特別長等。

2.檢查控制臺(tái),確認(rèn)是否存在因MixedContent策略或CORS策略導(dǎo)致的異常,或JS錯(cuò)誤等。可參考解決Web組件本地資源跨域問題。為了提高安全性,ArkWeb內(nèi)核禁止file協(xié)議和resource協(xié)議訪問跨域請(qǐng)求。因此,在使用Web組件加載本地離線資源的時(shí)候,Web組件會(huì)攔截file協(xié)議和resource協(xié)議的跨域訪問。Web組件無法訪問本地跨域資源時(shí),DevTools控制臺(tái)會(huì)顯示報(bào)錯(cuò)信息:
Accesstoscriptat'xxx'fromorigin'xxx'has been blockedbyCORS policy:Crossorigin requestsareonlysupportedforprotocol schemes: http, arkweb, data, chrome-extension, chrome, https, chrome-untrusted.
有如下兩種解決方法:
方法一:
開發(fā)者應(yīng)使用http或https協(xié)議替代file或resource協(xié)議,確保Web組件能夠成功訪問跨域資源。替代的URL域名應(yīng)為自定義構(gòu)造,僅限于個(gè)人或組織使用,以防止與互聯(lián)網(wǎng)上的實(shí)際域名沖突。此外,開發(fā)者需要利用Web組件的onInterceptRequest方法,對(duì)本地資源進(jìn)行攔截和相應(yīng)替換。
以下結(jié)合示例說明如何使用http或者h(yuǎn)ttps等協(xié)議解決本地資源跨域訪問失敗的問題。其中,index.html和js/script.js文件置于工程的rawfile目錄下。當(dāng)使用resource協(xié)議訪問index.html時(shí),js/script.js文件因跨域而被攔截,無法加載。在示例中,使用https://www.example.com/域名替換了原有的resource協(xié)議,同時(shí)利用onInterceptRequest接口替換資源,確保js/script.js文件可以成功加載,從而解決跨域攔截問題。
// main/ets/pages/Index.ets
import{ webview }from'@kit.ArkWeb';
@Entry
@Component
structIndex{
@Statemessage:string='Hello World';
webviewController: webview.WebviewController=newwebview.WebviewController();
// 構(gòu)造域名和本地文件的映射表
schemeMap =newMap([
["https://www.example.com/index.html","index.html"],
["https://www.example.com/js/script.js","js/script.js"],
])
// 構(gòu)造本地文件和構(gòu)造返回的格式mimeType
mimeTypeMap =newMap([
["index.html",'text/html'],
["js/script.js","text/javascript"]
])
build() {
Row() {
Column() {
// 針對(duì)本地index.html,使用http或者h(yuǎn)ttps協(xié)議代替file協(xié)議或者resource協(xié)議,并且構(gòu)造一個(gè)屬于自己的域名。
// 本例中構(gòu)造www.example.com為例。
Web({src:"https://www.example.com/index.html",controller:this.webviewController})
.javaScriptAccess(true)
.fileAccess(true)
.domStorageAccess(true)
.geolocationAccess(true)
.width("100%")
.height("100%")
.onInterceptRequest((event) =>{
if(!event) {
return;
}
// 此處匹配自己想要加載的本地離線資源,進(jìn)行資源攔截替換,繞過跨域
if(this.schemeMap.has(event.request.getRequestUrl())) {
letrawfileName:string=this.schemeMap.get(event.request.getRequestUrl())!;
letmimeType =this.mimeTypeMap.get(rawfileName);
if(typeofmimeType ==='string') {
letresponse =newWebResourceResponse();
// 構(gòu)造響應(yīng)數(shù)據(jù),如果本地文件在rawfile下,可以通過如下方式設(shè)置
response.setResponseData($rawfile(rawfileName));
response.setResponseEncoding('utf-8');
response.setResponseMimeType(mimeType);
response.setResponseCode(200);
response.setReasonMessage('OK');
response.setResponseIsReady(true);
returnresponse;
}
}
returnnull;
})
}
.width('100%')
}
.height('100%')
}
}
// main/resources/rawfile/js/script.js
constbody =document.body;
constelement =document.createElement('div');
element.textContent='success';
body.appendChild(element);
方法二:
通過setPathAllowingUniversalAccess設(shè)置一個(gè)路徑列表。當(dāng)使用file協(xié)議訪問該列表中的資源時(shí),允許進(jìn)行跨域訪問本地文件。此外,一旦設(shè)置了路徑列表,file協(xié)議將僅限于訪問列表內(nèi)的資源(此時(shí),fileAccess的行為將會(huì)被此接口行為覆蓋)。路徑列表中的路徑應(yīng)符合以下任一路徑格式:
1.應(yīng)用文件目錄通過Context.filesDir獲取,其子目錄示例如下:
/data/storage/el2/base/files/example
/data/storage/el2/base/haps/entry/files/example
2.應(yīng)用資源目錄通過Context.resourceDir獲取,其子目錄示例如下:
/data/storage/el1/bundle/entry/resource/resfile
/data/storage/el1/bundle/entry/resource/resfile/example
當(dāng)路徑列表中的任一路徑不滿足上述條件時(shí),系統(tǒng)將拋出異常碼401,并判定路徑列表設(shè)置失敗。如果路徑列表設(shè)置為空,file協(xié)議的可訪問范圍將遵循fileAccess規(guī)則,具體示例如下。
// main/ets/pages/Index.ets
import{ webview }from'@kit.ArkWeb';
import{BusinessError}from'@kit.BasicServicesKit';
@Entry
@Component
structWebComponent{
controller:WebviewController=newwebview.WebviewController();
uiContext:UIContext=this.getUIContext();
build() {
Row() {
Web({src:"",controller:this.controller})
.onControllerAttached(() =>{
try{
// 設(shè)置允許可以跨域訪問的路徑列表
this.controller.setPathAllowingUniversalAccess([
this.uiContext.getHostContext()!.resourceDir,
this.uiContext.getHostContext()!.filesDir+"/example"
])
this.controller.loadUrl("file://"+this.uiContext.getHostContext()!.resourceDir+"/index.html")
}catch(error) {
console.error(`ErrorCode:${(errorasBusinessError).code}, Message:${(errorasBusinessError).message}`);
}
})
.javaScriptAccess(true)
.fileAccess(true)
.domStorageAccess(true)
}
}
}
Demo
// main/resources/resfile/js/script.js
constbody =document.body;
constelement =document.createElement('div');
element.textContent='success';
body.appendChild(element);
3.查看onErrorReceive、onHttpErrorReceive、onSslErrorEvent、onHttpAuthRequest、onClientAuthenticationRequest等錯(cuò)誤上報(bào)接口是否有被調(diào)用。請(qǐng)根據(jù)返回的錯(cuò)誤碼,對(duì)照網(wǎng)絡(luò)協(xié)議棧錯(cuò)誤列表進(jìn)行排查。

復(fù)雜的布局與渲染模式導(dǎo)致白屏
若頁面使用了復(fù)雜布局或渲染模式,需注意其應(yīng)用場(chǎng)景和約束條件,不當(dāng)使用可能導(dǎo)致布局混亂或白屏。
Web組件提供了兩種渲染模式,能夠根據(jù)不同的容器大小進(jìn)行適配,從而滿足使用場(chǎng)景中對(duì)容器尺寸的需求,詳情見Web組件渲染模式。在使用過程中需要注意以下幾點(diǎn):
異步渲染模式下(renderMode:
RenderMode.ASYNC_RENDER),Web組件的寬高不能超過7,680px(物理像素),超過會(huì)導(dǎo)致白屏。
同步渲染模式下(renderMode:
RenderMode.SYNC_RENDER),Web組件的寬高不能超過500,000px(物理像素),超過會(huì)導(dǎo)致白屏。
Web組件提供了自適應(yīng)頁面布局的能力,詳情見 Web組件大小自適應(yīng)頁面內(nèi)容布局,使用時(shí)也需要注意以下約束條件:
配置同步渲染模式:webSetting({renderingMode: WebRenderingMode.SYNCHRONOUS})。
關(guān)閉滾動(dòng)效果:webSetting({overScrollMode: OverScrollMode.NEVER})。
此模式下不支持動(dòng)態(tài)調(diào)整組件高度,確保頁面高度固定。
避免在FIT_CONTENT模式下啟用鍵盤避讓屬性RESIZE_CONTENT,以免導(dǎo)致布局失效。
css樣式height:
子dom子dom
解決此白屏問題的參考方案如下:
子dom使用具體高度樣式撐開父元素。
子dom
父元素使用實(shí)際高度樣式。
子dom子dom
處理H5代碼兼容性
兼容性問題處理不當(dāng)也會(huì)導(dǎo)致頁面白屏。
特殊協(xié)議攔截。
若H5頁面調(diào)用tel:、mailto:等協(xié)議導(dǎo)致白屏,需通過onInterceptRequest攔截并調(diào)用系統(tǒng)撥號(hào)能力:
.onInterceptRequest((event) =>{ if(event.request.url.startsWith('tel:')) { // 調(diào)用系統(tǒng)撥號(hào)能力 call.makeCall({phoneNumber:'123456'}); return{responseCode:404};// 阻止默認(rèn)行為 } returnnull; })
監(jiān)控內(nèi)存與生命周期
內(nèi)存達(dá)到閾值會(huì)導(dǎo)致渲染進(jìn)程被終止,從而引發(fā)白屏現(xiàn)象;同樣,渲染進(jìn)程創(chuàng)建失敗或非正常銷毀也會(huì)導(dǎo)致白屏??蓮娜罩局信挪樵?。檢查Web組件是否與WebController正確綁定,或是否因過早釋放導(dǎo)致白屏。關(guān)注日志中與Render進(jìn)程相關(guān)的信息:是否存在內(nèi)存泄漏使渲染內(nèi)存不足。關(guān)鍵字“MEMORY_PRESSURE_LEVEL_CRITICAL”表明內(nèi)存已達(dá)到閾值,此情形下Web可能遭遇黑屏、花屏或閃屏等異常狀況,需排查是否存在內(nèi)存泄漏問題。Render進(jìn)程是否成功啟動(dòng)或異常退出。
下面列舉一些日志中的關(guān)鍵字和對(duì)應(yīng)的情況說明:
下面說明一下Web組件網(wǎng)絡(luò)加載過程中的關(guān)鍵日志,正常情況下一個(gè)Web組件的加載過程應(yīng)該包含這些關(guān)鍵節(jié)點(diǎn):
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
-
Web
+關(guān)注
關(guān)注
2文章
1298瀏覽量
73391 -
網(wǎng)絡(luò)
+關(guān)注
關(guān)注
14文章
8076瀏覽量
92724 -
開發(fā)者
+關(guān)注
關(guān)注
1文章
694瀏覽量
17900
原文標(biāo)題:Web白屏問題定位與解決指南
文章出處:【微信號(hào):HarmonyOS_Dev,微信公眾號(hào):HarmonyOS開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
屏幕白屏的解決方法
貼片機(jī)送料器系統(tǒng)的故障表現(xiàn)和解決方法
使用WebView組件實(shí)現(xiàn)應(yīng)用與Web頁面間的通信
web頁面與C代碼的數(shù)據(jù)交換方法是什么
HarmonyOS—使用Web組件加載頁面
BIOS錯(cuò)誤信息和解決方法
關(guān)于開關(guān)電源的電磁干擾問題研究和解決方法
采用MATLAB對(duì)SPWM進(jìn)行輔助設(shè)計(jì)與詳細(xì)分析和解決方法
GSM系統(tǒng)中干擾問題的分類、定位和解決方法
HarmonyOS Web頁面加載的原理和優(yōu)化方法

Web頁面白屏問題的排查步驟和解決方法



評(píng)論