Tree Shaking — tətbiqin qurulma mərhələsində istifadə olunmayan kodun silinmə mexanizmi (dead code elimination). Tree Shaking ES-modullarının statik strukturunu təhlil edir və heç bir yerdə idxal edilməyən ixrac edilmiş funksiyaları, sinifləri və dəyişənləri xaric edir. Webpack Documentation məlumatlarına görə, Tree Shaking-in düzgün konfiqurasiyası tətbiqin funksionallığını dəyişmədən bunt ölçüsünü 30–60% azalda bilər.
Əsas məqamlar
Tree Shaking (ağacın silkələnməsi) — tətbiqdə istifadə olunmayan modul və funksiyaların yekun buntdan xaric edildiyi kod optimallaşdırma texnikası. Termin 2015-ci ildə Rollup komandası tərəfindən təqdim edilmişdir və prosesi metaforik olaraq təsvir edir: asılılıq ağacı silkələnir, istifadə olunmayan budaqlar düşür. Əl ilə optimallaşdırmadan fərqli olaraq, Tree Shaking qurulma mərhələsində avtomatik olaraq həyata keçirilir.
Tree Shaking yalnız ES-modulları (ECMAScript Modules) ilə işləyir, burada asılılıqlar import və export vasitəsilə statik olaraq müəyyən edilir. CommonJS (require/module.exports) Tree Shaking-i dəstəkləmir, çünki require dinamik olaraq işləyir — qurucu hansı funksiyaların həqiqətən istifadə edildiyini əvvəlcədən müəyyən edə bilmir. Müasir kitabxanalar (Lodash, Moment.js, RxJS) Tree Shaking dəstəyi üçün ES versiyalarını buraxır.
Rollup — 2015-ci ildə Tree Shaking-i tətbiq edən ilk qurucu. Webpack-dən fərqli olaraq, Rollup əvvəldən ES-modulları üçün nəzərdə tutulmuşdur və ölü kodun daha aqressiv silinməsini həyata keçirir. Rollup təkcə ayrı-ayrı ixracları deyil, bütün modulları təhlil edir: əgər modulun yan təsirləri yoxdursa və heç bir ixrac istifadə edilmirsə, Rollup bütün modulu buntdan xaric edir.
Rollup xüsusilə hər kilobaytın əhəmiyyətli olduğu kitabxana və SDK-lar üçün effektivdir. Vue.js çərçivəsi production versiyasını qurmaq üçün Rollup-dan istifadə edir. React 2020-ci ildə Rollup-a keçmişdir. Tətbiqlər üçün daha çox Webpack istifadə olunur (zəngin plagin ekosisteminə görə — Hot Module Replacement, code splitting, CSS modules), lakin kitabxanaların qurulmasında maksimum Tree Shaking üçün Rollup sənaye standartı olaraq qalır.
Qənaət Tree Shaking-dən layihənin arxitekturasından güclü şəkildə asılıdır. React tətbiqində Ant Design kitabxanası ilə Tree Shaking UI komponentlərinin kodunun 70%-ə qədərini silə bilər. Bütün idxalların spesifik və dəqiq olduğu layihədə qənaət 5–15% təşkil edəcək. Webpack tədqiqatlarına görə orta qənaət bunt ölçüsünün 30–40%-ni təşkil edir.
| Ölü kodun növü | Nümunə | Tree Shaking tərəfindən aşkarlanma |
|---|---|---|
| İstifadə olunmayan ixrac | export function unusedHelper() | Bəli |
| İstifadə olunmayan idxal | import { unused } from "lib" | Bəli |
| Şərtin ölü budağı | if (false) { ... } | Xeyr (minifikator tərəfindən silinir) |
| DCE-dən sonra çağırılmayan funksiya | function a(){} a() a çağırılmadıqda | Qismən |
Tree Shaking mexanizmi qurucunun layihədəki bütün import/export-dan qurduğu asılılıq qrafikinə (dependency graph) əsaslanır. Birinci mərhələdə qurucu giriş nöqtəsindən (entry point) bütün faylları gəzərək modul ağacını toplayır. İkinci mərhələdə hər moduldan hansı ixracların digər modullarda həqiqətən idxal edildiyi təhlil edilir.
Hər modul üçün Webpack və ya Rollup ixracları istifadə olunan və ya istifadə olunmayan kimi qeyd edir. İstifadə olunmayan ixraclar buntdan xaric edilir. Lakin modulun özü buntda qalır, əgər onun ən azı bir ixracı istifadə olunursa. Modulu tamamilə xaric etmək yalnız sideEffects flagı ilə və ya modulda heç bir yan təsir yoxdursa mümkündür.
// utils.js — funksiyaları olan modul
export function formatDate(date) {
return date.toISOString().slice(0, 10);
}
export function formatCurrency(amount) {
return "$" + amount.toFixed(2);
}
export function slugify(text) {
return text.toLowerCase().replace(/\s+/g, "-");
}// app.js — giriş nöqtəsi
import { formatDate } from "./utils";
const today = formatDate(new Date());
console.log(today);// Tree Shaking-dən sonra — buntda yalnız formatDate
function formatDate(date) {
return date.toISOString().slice(0, 10);
}
const today = formatDate(new Date());
console.log(today);Tree Shaking formatCurrency və slugify-i yekun buntdan xaric etdi, çünki onlar app.js-də idxal edilmir. utils.js modulunun ölçüsü 3 funksiyadan 1-ə düşdü. Əgər utils.js-də side effects varsa (məsələn, qlobal inisializasiya), Tree Shaking hətta istifadə olunmayan ixracları belə silə bilməyəcək.
Webpack production rejimində TerserPlugin plagin vasitəsilə Tree Shaking üçün daxili dəstək ehtiva edir. Tree Shaking-i işə salmaq üçün iki şərt kifayətdir: mode production (mode: "production") olaraq təyin edilməli və modullar ES sintaksisindən (import/export) istifadə etməlidir. Webpack avtomatik olaraq istifadə olunmayan ixracları qeyd edir və silinmək üçün Terser-ə ötürür.
Əlavə konfiqurasiya usedExports: true optimization.webpack.config.js-də modul daxilində ixracların istifadəsinin detallı təhlilini aktivləşdirir. Bu seçim hansı ixracların həqiqətən istifadə edildiyini (used) və hansıların yalnız ixrac edildiyini (provided) müəyyən edir. usedExports və Terser kombinasiyası ölü kodun silinməsində maksimum effektivlik verir.
// webpack.config.js — Tree Shaking konfiqurasiyası
module.exports = {
mode: "production",
entry: "./src/app.js",
output: {
filename: "bundle.js",
},
optimization: {
usedExports: true,
minimize: true,
concatenateModules: true,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules\/(?!(my-lib)\/).*/,
use: {
loader: "babel-loader",
options: {
presets: [
["@babel/preset-env", { modules: false }],
],
},
},
},
],
},
};Əsas parametr — @babel/preset-env-də modules: false. Babel standart olaraq ES-modullarını CommonJS-ə çevirir ki, bu da Tree Shaking-i öldürür. modules: false Babel-ə import/export-u çevirməyi qadağan edir, Webpack üçün ES sintaksisini saxlayır. concatenateModules əlavə olaraq modulları ümumi görünmə sahəsində birləşdirir, IIFE sayını və bunt ölçüsünü azaldır.
Side effects (yan təsirlər) — modulun idxal edildikdə ixrac edilən dəyərlərlə əlaqəli olmayan hərəkətləri: qlobal stillər (import "./styles.css"), polifillər (import "core-js/stable"), qlobal dəyişənlərin inisializasiyası və ya Service Worker qeydiyyatı. Əgər modulda side effects varsa, qurucu onu buntdan təhlükəsiz şəkildə silə bilməz, hətta heç bir ixrac istifadə edilməsə belə.
sideEffects flagı package.json-da qurucuya paketdəki hansı modulların yan təsirlərinin olmadığını bildirir. Bütün modulların təmiz olduğu paket üçün (yalnız funksiya ixracı) "sideEffects": false təyin edilməlidir. CSS və ya polifilləri olan paketlər üçün — yan təsirləri olan fayllara yollar massivi: "sideEffects": ["*.css"]. Bu flag olmadan Tree Shaking hətta istifadə olunmayan funksiyaları belə silməyəcək.
Modulda yan təsirlərin olub-olmadığını yoxlamaq üçün sual verin: bu idxal dəyər ixracı ilə əlaqəli olmayan hər hansı bir hərəkət edəcəkmi? import "./styles.css" CSS-i DOM-a əlavə edir — bu side effect-dir. import { throttle } from "lodash-es" side effect-ə malik deyil — o, sadəcə throttle funksiyasını əlçatan edir. Polifillər (import "core-js/stable") side effect-ə malikdir — onlar qlobal prototipləri dəyişdirir.
Öz modullarınız üçün tövsiyə olunur: stilləri və polifilləri ayrı giriş nöqtələrinə çıxarmaq, təmiz alətləri (yan təsirsiz funksiyalar) yan təsirləri olan modullardan (inisializasiya, loglama, Service Worker qeydiyyatı) ayırmaq. Yuxarı səviyyəli layihənin package.json-da "sideEffects": false yalnız bütün modullar təmiz olduqda təyin edilməlidir. Stillər varsa — "sideEffects": ["*.css"] dəqiq təyin edilməlidir.
{
"name": "my-ui-lib",
"version": "2.1.0",
"sideEffects": [
"*.css",
"polyfills.js"
],
"module": "dist/index.esm.js",
"main": "dist/index.cjs.js"
}"sideEffects": ["*.css", "polyfills.js"] o deməkdir: bütün CSS fayllarının yan təsirləri var (onlar silinə bilməz) və polyfills.js-nin də. Paketdəki bütün digər JS faylları təmizdir — onlar təhlükəsiz şəkildə shake-edilə bilər. module sahəsi qurucunun Tree Shaking üçün CommonJS versiyası (main) əvəzinə istifadə etməli olduğu ES versiyasına yolu göstərir.
React Native Metro Bundler ilə məhdud Tree Shaking versiyasını dəstəkləyir. Metro Webpack kimi istifadə olunan ixracların (usedExports) tam statik təhlilini aparmır. Bunun əvəzinə Metro minifikasiya mərhələsində modulların istifadə olunmayan hissəsini silmək üçün Terser-ə etibar edir. Bu yanaşmanın effektivliyi Webpack-də tam Tree Shaking-dən aşağıdır.
Maksimum optimallaşdırma üçün React Native layihələrində tövsiyə olunur: ES modulları olan kitabxanalardan istifadə etmək (package.json-da module sahəsi), debug kodunu silmək üçün babel-plugin-transform-remove-console plaginlərini qoşmaq və Terser üçün Metro transformer.minifierConfig-i konfiqurasiya etmək. Əlavə olaraq Ram Bundle (buntun modullara bölünməsi) istifadə olunmayan ekranların yüklənməsini azaldır.
Tez-tez verilən suallar
CommonJS (require/module.exports) statik təhlili dəstəkləmir — require şərtlər və funksiyalar daxilində dinamik olaraq çağırıla bilər. Qurucu modulun hansı hissələrinin həqiqətən istifadə edildiyini müəyyən edə bilmir. Yalnız statik import/export olan ES-modulları Tree Shaking-ə imkan verir.
TypeScript Tree Shaking ilə tam uyğundur, tsconfig.json-un ES-modullarına konfiqurasiya edilməsi şərtilə: "module": "esnext". TypeScript kompilyatoru import/export-u CommonJS-ə çevirmədən saxlamalıdır. @babel/preset-typescript və modules: false olan Babel də ES-modullarını Webpack-ə düzgün ötürür.
Webpack Bundle Analyzer — buntun tərkibini interaktiv diaqram şəklində vizuallaşdıran plagin. Əgər kitabxana buntda mövcuddursa, lakin onun funksiyaları istifadə edilmirsə, Tree Shaking işləməyib. Həmçinin çıxış faylını təhlil etmək olar: grep vasitəsilə bunt mətnində istifadə olunmayan ixracı tapmaq.
Lodash v4 CommonJS paketi kimi yayımlanır. Tree Shaking üçün lodash-es — kitabxananın ES versiyasından istifadə etmək lazımdır. import throttle from "lodash/throttle"-ni import { throttle } from "lodash-es" ilə əvəz edin və Webpack-də resolve.alias-ı lodash-ı lodash-es ilə əvəz etmək üçün konfiqurasiya edin.
Tree Shaking qurulma vaxtını cüzi artırır (5–15%), çünki asılılıq qrafikinin təhlili və istifadə olunan ixracların qeyd edilməsi mərhələsini əlavə edir. Development rejimində Tree Shaking adətən sürət üçün söndürülür. Production-da əlavə vaxt bunt ölçüsünün əhəmiyyətli dərəcədə azalması ilə əsaslandırılır.
Xülasə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun