Настройка webpack и rollup

Библиотека date-fns распространяется как набор модульных функций, ориентированных на ESM и CommonJS, что делает её удобной для интеграции с современными сборщиками. При работе с бандлерами ключевым становится корректная настройка tree-shaking, обработка локалей и выбор формата импортов.

Основная особенность архитектуры заключается в том, что каждая функция экспортируется отдельно. Это позволяет системам сборки удалять неиспользуемый код, но только при условии правильной конфигурации webpack или rollup.


ESM и CommonJS в date-fns

Современные версии date-fns ориентированы на ES Modules:

import { format, addDays } from 'date-fns';

Такой импорт позволяет бандлерам выполнять статический анализ зависимостей.

CommonJS-вариант:

const { format, addDays } = require('date-fns');

При использовании CommonJS tree-shaking часто работает хуже, особенно в webpack без дополнительной настройки sideEffects.


Настройка webpack для date-fns

Базовая конфигурация

Корректная работа tree-shaking требует включённого production mode:

const path = require('path');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

Включение tree-shaking

Важные параметры:

module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true,
    sideEffects: false
  }
};

Параметр sideEffects: false критичен для библиотек вроде date-fns, где каждый модуль является чистым.


Проверка ESM-резолва

webpack по умолчанию поддерживает поле module в package.json, но в некоторых случаях полезно явно указать:

resolve: {
  mainFields: ['module', 'main']
}

Это позволяет приоритизировать ESM-версию библиотеки.


Оптимизация локалей

date-fns содержит локали, которые могут значительно увеличивать размер бандла:

import { format } from 'date-fns';
import { ru } from 'date-fns/locale';

Чтобы избежать подтягивания всех локалей, необходимо импортировать их напрямую, а не через индексные файлы.


Алиасизация локалей

Иногда применяется ограничение доступных локалей:

module.exports = {
  resolve: {
    alias: {
      'date-fns/locale': 'date-fns/locale/ru'
    }
  }
};

Это позволяет принудительно ограничить набор языков.


Настройка rollup для date-fns

Rollup изначально ориентирован на ESM и обеспечивает более агрессивный tree-shaking.

Базовая конфигурация:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'esm'
  },
  plugins: [
    resolve(),
    commonjs()
  ]
};

Эффективность tree-shaking в rollup

rollup выполняет статический анализ модулей на этапе сборки и удаляет неиспользуемые экспорты без дополнительных настроек, если зависимости написаны в ESM-формате.

date-fns хорошо подходит для такого подхода, поскольку каждая функция представляет собой независимый модуль.


Работа с форматами сборки

date-fns поддерживает несколько форматов:

  • ESM (основной для современных сборщиков)
  • CommonJS (для Node.js окружений)
  • отдельные файлы функций

Выбор формата влияет на итоговый размер бандла и эффективность tree-shaking.


Устранение дублирования кода

При неправильной настройке сборщика могут появляться дубликаты функций:

import format from 'date-fns/format';
import addDays from 'date-fns/addDays';

Такой подход иногда предпочтительнее в webpack-сборках, где ESM анализ ограничен.

В rollup достаточно:

import { format, addDays } from 'date-fns';

Side effects и их влияние

Важнейший аспект оптимизации — корректное определение побочных эффектов.

date-fns не выполняет глобальных изменений состояния, поэтому может считаться полностью чистой библиотекой:

{
  "sideEffects": false
}

Это позволяет сборщикам безопасно удалять неиспользуемые части дерева зависимостей.


Минимизация размера бандла

Основные факторы, влияющие на размер:

  • импорт всей библиотеки вместо отдельных функций
  • подключение всех локалей
  • отсутствие tree-shaking
  • использование CommonJS в ESM-пайплайне

Оптимальная стратегия — точечные импорты:

import format from 'date-fns/format';
import parseISO from 'date-fns/parseISO';

Поддержка legacy-окружений

В старых версиях webpack может потребоваться настройка транспиляции:

module.exports = {
  module: {
    rules: [
      {
        test: /\.m?js$/,
        resolve: {
          fullySpecified: false
        }
      }
    ]
  }
};

Это предотвращает ошибки резолва ESM-путей.


Разделение кода (code splitting)

webpack автоматически поддерживает динамические импорты:

import('date-fns/format').then(({ default: format }) => {
  console.log(format(new Date(), 'yyyy-MM-dd'));
});

rollup использует аналогичный механизм через динамический import() при соответствующем output формате.


Использование date-fns в библиотечных сборках

При создании собственной библиотеки поверх date-fns важно сохранять ESM-совместимость:

export { format } from 'date-fns/format';
export { addDays } from 'date-fns/addDays';

Это позволяет downstream-сборщикам корректно выполнять tree-shaking.


Типичные проблемы интеграции

Проблема полного импорта

import * as df from 'date-fns';

Такой импорт блокирует tree-shaking и приводит к включению всех модулей.


Проблема локалей

Импорт через индекс:

import { ru } from 'date-fns/locale';

может подтянуть лишние данные при неправильной сборке, если бандлер не оптимизирует ESM-дерево.


Конфликт CJS и ESM

При смешивании форматов возможны дубли и увеличение размера bundle, особенно в webpack без корректного mainFields.