摘要:?jiǎn)栴}背景最近做的一個(gè)項(xiàng)目需要引入一個(gè)外部的第三方腳本。什么情況可以用我以上思路引入的第三方腳本較大,加載所需時(shí)間較長(zhǎng)頁(yè)面按需加載,整個(gè)項(xiàng)目只有其中某幾個(gè)頁(yè)面需要用到引入的第三方腳本第三方腳本沒(méi)加載完就渲染頁(yè)面導(dǎo)致的頁(yè)面報(bào)錯(cuò)
問(wèn)題背景
最近做的一個(gè)項(xiàng)目需要引入一個(gè)外部的第三方j(luò)s腳本。由于這是一個(gè)關(guān)于渲染3D建筑的腳本,所以體積比較大,大概有2M,加載完成也得要個(gè)好幾秒,網(wǎng)速慢的時(shí)候十幾秒都有可能。
之前也遇到腳本加載慢的問(wèn)題,但是沒(méi)這么慢,所以這次就特別寫個(gè)文章記錄一下我的解決過(guò)程。
下圖是通過(guò)第三方腳本渲染出來(lái)的3D建筑頁(yè)面
下圖是首頁(yè),不需要用到第三方腳本
遇到的問(wèn)題和需求引入外部腳本太大,加載時(shí)間太長(zhǎng)
首頁(yè)用不到外部腳本,需要先渲染出來(lái)
用到外部腳本的頁(yè)面,要是腳本還沒(méi)加載好就點(diǎn)進(jìn)去會(huì)報(bào)錯(cuò)
解決問(wèn)題的過(guò)程我一開(kāi)始通過(guò)
`
這樣頁(yè)面是可以正常加載的,但是頁(yè)面出來(lái)的很慢,一開(kāi)始會(huì)白屏一段時(shí)間等待這個(gè)js腳本加載完成。雖然腳本體積大是事實(shí),但這用戶體驗(yàn)肯定是可以優(yōu)化的。
后來(lái)我又把這個(gè)腳本放到了頁(yè)面底部,也就是
標(biāo)簽下面。這樣可以先讓頁(yè)面渲染出來(lái),再慢慢加載這個(gè)龐大的腳本,于是首頁(yè)是出來(lái)的很快,但是從首頁(yè)跳轉(zhuǎn)到需要用到這個(gè)腳本的頁(yè)面就會(huì)報(bào)錯(cuò),如下
這個(gè)錯(cuò)誤原因是這個(gè)頁(yè)面需要用到window.DDEarth這個(gè)對(duì)象,但是由于此時(shí)這個(gè)腳本還沒(méi)有加載完成,所以window下并沒(méi)有這個(gè)對(duì)象,所以就報(bào)錯(cuò)了。
于是我又想到等腳本加載完成再執(zhí)行相關(guān)方法,這時(shí)就需要用到onload這個(gè)方法了,onload這個(gè)方法在腳本加載完成的時(shí)候會(huì)執(zhí)行。我引入腳本的時(shí)候給它加了個(gè)id,方便以后通過(guò)dom找到,代碼如下:
// 入口文件 // PageTwo.js componentDidMount() { const scriptEle = document.getElementById("ddEarthScript"); // 找到腳本節(jié)點(diǎn) if (scriptEle) { scriptEle.onload = () => { // 腳本加載完成執(zhí)行加載地圖的操作 this.loadEarthMap(); }; } }
有了以上代碼我跳轉(zhuǎn)到PageTwo這個(gè)頁(yè)面的時(shí)候,會(huì)等到DDEarth.js這個(gè)腳本加載完成,再執(zhí)行加載建筑地圖的操作,這樣就不會(huì)報(bào)錯(cuò)了。
但是這又有一個(gè)問(wèn)題,就是如果我跳轉(zhuǎn)到PageTwo的之前,DDEarth.js已經(jīng)加載完成了,onload這個(gè)事件在PageTwo這個(gè)頁(yè)面中就不生效了,loadEarthMap這個(gè)方法自然也就不會(huì)執(zhí)行了。
這個(gè)時(shí)候需要加一個(gè)判斷,完整代碼如下:
// PageTwo.js componentDidMount() { if (window.DDEarth) { // 如果跳轉(zhuǎn)到此頁(yè)面之前,腳本已加載完成 this.loadEarthMap(); } else { const scriptEle = document.getElementById("ddEarthScript"); if (scriptEle) { scriptEle.onload = () => { this.loadEarthMap(); }; } } }總結(jié)一下我以上解決問(wèn)題的步驟
在入口文件的底部引入第三方腳本,并給它加個(gè)id。當(dāng)然也可以放在
里,但是需要額外加上html5新增的 async 這個(gè)屬性,這樣腳本才能異步加載。
在需要用到這個(gè)腳本的頁(yè)面,先判斷腳本有沒(méi)有加載完成(我這里是直接判斷window.DDEarth對(duì)象是否為空)。如果已經(jīng)加載完成,就直接執(zhí)行相關(guān)操作;如果沒(méi)有,先通過(guò)document.getElementById找到那個(gè)腳本,然后監(jiān)聽(tīng)腳本的onload事件,再做相關(guān)操作。
什么情況可以用我以上思路?引入的第三方腳本較大,加載所需時(shí)間較長(zhǎng)
頁(yè)面按需加載,整個(gè)項(xiàng)目只有其中某幾個(gè)頁(yè)面需要用到引入的第三方腳本
第三方腳本沒(méi)加載完就渲染頁(yè)面導(dǎo)致的頁(yè)面報(bào)錯(cuò)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/99862.html
摘要:表示要執(zhí)行外部文件的路徑或鏈接。由于規(guī)范要求腳本按照他們出現(xiàn)的先后順序執(zhí)行,因此第一個(gè)延遲腳本會(huì)優(yōu)先于第二個(gè)執(zhí)行,二這兩個(gè)腳本會(huì)優(yōu)先于事件執(zhí)行。無(wú)論使用任何方式,只要不存在和屬性,瀏覽器都會(huì)按照元素在頁(yè)面中出現(xiàn)的先后順序依次解析。 元素屬性 屬性 定義 async 【可選】??梢援惒郊虞d,表示可以立即下載此腳本,但不影響頁(yè)面其他操作。只對(duì)外部腳本有效。 charset ...
摘要:雖然如此,但是網(wǎng)站前端性能優(yōu)化的思路基本沒(méi)變。為什么前端性能如此重要數(shù)據(jù)顯示只有的最終用戶響應(yīng)時(shí)間花在了下載文檔上。前端性能優(yōu)化一味奉行最佳實(shí)踐有時(shí)候反而過(guò)而不及,所以針對(duì)項(xiàng)目的實(shí)際情況來(lái)優(yōu)化才是明智的選擇。 前端近幾年變化很大,各種工具,庫(kù),框架并發(fā)。雖然如此,但是網(wǎng)站前端性能優(yōu)化的思路基本沒(méi)變。為什么前端性能如此重要?數(shù)據(jù)顯示: 只有 10%~20% 的最終用戶響應(yīng)時(shí)間花在了下載...
摘要:例如指定一些依賴到模塊中實(shí)現(xiàn)規(guī)范的模塊化,感興趣的可以查看的文檔。 CommonJS 定義了 module、exports 和 require 模塊規(guī)范,Node.js 為了實(shí)現(xiàn)這個(gè)簡(jiǎn)單的標(biāo)準(zhǔn),從底層 C/C++ 內(nèi)建模塊到 JavaScript 核心模塊,從路徑分析、文件定位到編譯執(zhí)行,經(jīng)歷了一系列復(fù)雜的過(guò)程。簡(jiǎn)單的了解 Node 模塊的原理,有利于我們重新認(rèn)識(shí)基于 Node 搭建的...
摘要:盡管腳本的下載過(guò)程中不會(huì)相互影響,但頁(yè)面仍然要等到所有代碼下載并完成執(zhí)行才能繼續(xù)。 defer和asnyc(只對(duì)外部文件有效) defer 在頁(yè)面完成解析時(shí)執(zhí)行代碼,這個(gè)屬性表明腳本在執(zhí)行時(shí)不會(huì)影響頁(yè)面的構(gòu)造,在元素中設(shè)置這個(gè)屬性相當(dāng)于告訴瀏覽器立即下載但延遲執(zhí)行 async 相對(duì)于頁(yè)面其他部分異步執(zhí)行腳本,一般的script標(biāo)簽都是會(huì)阻塞頁(yè)面執(zhí)行的,沒(méi)有加上async屬性的標(biāo)簽...
閱讀 3773·2023-04-26 00:56
閱讀 2777·2021-09-30 10:01
閱讀 1051·2021-09-22 15:30
閱讀 4000·2021-09-07 10:21
閱讀 1663·2021-09-02 15:40
閱讀 2861·2021-08-30 09:47
閱讀 1332·2021-08-16 10:57
閱讀 1929·2019-08-30 14:01