Встряска дерева (англ. three shaking
) - подход к сборке проекта, позволяющий добиться исключения "мёртвого кода" (англ. dead code elimination
) - тех файлов (или методов в этих файлах), которые не задействованы в приложении.
При этом подходе проект представляется в виде дерева зависимостей:
- Выбирается лючевой, корневой файл (
app.js
,index.js
), с которого начинается запуск приложения (например,node index.js
). Этот файл становится корнем дерева (англroot
). - Корневой файл чаше всего имеет зависимости (
require
,import
) в виде других файлов, которые в дереве зависимостей становятся его дочерними узлами. Поскольку эти файлы тоже могут иметь зависимости, то и у них могут быть дочерние узлы. Выстроив все цепочки зависимостей файлов, получаем некоторый граф. - Если некоторая зависимость уже была внедрена (импортирована), то второй раз она в итоговую сборку не включается - берётся уже существующая ссылка на файл. Это позволяет исключить циклические зависимости, а значит граф можно представить в виде дерева.
/* пример циклической зависимости */
// a.js
require('b.js');
// b.js
require('a.js');
- Таким образом, те файлы в проекте, которые по каким-либо причинам нигде не были импортированы, не попадают в дерево зависимотей, а значит и в сборку проекта. Это позволяет уменьшить размер бандла, а значит ускорить загрузку страницы.
- Если учесть, что можно импортировать не только файлы, но и отдельные методы, то узлами дерева могут становиться эти самые методы. В таком случае неимпортированные методы не так же не попадут в сборку.
Отсюда можно сделать вывод касательно названия. Когда мы трясём дерево - то, что держится за ветку не достаточно прочно, - падает (яблоки, шишки, каштаны, листья, а в нашем случае - "мёртвый код").
Концепция "встряски дерева" была популяризирована Rollup и Webpack.
Рассмотрим пример исключения неиспользуемых методов из сборки (с файлами всё аналогично).
Допустим, есть некоторый модуль utils.js
по типу lodash
, содержащий множество полезных утилит.
// utils.js
export const debounce = () => { /* ... */ };
export const throttle = () => { /* ... */ };
export const groupBy = () => { /* ... */ };
И есть модуль app.js
, который использует метод splitIntoChunks
из этого модуля. Пусть другие модули не используют utils.js
.
// app.js
import { groupBy } from 'utils';
В таком случае в сборку попадёт только метод groupBy
, а методы debounce
и throttle
в неё не попадут.