Spaghettify 將任何靜態 HTML 網站轉換為單頁應用程序,具有 AJAX 驅動的導航和 DOM 元素的持久性功能。為此,它實現了一個 DOM 攔截器和一個中間件漏斗處理器,用於捕獲連結單擊事件,透過XHR 獲取每個請求的文檔,並在刷新瀏覽器文檔之前通過一系列中間件函數流式傳輸響應來消化響應。
這些中間件函數是可插入的 I/O 處理程序,它們遵守單一職責原則並符合完整的步驟管道,可以將其分類為onBeforeComplete
中間件鉤子(不會改變當前頁面 DOM)和onAfterComplete
中間件鉤子(會應用其變更) (因此變異)在註入後直接在目前頁面 DOM 上。
整個專案建構在 TypeScript 之上,並實作了多個填充和編碼策略,以擴展對舊版瀏覽器(例如 MSIE11)的支援。
執行此專案的最低要求(無論是在開發還是生產模式)及其開發腳本是node v12.16.0
和npm v.6.14.15
或更高版本。也許這個專案可以在舊版的node
和npm
上順利運行,但我們建議使用最新的 LTS 版本。
此專案依賴 BabelJS 和 Webpack 在開發模式下編譯程式碼,運行建置服務演示站點檔案並處理程式碼最佳化。
為了您的方便,與BabelJS
和Webpack
所有互動都已抽像在自訂 npm 腳本中。
作為產生開發環境或生產建置的第一步,請執行yarn
或npm install
來提取該專案所需的所有相依性。
請從終端機視窗執行yarn build
或npm run build
。
專案捆綁器將瀏覽整個應用程式樹,並將 JavaScript 工件建置到/dist
資料夾中,捆綁為spaghettify.js
。為了您的方便,其他有用的捆綁包也將保存在那裡。
我可以從 npm 註冊表取得 Spaghettify 嗎?在撰寫本文時,專案的首要任務是進一步提高測試覆蓋率,並透過擴展對使用者提供的中間件掛鉤的支援來擴展 API 功能。目前,Spaghettify 旨在作為瀏覽器依賴項使用,但將其作為 NPM 套件分發已在路線圖中。請稍後回來查看更新。
您可以透過方便的 API 來實例化 Spaghettify 並與之交互,該 API 提供全域切換、路由攔截器、排除和狀態持久性屬性標誌,以及最後但並非最不重要的載入進度指示器和處理程序。
成功編譯 Spaghettify 後,您可以將其導入並實例化到您的應用程式中,如下所示:
< script type =" text/javascript " src =" /dist/spaghettify.js " > </ script >
< script type =" text/javascript " >
new Spaghettify ( {
enabled : true ,
routes : [ '*.html' , 'content/*' ] ,
excludeByAttr : 'no-spa' ,
loadProgress : true ,
persistAttr : 'data-persist' ,
} ) ;
</ script >
正如您所看到的,Spaghettify 可以在實例化時取得配置物件。請注意,所有欄位都是可選的,甚至整個配置物件本身也是可選的。如果未提供,Spaghettify 將使用下表中所述的預設選項進行實例化。
Spaghettify 配置設定物件可概括如下:
場地 | 類型 | 預設 | 描述 |
---|---|---|---|
enabled | Boolean | true | 在實例化時啟用或停用 Spaghettify |
routes | String[] | ['*'] | 定義透過 Spaghettify 攔截和服務的路由模式。支援全域令牌。 |
excludeByAttr | String | undefined | 定義排除資料屬性標記(帶或不帶data- 前綴)。 Spaghettify 將繞過用此屬性修飾的鏈接 |
loadProgress | Boolean Function | false | 是否啟用內建進度列。它還可以採用一個函數處理程序,該處理程序將在載入時接收百分比進度整數。 |
persistAttr | String | undefined | 定義 UI 狀態持久性標誌資料屬性(有或沒有data- 前綴)。用此屬性裝飾的元素將在頁面導航中保留其狀態。 |
請注意,所有配置選項(以及選項有效負載本身)都是可選的,如果未明確聲明,則將採用預設值。
Spaghettify 透過在內部將事件處理程序綁定到符合條件的連結來與目前文件進行互動。為了防止記憶體洩漏,或者如果您想停止 Spaghettify 直到它再次恢復,您將需要以以下方式銷毀它:
< script type =" text/javascript " >
// First, we instantiate Spaghettify
const spa = new Spaghettify ( ) ;
// Then we dispose it after use
spa . destroy ( ) ;
</ script >
Spaghettify 將所有連結配置為要攔截的物件。內部事件管理器機制將透過針對routes
glob 令牌測試連結 href 值來評估連結是否有資格被視為 AJAX 請求。
但是,我們可以透過使用屬性值(無論是否帶有data-
前綴)來配置excludeByAttr
選項來預先繞過此步驟。
儘管如此,出於語義考慮,Spaghettify 將僅考慮配置有完整屬性的連結元素。
< script type =" text/javascript " >
new Spaghettify ( {
excludeByAttr : 'skip-me' ,
} ) ;
</ script >
<!-- Spaghettify will disregard the following link -->
< a href =" foo.html " data-skip-me > Skip this link </ a >
配置的屬性可以填入任何值或根本不填入。 Spaghettify 無論如何都會忽略這個值。
正如我們已經看到的, loadProgress
配置選項可以採用Boolean
原始值或函數處理程序。
< script type =" text/javascript " >
new Spaghettify ( {
loadProgress : true ,
} ) ;
</ script >
如果未明確配置或設定為false
,則不會顯示進度條指示器。如果設定為true
,Spaghettify 將在視窗頂部顯示一個動畫的紅色進度條指示器。進度條顯示實際下載進度。
然而,消費者可能希望實現自己的視覺解決方案來呈現下載進度資訊。 Spaghettify 透過提供一個載入進度處理程序來解決這些問題,該處理程序在其簽章中需要一個整數值參數,當透過 HXR 請求和下載頁面時,該參數將採用0
到100
之間的值。
< script type =" text/javascript " >
new Spaghettify ( {
loadProgress : function onLoad ( progress ) {
console . log ( progress ) ; // Will log values from 0 to 100
} ,
} ) ;
</ script >
Spaghettify 實作了一個實驗性 API,用於在頁面導覽中保留選定的、帶註釋的 DOM 節點的狀態。為此,您只需在persistAttr
選項中配置一個值標記,然後使用每個具有唯一值的等效data-
屬性來註解那些您希望其狀態持久化的 DOM 元素:
< script type =" text/javascript " >
new Spaghettify ( {
persistAttr : 'persist-id' ,
} ) ;
</ script >
< input type =" text " data-persist-id =" my-input " />
您可以明確地為值添加data-
前綴,也可以不添加前綴,但 Spaghettify 將要求您使用完整的資料屬性語法來註解要持久保存的 DOM 元素。
請注意:屬性值應該是唯一的。如果多個不同類型的元素配置了相同的屬性值,Spaghettify 將拋出異常。
值得強調的是,持久性將應用於完整的 DOM Node
基礎上,因此它將不僅包含元素的內部 HTML,還包含輸入控制項的本機觸控狀態。這一切都與外部 HTML 的變化無關。
您可以透過在控制台中執行yarn dev
或npm run dev
來產生開發環境。
系統將產生所有工件並從 http://localhost:3000(或您選擇的任何其他端口,如果您將--port=PORT
參數附加到dev
命令,其中PORT
是所需的端口)處於監視模式,因此應用程式將在原始程式碼發生更改時重新編譯。
沙盒網站是一個小型、超級簡單的 Web 應用程序,可作為在實時環境中調試 Spaghettify 的遊樂場和測試場所。它具有相當簡單的樣式,透過一組不同的分層頁面描述以下關鍵功能:
index.html
包含一個用於演示目的的 Spaghettify 內聯實例。所有其他文件都將此類實例實作為導入腳本。您無需在每個文件上匯入 Spaghettify,只需在條目上匯入即可。但是,出於演示目的,這允許在重新載入瀏覽器視窗後從任何文件啟動 Spaghettify。在真實的生產場景中,Spaghettify 可以(並且應該)在入口位置僅導入和實例化一次。/sandbox
根層級和子/sandbox/content
子資料夾之間,因此貢獻者可以在必要時使用指向子資料夾的連結選擇器。/sandbox/content
中的頁面具有內嵌或匯入的自訂 JavaScript,Spaghettify 將在需要時消化、重新註入和執行。ESLint 目前已在 Spaghettify 程式碼庫中啟用,並且將在建置專案時觸發 linting 審核。您可以將 IDE 配置為在引入變更時自動提供 linting 評估。此外,您可以透過在終端機控制台中執行npm run lint
或yarn lint
隨時觸發程式碼 linting。
您可以在程式碼庫中引入測試,或透過在終端控制台中執行npm test
或yarn test
來執行現有測試。程式碼覆蓋率資料被收集並儲存在/coverage/lcov-report
中格式方便的文件中。對於螢幕覆蓋率報告,請將--coverage
參數附加到test
指令中。
您還可以在 Coveralls 上在線查看全面的測試覆蓋率報告。
版權所有 2021 巴勃羅·迪爾曼
特此免費授予任何獲得本軟體及相關文件文件(「軟體」)副本的人不受限制地使用本軟體,包括但不限於使用、複製、修改、合併的權利、發布、散佈、再授權和/或銷售軟體的副本,並允許向其提供軟體的人員這樣做,但須滿足以下條件:
上述版權聲明和本授權聲明應包含在本軟體的所有副本或主要部分中。
本軟體以「現況」提供,不提供任何明示或暗示的保證,包括但不限於適銷性、特定用途的適用性和不侵權的保證。 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE軟體.