最小化 JavaScript 套件大小的實用技巧
作品:https://code-art.pictures/
為什麼要麻煩?
現在可能會令人驚訝,但在許多情況下網路流量仍然是一個問題。行動網路的數據套餐通常有限,設備電池也不是無限的,最重要的是,用戶在等待網站載入時的注意力也是有限的。這就是為什麼捆綁包大小仍然很重要。以下有七個建議供您考慮。
1. 不要轉換為 ES5
2020 年,我正在為本地社交網路維護一個促銷應用程式。這是一個典型的針對 ES5 的 React TypeScript Webpack 應用程式。當 webpack 5 發佈時,我決定升級。一切都很順利;我監控了錯誤分析和使用者回饋,沒有什麼意外的。一週後,我意外地發現我的套件中包含了箭頭函數——這是一個新的 webpack 功能。
這是一篇關於 ES5 狀態的精彩文章。重點:
- 許多函式庫已經包含 ES6 程式碼,這表示它們的捆綁包不相容於 ES5。
- 世界上大多數流行的網站都不相容 ES5 — 您的網站可能也不需要它。
- 如果您確定仍然需要 ES5 相容性,則必須在建置過程中包含這些程式庫。
2.了解並使用現代 JavaScript 語言特性
這裡有一些功能,可以讓您編寫更好、更緊湊的程式碼。
2.1.發電機
生成器是遍歷巢狀結構的有效方法:
type TreeNode<T> = { left?: TreeNode<T> value: T right?: TreeNode<T> }; function* traverse<T>(root: TreeNode<T>): Generator<T> { if (root.left) yield* traverse(root.left) yield root.value if (root.right) yield* traverse(root.right) }
2.2.私有類別字段
壓縮器確信這些欄位不能有外部用途,即使在導出的物件中也是如此,並且可以自由縮短它們的名稱。
來源
export class A { #myFancyStateObject }
捆綁包
export class A{#t}
當然,對於 TypeScript 私有欄位來說,這不起作用,因為一旦 tsc 完成其工作,它們是私有的這一知識就會消失。
2.3.現代 API
你聽過 Promise.withResolvers() 或 Map.groupBy() 嗎?在撰寫本文時,這些 API 尚未廣泛使用,但很快就會廣泛使用。現在花點時間熟悉它們,並準備好在幾年後採用它們。
提示:如何發現新的 JavaScript API
有無數的部落格和播客,但我發現最好的「新聞通訊」是 TypeScript 儲存庫中的新 .d.ts 檔案。例如,只需打開 es2024.collection.d.ts 即可享受?
3. 避免程式碼重複
你注意到重複的模式了嗎?
type TreeNode<T> = { left?: TreeNode<T> value: T right?: TreeNode<T> }; function* traverse<T>(root: TreeNode<T>): Generator<T> { if (root.left) yield* traverse(root.left) yield root.value if (root.right) yield* traverse(root.right) }
重複的程式碼不僅增加了套件的大小,而且還使理解每個部分的作用變得更加困難。這通常會導致開發人員編寫新程式碼,而不是識別和重複使用現有的實用函數,從而進一步使捆綁包變得臃腫。
關於這個主題已經有很多優秀的材料,所以我不再重述它,而是推薦經典:Martin Fowler 的重構。它不僅涵蓋了上面的簡單範例,還涵蓋了耦合層次結構和重複設計等複雜情況。
現在,讓我們改進我們的小例子。看來clamp經常用於將參數限制在數組索引範圍內,所以我們可以創建一個快捷方式:
export class A { #myFancyStateObject }
此變更明確表明 n 可能是整數,目前尚未檢查。它還突出顯示了一個未處理的邊緣情況:空數組。透過進行這個小的重複資料刪除,我們還發現了兩個潛在的錯誤?
4.避免過度設計
我不記得這句話的確切來源,但我認為它是正確的:
過度設計正在解決你沒有的問題。
在 Web 開發領域,我觀察到兩種主要類型的過度設計。
4.1.過度概括
考慮這段程式碼。內邊距是 4px 的倍數,背景顏色是藍色陰影。這可能不是巧合,如果是這樣,則可能表示可能存在重複。但是我們真的有足夠的資訊來提取通用 Button 組件,還是我們過度設計了?
CSS
export class A{#t}
JSX
const clamp = (min, val, max) => Math.max(min, Math.min(val, max)) const x = clamp(0, v1, a.length - 1) const y = clamp(0, v2, b.length - 1) const z = clamp(0, v3, c.length - 1)
這個建議確實與「避免重複」有些衝突。過度重複程式碼刪除可能會導致過度設計。那麼,你在哪裡劃清界線呢?就我個人而言,我使用神奇的數字“3”:一旦我看到三個具有相似模式的地方,可能是時候提取通用組件了。
對於我們的藍色按鈕,我相信最好的解決方案是使用 CSS 變量,至少用於填充,而不是創建一個新組件。
4.2.使用不正確的框架
是的,我說的是我們喜歡的東西——Next.js、React、Vue 等等。如果您的應用程式在 DOM 元素層級不涉及大量互動性,或者不是動態的,或者非常簡單,請考慮其他選項:
- 靜態網站產生器 - 您可以從一些精選清單開始。
- 注意:其中一些在幕後使用 React 或其他框架。如果您的目標是捆綁最小化,請嘗試不同的方法。
- 內容管理系統,例如 WordPress。
- Vanilla — 在兩種情況下特別有用:
- 該應用程式非常簡單。
- 該應用程式不會操作太多 DOM,而是在畫布上繪製一些東西。我有一個與此完全相同的項目。
5. 避免過時的 TypeScript 功能
TypeScript 目前的目標主要是對 JavaScript 進行類型檢查,但情況並非總是如此。早在 ES6 出現之前,人們就曾多次嘗試創建“更好的 JavaScript”,TypeScript 也不例外。有些功能可以追溯到早期。
5.1.枚舉
它們不僅難以正確使用,還會轉換成相當冗長的結構:
TypeScript
type TreeNode<T> = { left?: TreeNode<T> value: T right?: TreeNode<T> }; function* traverse<T>(root: TreeNode<T>): Generator<T> { if (root.left) yield* traverse(root.left) yield root.value if (root.right) yield* traverse(root.right) }
JavaScript
export class A { #myFancyStateObject }
官方 TypeScript 手冊建議使用簡單物件而不是枚舉。您也可以考慮聯合類型。
5.2.命名空間
命名空間是 ESM 之前的模組解決方案。它們不僅增加了套件的大小,而且由於命名空間是全局的,因此在大型專案中很難避免命名衝突。
TypeScript
export class A{#t}
JavaScript
const clamp = (min, val, max) => Math.max(min, Math.min(val, max)) const x = clamp(0, v1, a.length - 1) const y = clamp(0, v2, b.length - 1) const z = clamp(0, v3, c.length - 1)
使用 ES 模組取代命名空間。
注意:但是,對於為全域庫編寫類型定義,命名空間仍然有用。
6. 不要忽視小的優化
這些小技巧中的每一個都可以為您節省捆綁中的幾個到幾十個位元組。如果堅持使用,可以帶來明顯的效果。
6.1.使用真/假屬性
例如,空字串是假的。要檢查它是否已定義且非空,您可以簡單地編寫:
const clampToRange = (n, {length}) => clamp(0, n, length - 1) const x = clampToRange(v1, a) // ...
6.2.有時允許非嚴格比較
我相信使用 == 強制 null 為 undefined,反之亦然,是完全合理的。
.btn-a { background-color: skyblue; padding: 4px; } .btn-b { background-color: deepskyblue; padding: 8px; }
6.3.使用空合併、邏輯或和預設參數來取代預設值
<button className='btn-a' onClick={handleClick}> Show </button> // ... <button className='btn-b' onClick={handleSubmit}> Submit </button>
6.4.使用單行箭頭函數
而不是這個:
enum A { x, y }
寫下:
var A; (function (A) { A[A["x"] = 0] = "x"; A[A["y"] = 1] = "y"; })(A || (A = {}));
6.5.不要對非常簡單的物件使用類
而不是這個:
namespace A { export let x = 1 }
寫下:
var A; (function (A) { A.x = 1; })(A || (A = {}));
您也可以凍結物件以保護其屬性免遭變更。
7.定期檢查捆綁包
對於每個捆綁器,都有可視化其內容的工具,例如用於 webpack 的 webpack-bundle-analyzer 和用於 Vite 的 vite-bundle-analyzer。這些工具可以幫助您識別捆綁包的常見問題:
- 庫佔用了不成比例的空間 — 也許是時候遷移或升級了?
- 項目的不同部分使用了兩個相似的庫 - 您可以合併並僅使用一個嗎?
- 您的捆綁包中存在一個大文件,但只能由 0.5% 用戶訪問的頁面訪問(例如許可證文本)——也許您可以使用動態 import() 對捆綁包進行分區?
除了這些工具之外,偶爾手動閱讀捆綁包以發現違規行為也是一個好主意。例如,由於 TypeScript 配置錯誤,您可能會在 ES6 捆綁包中找到 ES5 幫助程序,或在 ESM 專案中找到 CJS 幫助程序。這些問題可能無法被自動化工具發現,但仍然會增加載入時間,並可能會損失您最寶貴的資產 - 用戶的注意力。
感謝您的閱讀。快樂編碼!
以上是最小化 JavaScript 套件大小的實用技巧的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

zustand異步操作中的數據更新問題在使用zustand狀態管理庫時,經常會遇到異步操作導致數據更新不及時的問題。 �...
