日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

js后退页面不重新加载_快应用:支持加载单独JS文件的规范思考

發布時間:2023/12/10 javascript 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js后退页面不重新加载_快应用:支持加载单独JS文件的规范思考 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
當前快應用的項目中,支持加載其它JS文件(通過:require('./foo.js')),然后通過webpack工具處理依賴,最終完成頁面JS的構建,其中頁面JS包含了引入的所有JS內容;
本文討論的主要是:webpack打包時,能夠將依賴JS不合入到頁面JS中,而是在rpk的ZIP壓縮文件中單獨存在,然后運行時,頁面在需要的時候加載該JS文件;
  • 背景描述
  • 當前如果每個頁面都引入一個共同的JS文件,如:foo.js;那么toolkit工具打包時,會將每個foo.js都打包到頁面JS代碼中;

    這樣帶來以下幾個問題,造成頁面渲染變慢:

    1) 每個頁面JS都包含了foo.js,使得JS代碼重復,導致rpk包體積增大,從而運行時下載rpk時間變長;

    2) 每個頁面JS都包含各自的foo.js,運行時JS引擎編譯代碼字符串為AST和JS對象,用時變長;

    3) 由于JS代碼存在多個地方,導致每個頁面引入的foo都是獨立的JS對象,而不是:同一個JS內存對象;

    面對上面的問題,我們提供一種新的規范來解決:編譯時支持JS單獨構建,并在運行時調用加載;

    2. 規范的方案拆解

    針對上面所述,規范實現的工作主要拆解到兩大模塊中:

    1) 編譯時:頁面中用到的公共JS文件;在構建時,生成單獨的JS文件;保持rpk中只有一份該JS文件的代碼;

    2) 運行時:提供動態加載JS文件的API:頁面中首次加載時,則從內存/磁盤中同步讀取并執行;第二次加載時,選擇復用內存中之前的JS對象或者重新執行;

    上面劃分看上去實現簡單,但圍繞一些拆解出來的子任務,其實思路很多,需要權衡利弊:

    1) 編譯時的單獨JS構建方案;

    2) 當前編譯時用的toolkit使用的是webpack4;如果使用其它工具(如:rollupjs),如何持續兼容;

    3) 動態加載JS文件時,需要考慮:模塊化,緩存,頁面/APP上下文,時間成本,向后兼容,可擴展能力等的問題;

    比如:模塊化是否要放在運行時;當頁面銷毀后如果保證頁面里的接口調用也跟著銷毀;

    接下來,圍繞各項子任務分別進行考慮;

    3. 任務1:編譯時的單獨JS構建方案

    目前市面上主流的構建方案分為兩類:語法型,配置型;其中webpack4中的splitChunkPlugin應用就屬于配置型;

    3.1 語法型

    這種指的是,快應用平臺運行時直接給開發者暴露一個 $app_evaluate$ 的函數,開發者在自己的ux文件或者js文件中,通過`const foo = $app_evaluate$('./foo.js')`方式引入JS依賴;

    當工具toolkit編譯時,檢測到這樣的函數API的JS,就不再打包到頁面JS中;

    優點:

    1) 開發者可以靈活改寫,讓某個JS既可以打包到某個頁面中,又可以獨立存在;

    2) toolkit編譯時無需開發者配置,簡單場景下方便易用;

    缺點:

    1) 這種方式對單個JS引用,很容易替換不完全,造成重復打包;

    2) 編譯工具需要自行構建依賴分析的能力,將相對路徑的引入轉換為絕對路徑;不僅無法復用webpack本身的依賴分析,而且需要增加依賴分析的邏輯和管理;實現起來增加工作量和難度;

    3) 對開發者來說,有認知成本,與現有的require, import語法相比,不夠貼切自然;

    3.2 配置型

    這種指的是,開發者通過給某個JS文件增加標識,標識為獨立打包;接著在ux與js中,如果通過require或者import引入的,那么toolkit在編譯時,根據標識,就不再打包到頁面JS的代碼中,而是單獨創建一個JS文件;

    比如:page1,page2等都引用了 foo.js文件,foo.js中聲明:`/** quickapp:standalone */` 標識為該文件不打包到頁面JS中;

    優點:

    1) 開發者只需要在JS文件中聲明一下即可,或者采用其它配置形式(如:在manifest.json或者quickapp.config.js的配置文件中聲明);

    缺點:

    1) 如果JS文件很多,可能每個希望獨立打包的JS都需要聲明;

    2) 編譯時webpack分析出依賴關系后,需要替換代碼中的`require`關鍵字為`$app_evaluate$`,避免被webpack引入;

    當然,配置型的表現形式也有很多:

    1) 與文件所在路徑放在一起,同時更新:

    在JS文件中,使用標記 `/** quickapp:standalone */` 類似語法,配置每個JS文件單獨打包;

    2) 在manifest.json中聲明:

    在manifest.json文件中,配置JS文件單獨打包,通過resource屬性去聲明單獨打包的JS文件的路徑;

    3) 在quickapp.config.js中聲明:

    `quickapp.config.js`是快應用項目下的一個配置文件,代表項目將如何構建;通過在配置文件中聲明,以確定哪些文件單獨創建;

    由于JS單獨打包的功能僅僅只是一個編譯時的工作,不應該與manifest這種運行時檢查的文件混合在一起,因此優于上一條;

    以上三種類似Java中的Annotation與XML聲明,各有優缺:

    前者直接分散,和代碼一起,不必擔心JS文件路徑變化時,引起后者配置路徑無效的問題;

    后者直觀方便,統一性強,但是與JS文件代碼分離較遠,容易發生路徑找不到;

    3.3 總結

    其實對開發者來說,他關注的是:如何以最小的認知成本,來達到rpk最小的體積與最快的頁面加載;

    所以,最佳的方式是:什么配置都不需要就能實現,對開發者無感知;

    其次是簡單的一條選擇項或一條配置就能完成;

    語法型有較大的缺陷、難度、認知,就不再考慮了;

    上面說的語法型、配置型是站在開發者的角度上說的;如果站在內部實現的角度來說,可能部分屬于語法型了,因為涉及到對`require('foo.js')`替換為`$app_evaluate$('foo.js')`的更改;

    4. 任務2:各頁面加載同一個JS文件時,其JS對象是否應該共用

    下文的`evaluate`指的是:編譯JS文件的字符串代碼 轉換為 JS對象;(通過:eval,new Function等形式)

    共用指的是:各頁面都依賴同一個JS文件時,那么這個JS文件在evaluate后對應的JS對象,是否應該被各頁面共用?

    如果共用,意味著:各頁面之間訪問的是:同一個JS對象;頁面之間對該模塊可以一起更新并取值;

    如果不共用,意味著:各頁面之間訪問的是:不同的JS對象;頁面之間的該模塊操作互不干擾影響;

    4.1 總結

    經過討論,我們認為:各頁面之間不要共用,利大于弊;

    因為快應用是一個APP的概念,頁面與頁面之間應該保持很強的獨立性,頁面之間的數據與狀態更新應該通過專有的固定通道來通信;

    否則的話,開發者容易濫用,帶來頁面之間公用模塊的互相操作影響,造成:耦合性強,狀態不穩定,通信機制泛濫,監控不到位;

    與瀏覽器中運行的SPA模式、NodeJS中模塊共用的方式相比,快應用選擇了不一樣的設計思路,最主要的目的就是:保證頁面的強獨立性;

    5. 任務3:如果JS模塊不共用,那么頁面之間隔離的方式怎么實現?

    5.1 方式1. JS文件只會evaluate一次;

    雖然JS文件僅evaluate一次,但是利用編譯時webpack的能力,它將每個JS文件封裝為模塊化代碼(`function (module, exports, __webpack_require__) { ...code... }`);

    當每個頁面重新加載該JS時,其實是填充到了各自頁面級別的module緩存`installedModules`中;

    這樣,當每次頁面引入該JS時,得到的就是,該頁面下的該模塊的JS對象;

    優點:JS的evaluate只會一次,但頁面對應的該JS模塊會重新填充一次;

    缺點:JS中模塊化代碼之外的代碼只會執行一次,但是模塊內的代碼會執行N次(N個頁面加載);

    5.2 方式2. 每次頁面加載JS文件時,都重新evaluate對應的JS代碼,得到不同的JS對象;

    優點:做到了運行時的天然隔離每個JS模塊,即使以后更換為沒有模塊化的打包工具時,仍然能夠無縫隔離;

    缺點:每次新頁面加載,都重新evaluate,引起同樣的JS代碼執行多次;

    5.3 總結

    綜上所述,我們認為:頁面中的JS模塊獨立性是一項運行時的能力;

    這種能力不應該依賴于編譯時的保證,以后即使不使用webpack編譯工具時,仍然能夠保證隔離,而且還提高了頁面的安全性;

    所以,選擇方式2,頁面每次加載都重新evaluate對應的JS代碼;

    6. 任務4. 單獨JS文件的模塊化管理

    既然要支持單獨的JS文件加載,那么就需要對所有的單獨JS文件做模塊化管理;

    需要考慮幾個方面:實現位置,遞歸依賴,路徑轉換;

    實現位置指的是:模塊化的功能在運行時實現,還是編譯時實現;

    遞歸依賴的問題,可以參考NodeJS中的模塊化實現,是在首次加載JS文件前,先定義模塊為空對象,然后執行時包裹一段模塊化代碼:`function (exports, require, module, __filename, __dirname) { ...code... }`;當發生遞歸式依賴時,傳遞之前已經定義的模塊對象;

    由此來看,模塊化無論發生在編譯時還是運行時,都需要解決遞歸依賴;

    6.1 實現位置:編譯時

    在webpack構建中,如果是僅生成一個JS文件,是通過`installedModules`內部緩存了各個模塊;如果要生成多個JS文件時,是通過`webpackJsonp`完成的,因此只需要對這塊針對快應用添加適配,提供同步讀取rpk中JS文件的能力,即可完成編譯時模塊化的能力;

    編譯時同時也需要完成源代碼中相對路徑到絕對路徑的轉換,這塊都可以使用webpack現有的實現方式;

    6.2 實現位置:運行時

    運行時模塊化增加這塊機制的好處在于:可以擺脫對webpack編譯工具的模塊管理依賴,以后如果有其它的編譯工具,那么也能夠無縫支持;

    6.3 總結

    考慮到規范發版,開發的時間成本,本次先利用成熟的webpack工具,即:編譯時能力解決,待以后再增加對應的運行時實現;

    關于模塊化中的`動態加載`模塊的能力(`const variable1 = 'test'; require(variable1);`),以及異步加載的能力,由于需求不太緊迫,因此本次規范暫不考慮;

    7. 任務5:流式加載

    當前快應用項目構建的RPK文件是一個ZIP文件,里面根據運行時加載JS文件的順序,相應的安排了每個文件在ZIP索引中的順序;比如根據順序,先后主要為:`manifest.json`,`app.js`,每個`page.js`;

    這項任務指的是:如何安排獨立JS文件的位置(哪些在頁面JS之前與之后),讓頁面首屏渲染需要的文件能夠保證內存級別的同步讀取耗時最少(避免磁盤讀引起的時間損耗);

    也就是說,這項任務的核心是:是否有辦法確定哪些JS是屬于頁面首屏渲染必須的?

    經過分析之后,目前沒有直接的辦法確定,通過讓開發者加標記FLAG也并不是一件好辦法;

    但可以換個思路考慮問題:假設所有的獨立JS放在頁面JS之前,因為它并不會被立即執行為為JS對象,所以放在頁面之前也僅僅只是增加了RPK下載與ZIP解壓縮這些獨立JS的時間;目前看,這些時間相對較小;

    所以實現思路上,可以將:單獨JS全部放在app.js與頁面JS之前,因為app.js也可能會用到獨立JS;

    8. 任務6:分包支持

    當前快應用支持分包能力,非獨立包又分為:頁面模塊包與基礎包;

    為了管理上的方便,建議:將所有的獨立JS放置在一個統一的固定目錄下,如:(`%PROJECT%/build/chunks/foo.js`);

    定義一個`chunks`的文件夾,將獨立JS在里面,當然這個目錄下可能還存在子目錄的路徑;

    8.1 非獨立包

    如果是非獨立包的話,可以將所有的獨立JS也就是對應的目錄,移動到:`基礎包`中;

    8.2 獨立包

    如果是獨立包的話,則將自己用到的獨立JS放在該模塊下;

    9. 文章總結

    經過上面幾個任務的分析,為了使得v1070版本提供的規范盡快發版,將使用編譯時的模塊化能力,運行時僅提供文件的同步讀取API,以支持:加載單獨JS文件的規范;

    針對于運行時模塊化(即:動態加載)、異步加載的其它需求,將在后面收到開發者需求后再制定快應用聯盟規范。

    總結

    以上是生活随笔為你收集整理的js后退页面不重新加载_快应用:支持加载单独JS文件的规范思考的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。