webpack scope hositing 和tree shaking

Scope Hoisting(作用域提升)Tree Shaking(搖樹優化) 是現代前端構建中至關重要的概念。它們是構建工具(如 Webpack、Rollup、Vite)用來優化最終打包產物的核心技術。

核心概念快速理解

  • Tree Shaking“消除死代碼”。像一個園丁搖動果樹,把已經枯萎、不再結果實的樹枝(未使用的代碼)搖掉。它是一個靜態分析過程,在打包時移除 JavaScript 上下文中未引用的代碼(export 但未被 import 的部分)。
  • Scope Hoisting“優化模塊結構”。它盡可能地將分散的模塊合并到一個函數作用域內,然后重命名變量以防止沖突。它的主要目的是減少打包后的函數聲明數量、減小文件體積、提升運行時執行效率

1. Tree Shaking(搖樹優化)

是什么?

Tree Shaking 是一個術語,通常用于描述在 JavaScript 打包過程中移除未被使用的代碼(俗稱“死代碼”,dead code)的行為。它依賴于 ES2015 模塊語法(importexport)的靜態結構特性。

為什么需要?

在編寫項目時,我們經常會引入整個庫(例如 import _ from 'lodash'),但可能只使用了其中一兩個函數。如果沒有 Tree Shaking,整個 lodash 庫都會被完整地打包到最終產物中,導致體積巨大。

工作原理:
  1. 標記:構建工具(如 Webpack)從入口文件開始,分析所有 importexport 語句,構建一個依賴圖。
  2. 分析:工具會標記出哪些 export 的代碼被其他模塊 import 并使用了。
  3. 清除:在最終生成打包文件時,所有未被標記為“已使用”的 export 代碼將被安全地剔除。
生效的前提條件:
  1. 必須使用 ES Module(ESM)語法:即使用 importexportCommonJS(requiremodule.exports)無法被可靠地 Tree Shaken,因為它的依賴關系是動態的,無法在構建時靜態分析。
    • 有效import { debounce } from 'lodash-es';
    • 無效const debounce = require('lodash/debounce'); (雖然這樣寫更好,但整個 require 語法樹本身不支持搖樹)
  2. 編譯器不能將 ESM 轉換為其他模塊規范:例如,Babel 默認配置可能會將 import/export 轉譯成 CommonJS。你需要確保 Babel 保留 ESM 語法(通常通過設置 @babel/preset-envmodules: false)。
  3. package.json 的 sideEffects 屬性
    • 有些模塊本身沒有導出任何內容,而是會執行一些操作(如 polyfills、CSS 文件)。這些被稱為“有副作用”的模塊。
    • 如果你在 package.json 中設置 "sideEffects": false,是在告訴打包工具:“我這個包里的所有文件都是純的,沒有副作用,你可以安全地對它們進行 Tree Shaking”。
    • 如果你的包有副作用文件,需要列出它們:"sideEffects": ["./src/some-side-effectful-file.js", "*.css"],以防止它們被意外移除。
示例:

假設我們有一個 math.js 庫:

// math.js
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b; // 假設這個函數未被使用
export const pi = 3.14159; // 假設這個常量未被使用

在我們的主文件中:

// main.js
import { add } from './math.js';
console.log(add(1, 2));

經過 Tree Shaking 后,打包產物將不包含 multiplypi 的代碼,最終體積更小。


2. Scope Hoisting(作用域提升)

是什么?

在 Webpack 等工具中,每個模塊通常會被包裹在一個函數中(Webpack 稱之為“模塊包裝函數”)。這是為了實現模塊化,但會帶來一些性能開銷。Scope Hoisting 會盡可能地將所有模塊合并到一個作用域中,而不是將它們放在單獨的模塊函數里。

為什么需要?
  1. 減少體積:消除大量模塊包裝函數的代碼本身就能減小文件體積。
  2. 提升運行速度
    • 減少函數聲明:JavaScript 引擎執行代碼時,調用一個函數的開銷比執行內聯代碼要大。
    • 改善壓縮效果:變量被合并到一個作用域后,壓縮工具(如 Terser)可以更好地重命名變量,實現更高效的壓縮。
工作原理:

構建工具會分析模塊之間的依賴關系,并將它們盡可能地“內聯”到同一個作用域中。它會智能地重命名變量以避免沖突。

示例(簡化概念):

沒有 Scope Hoisting 的打包產物可能看起來像:

// 很多這樣的模塊包裝函數
(function(module, __webpack_exports__, __webpack_require__) {"use strict";__webpack_require__.r(__webpack_exports__);/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);console.log(Object(_math__WEBPACK_IMPORTED_MODULE_0__["add"])(1, 2));
}),
(function(module, __webpack_exports__, __webpack_require__) {"use strict";__webpack_require__.r(__webpack_exports__);/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "add", function() { return add; });const add = (a, b) => a + b;const multiply = (a, b) => a * b;
})

啟用 Scope Hoisting 后,產物可能被優化為:

// 模塊被合并到一個作用域,變量被重命名
const $add$ = (a, b) => a + b;
// ... multiply 可能被 Tree Shaken 掉 ...
console.log($add$(1, 2));

可以看到,后者沒有了函數包裝,代碼更緊湊,執行效率更高。


兩者的關系與區別

特性Tree ShakingScope Hoisting
主要目標移除未使用的代碼,減小體積優化模塊結構,減小體積并提升運行性能
工作階段主要在代碼壓縮(Minification)階段主要在模塊連接(Module Concatenation)階段
關系它們是互補的優化技術。Scope Hoisting 將模塊合并到一個作用域,這為 Tree Shaking 提供了更好的基礎來識別未使用的變量和函數。

協同工作流程:

  1. Scope Hoisting 首先將許多模塊內聯到同一個作用域中。
  2. 然后,Tree Shaking 和代碼壓縮工具(如 Terser)在這個扁平化的作用域中進行靜態分析,能更輕松地發現和移除那些未被引用的變量和函數。

如何在 Webpack 中啟用?

  • Tree Shaking
    • production 模式下(mode: 'production')是默認啟用的。Webpack 會自動使用 TerserPlugin 進行壓縮和 Tree Shaking。
    • 確保你的代碼和依賴使用 ES Module 語法。
  • Scope Hoisting
    • production 模式下也是默認啟用的。Webpack 內部使用 ModuleConcatenationPlugin 來實現這一功能。
    • 在某些情況下(如動態導入),Webpack 無法進行作用域提升,它會安全地回退到傳統的模塊包裝函數。

總結

優化解決了什么問題?帶來的好處
Tree Shaking引入了整個庫但只使用一小部分減小打包體積
Scope Hoisting模塊包裝函數帶來的體積和性能開銷減小打包體積提升運行時性能

它們是現代前端構建流程的基石,通過協同工作,共同打造出體積更小、性能更優的應用程序 bundle。要最大化利用它們,關鍵在于編寫“可搖樹”的代碼(使用 ESM 語法)和正確配置庫的 sideEffects 屬性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98325.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98325.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98325.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

手寫React狀態hook

在日常開發中,我們經常用到 React 的狀態管理 Hook:useState 和 useReducer。 但你有沒有想過:這些 Hook 內部是怎么實現的?為什么調用 setState 之后組件會重新渲染? 今天我們就來從零手寫 useState 和 useReducer&am…

力扣hot100:相交鏈表與反轉鏈表詳細思路講解(160,206)

問題描述核心思路:雙指針交替遍歷算法思想: 使用兩個指針 pa 和 pb 分別從鏈表A和鏈表B的頭節點出發,同步向后遍歷。當任一指針走到鏈表末尾時,將其重定位到另一鏈表的頭節點繼續遍歷。若兩鏈表相交,pa 和 pb 最終會在…

跨平臺游戲引擎 Axmol-2.8.1 發布

所有使用 axmol-2.8.0 的開發者都應更新至此版本 Axmol 2.8.1 版本是一個以錯誤修復和功能改進為主的次要 LTS 長期支持版本,發布時間: 2025 年 9 月 5 日 🙏感謝所有對 axmol 項目的貢獻者,包括財務贊助者:scorewarrior、peter…

通過PXE的方式實現Ubuntu 24.04 自動安裝

PXE自動化安裝Ubuntu 24.04的配置文件之前都是通過PXE來自動化安裝Redhat系列的,例如:Rocky9、Rocky10、CentOS7、銀河麒麟 Kylin-V10、Kylin-V11、OpenEuler 24.03等。現在安裝Ubuntu系列的跟紅帽的不太一樣,所以在這里介紹下。創建三個文件…

AOSP Framework開發的一些超方便的快捷命令

在系統源碼中發現的一些命令和快捷方式。我們在編譯源碼之前執行的source build/envsetup.sh,通過cat build/envsetup.sh發現如下命令 - lunch: lunch <product_name>-<build_variant>Selects <product_name> as the product to build, and <build_…

【Protues仿真】基于AT89C52單片機的數碼管驅動事例

目錄 0案例視頻效果展示 1 AT89C52單片機驅動單個數碼管 1.1 數碼管基礎知識 1.1.1外觀與引腳 1.1.2 共陰(CC) vs 共陽(CA) 1.1.3段碼表(以數字1為例) 1.1.4驅動方式A. 直連IO(最簡單,占用IO多)一個段一根線,共陰或共陽公共端固定接GND/VCC。適合單個數碼管、…

01-Redis 發展簡史與核心定位解析:從誕生到三大產品矩陣

目錄引言一、Redis 的起源與發展&#xff1a;從定制工具到開源生態二、Redis 的核心定位&#xff1a;不止是緩存的多面手三、Redis 三大產品矩陣&#xff1a;按需選擇的完整解決方案3.1 Redis Open Source&#xff08;社區版&#xff09;&#xff1a;入門與輕量場景首選3.2 Red…

記錄jilu~

centos1、安裝最小版Linux 安裝必要工具yum -install -y epel-releaseyum -install -y net-toolsyum -install -y vim2、修改hostname hostnamectl net-hostname newhostname3、網絡配置文件&#xff0c;網關 &#xff0c; 使用ip &#xff0c;dns。。/etc/sysconfig/network-s…

【Linux基礎】fdisk命令詳解:從入門到精通的磁盤分區管理完全指南

目錄 前言 1 fdisk命令概述 1.1 什么是fdisk 1.2 fdisk的應用場景 1.3 fdisk與其他分區工具的比較 2 fdisk命令的安裝與基本語法 2.1 在不同Linux發行版中安裝fdisk 2.2 fdisk的基本語法 3 fdisk命令參數詳解 3.1 主要參數說明 3.2 交互式命令 4 fdisk操作流程詳解…

Flowable 工作流引擎

1、核心類 Flowable 引擎通過 ProcessEngine 作為總入口點&#xff0c;提供了多個核心服務接口&#xff0c;每個服務都負責特定的功能領域&#xff1a;服務名稱 (Service Name)主要功能 (Main Functionality)關鍵操作 (Key Operations)RepositoryService管理流程定義和部署&…

(RDFS)隨機深度特征選擇方法解釋:簡而言之,RDFS主要針對的是惡意的服務器,它建立在客戶端是誠實的前提下。

1. 隨機深度特征選擇是怎么實現的&#xff1f;隨機深度特征選擇 是一種在分布式機器學習&#xff08;特別是聯邦學習&#xff09;中用于保護客戶端數據隱私的技術。它的核心思想是&#xff1a;在每一輪訓練中&#xff0c;每個客戶端隨機選擇模型的一個子集&#xff08;即“深度…

C++20格式化字符串:std::format的使用與實踐

在C編程中&#xff0c;字符串格式化是一項常見的任務。在C20引入std::format之前&#xff0c;開發者通常依賴于一些傳統的解決方案&#xff0c;如printf系列函數、sstream&#xff0c;或者第三方庫如boost.format。然而&#xff0c;這些方法在代碼可讀性、類型安全性和靈活性方…

【漏洞復現】CVE-2025-8088|WinRAR 路徑穿越漏洞:從原理到藍屏攻擊全流程

【漏洞復現】CVE-2025-8088&#xff5c;WinRAR 路徑穿越漏洞&#xff1a;從原理到藍屏攻擊全流程 前言 WinRAR 作為 Windows 平臺最常用的壓縮管理工具之一&#xff0c;幾乎是每臺電腦的 “標配軟件”。但在 2025 年 8 月&#xff0c;一款影響范圍覆蓋 WinRAR 0 至 7.12 全版本…

uniapp中使用echarts并且支持pc端的拖動、拖拽和其他交互事件

npm install echarts -D ? // "echarts": "^5.3.2", [推薦版本] // "zrender": "^5.3.2" [如果報錯的話就安裝這個]<template><view class"container"><view id"myChart" class"chart"…

Qt中QProxyStyledrawControl函數4個參數的意義

Qt中QProxyStyle::drawControl函數4個參數的意義 我們來詳細解釋一下 Qt 中 QProxyStyle::drawControl 函數的四個參數。 這個函數是 Qt 樣式系統中的一個核心方法&#xff0c;用于繪制標準 UI 元素&#xff08;如按鈕、復選框、菜單欄等&#xff09;。當你繼承 QProxyStyle 并…

idf-esp32 PWM呼吸燈(LEDC頭文件)

相關宏和變量#define LED_PIN GPIO_NUM_3 #define LEDC_CHANNEL LEDC_CHANNEL_0 #define LEDC_TIMER LEDC_TIMER_0 #define LEDC_MODE LEDC_LOW_SPEED_MODE #define LEDC_DUTY_RES LEDC_TIMER_13_BIT // 2^13 8192級亮度 #define LEDC_FREQUENCY 50…

PLC_博圖系列?基本指令”S_ODTS:分配保持型接通延時定時器參數并啟動“

PLC_博圖系列?基本指令”S_ODTS&#xff1a;分配保持型接通延時定時器參數并啟動“ 文章目錄PLC_博圖系列?基本指令”S_ODTS&#xff1a;分配保持型接通延時定時器參數并啟動“背景介紹S_ODTS&#xff1a; 分配保持型接通延時定時器參數并啟動說明參數脈沖時序圖示例關鍵字&a…

OneCode 可視化揭秘系列(三):AI MCP驅動的智能工作流邏輯編排

OneCode 可視化揭秘系列&#xff08;三&#xff09;&#xff1a;AI MCP驅動的智能工作流邏輯編排 引言 在前兩篇系列博文中&#xff0c;我們詳細探討了OneCode可視化動作的基礎配置與界面設計&#xff0c;以及組件交互與數據流管理。在本篇文章中&#xff0c;我們將深入剖析邏輯…

TypeORM、Sequelize、Hibernate 的優缺點對比:新手常見 SQL 與 ORM 踩坑總結

1. ORM 與關系型數據庫&#xff08;MySQL、PostgreSQL&#xff09; 的使用 SQL 語句編寫&#xff08;JOIN、GROUP BY、索引使用、事務控制&#xff09;與 ORM 映射&#xff08;如 Sequelize、TypeORM、Hibernate&#xff09;之間的差異會讓新手非常糾結&#xff1b;尤其是理解…

JavaScript 創建型設計模式詳解

1. 單例模式1.1. 使用場景在前端開發中&#xff0c;全局狀態管理、配置信息、數據庫連接等往往需要在應用中只存在一個實例&#xff0c;避免多次實例化帶來的數據不一致性。例如&#xff0c;在一個前端應用中&#xff0c;全局的 loading 狀態通常需要一個單例模式來確保其唯一性…