Кэширование сборки в Webpack строится вокруг идеи сохранения промежуточных результатов между запусками, чтобы повторная сборка не выполняла одинаковую работу заново. В современных версиях Webpack основная реализация основана на persistent filesystem cache, который позволяет хранить артефакты компиляции на диске и восстанавливать их при последующих запусках.
Внутренняя система кэширования Webpack работает на нескольких уровнях:
Каждый уровень решает свою задачу, но совместно они уменьшают количество повторных вычислений.
Основной принцип: если входные данные модуля и окружение не изменились, результат его обработки может быть переиспользован.
Ключевая функциональность Webpack 5 — встроенный файловый кэш, который сохраняет данные сборки между процессами.
Конфигурация включает базовый блок:
module.exports = {
cache: {
type: 'filesystem',
cacheDirectory: path.resolve(__dirname, '.webpack-cache'),
buildDependencies: {
config: [__filename]
}
}
}
При первой сборке Webpack:
При повторной сборке:
Кэш становится невалидным при изменении следующих факторов:
Особое внимание уделяется buildDependencies:
buildDependencies: {
config: [__filename]
}
Любое изменение конфигурационного файла приводит к полной инвалидизации кэша, так как Webpack не может гарантировать идентичность результата.
Хотя persistent cache работает на уровне сборщика, contenthash влияет на итоговые артефакты.
Разделение:
Пример:
output: {
filename: '[name].[contenthash].js'
}
Если содержимое модуля не изменилось, Webpack может использовать кэшированную трансформацию и в итоге сохранить тот же contenthash.
Каждый модуль проходит цепочку loader-ов. Webpack сохраняет промежуточные результаты:
Если входной файл и конфигурация loader-ов не изменились, pipeline не выполняется заново.
Пример:
module: {
rules: [
{
test: /\.ts$/,
use: [
'cache-loader',
'ts-loader'
]
}
]
}
В Webpack 5 cache-loader часто избыточен, поскольку
filesystem cache уже покрывает эту задачу.
Отдельный слой кэширования относится к resolve алгоритму.
Webpack кеширует:
import 'react')@components/Button).js, .ts,
.json)Это позволяет избежать повторного обхода файловой системы.
Пример настройки resolve:
resolve: {
extensions: ['.js', '.ts'],
alias: {
'@': path.resolve(__dirname, 'src')
}
}
Каждый resolve запрос кэшируется с учётом контекста.
Webpack использует snapshot механизм для отслеживания состояния файловой системы.
Snapshot включает:
Если snapshot совпадает с предыдущим состоянием, файл считается неизменным и не пересобирается.
Это особенно важно при инкрементальной сборке.
Неправильная настройка buildDependencies может полностью
обесценить persistent cache.
Типичная ошибка:
buildDependencies: {
config: []
}
В таком случае изменения конфигурации могут не учитываться, что приводит к некорректной сборке.
Оптимальный вариант:
buildDependencies: {
config: [__filename],
tsconfig: [path.resolve(__dirname, 'tsconfig.json')]
}
В монорепозиториях (Lerna, Nx, pnpm workspaces) проблема кэширования усложняется:
Ключевой риск — чрезмерная инвалидизация кэша.
Решение:
Пример:
cache: {
type: 'filesystem',
cacheDirectory: path.resolve(__dirname, '.cache', packageName),
name: packageName
}
Не все loader-ы одинаково хорошо кэшируются.
Проблемные случаи:
Такие loader-ы полностью ломают кэширование.
Правильный подход — детерминированные трансформации.
Основные причины cache miss:
Оптимизация включает:
Filesystem cache ускоряет сборку за счёт:
Однако при очень больших проектах возникают узкие места:
В таких случаях используется разделение кэша по средам (dev/build/ci).
В development режиме cache особенно важен при HMR.
Webpack сохраняет:
Это позволяет обновлять только изменённые части приложения без полной пересборки.
Persistent cache напрямую влияет на performance budget проекта:
Но при этом увеличивает:
На практике persistent cache может приводить к скрытым проблемам:
В таких случаях часто используется временное отключение cache:
cache: false
или очистка директории .webpack-cache.
В CI системах кэширование требует аккуратной настройки:
Часто применяется стратегия:
Это значительно ускоряет pipeline при повторных прогонах.