Сборка с webpack, Rollup, Vite

Crypto-js относится к библиотекам, которые активно используются в браузерной среде и Node.js для реализации криптографических примитивов: хеширование, симметричное шифрование, HMAC и набор вспомогательных утилит для работы с кодировками и бинарными данными. При интеграции в проекты с современными сборщиками ключевое значение имеет способ импорта, влияние на размер бандла и корректная работа в ESM/CJS окружениях.

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


Особенности структуры пакета crypto-js

Пакет организован как набор независимых модулей:

  • crypto-js/core
  • crypto-js/md5
  • crypto-js/sha256
  • crypto-js/aes
  • crypto-js/enc-utf8
  • crypto-js/hmac

Каждый алгоритм вынесен отдельно, но общий экспорт часто тянется через корневой модуль:

import CryptoJS from 'crypto-js';

Такой импорт удобен, но влечёт загрузку всей библиотеки. Для production-сборок это считается неоптимальным вариантом.

Более точечный импорт:

import SHA256 from 'crypto-js/sha256';
import AES from 'crypto-js/aes';

Webpack: конфигурация и оптимизация

Webpack по умолчанию умеет работать с CommonJS, однако tree-shaking в таком режиме ограничен. Основная проблема Crypto-js — отсутствие ESM-сборки.

Базовая интеграция

import SHA256 from 'crypto-js/sha256';

const hash = SHA256('message').toString();

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

Для уменьшения размера сборки применяется точечный импорт и настройка режима production:

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

Однако usedExports не всегда позволяет удалить неиспользуемые части Crypto-js, поскольку CommonJS-структура затрудняет статический анализ.


Алиасинг и замена импортов

Практика уменьшения бандла заключается в подмене импортов через resolve.alias.

resolve: {
  alias: {
    'crypto-js': 'crypto-js/core'
  }
}

Такой подход может привести к ошибкам, если используются алгоритмы вне core, поэтому применяется осторожно.


Rollup: особенности сборки

Rollup обеспечивает более строгий tree-shaking, но Crypto-js остаётся проблемным из-за CJS-архитектуры.

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

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 способен исключать неиспользуемые модули только при точечных импортах:

import MD5 from 'crypto-js/md5';

При импорте через корневой модуль оптимизация фактически не работает.


Проблемы совместимости ESM и CommonJS

Crypto-js не предоставляет нативной ESM-сборки, поэтому сборщики вынуждены использовать транспиляцию через commonjs-плагины.

Типичные последствия:

  • невозможность статически анализировать внутренние зависимости
  • увеличение итогового размера бандла
  • частичная потеря tree-shaking

Vite: поведение и pre-bundling

Vite использует esbuild для предварительной обработки зависимостей. Crypto-js обрабатывается как CommonJS-пакет и преобразуется в ESM-обёртку.

Автоматическое преобразование

При первом запуске dev-сервера Vite выполняет pre-bundle:

  • конвертация CJS → ESM
  • кеширование результата в node_modules/.vite

Импорт в Vite

import SHA256 from 'crypto-js/sha256';

Работает стабильно, но итоговый бандл всё равно зависит от структуры импорта.


Оптимизация в Vite

Vite позволяет исключать излишние зависимости через optimizeDeps:

export default {
  optimizeDeps: {
    include: ['crypto-js/sha256', 'crypto-js/aes']
  }
};

Это ускоряет dev-сервер, но не решает проблему полного бандла при неправильных импортах.


Динамический импорт алгоритмов

Для ленивой загрузки криптографических операций применяется динамический импорт:

async function hashMessage(msg) {
  const { default: SHA256 } = await import('crypto-js/sha256');
  return SHA256(msg).toString();
}

Такой подход уменьшает initial bundle size, особенно в SPA с большим количеством редко используемых функций.


Работа с большими приложениями

В масштабных проектах Crypto-js часто становится причиной увеличения бандла из-за неосторожного импорта.

Типичные стратегии контроля размера:

  • импорт только используемых алгоритмов
  • отказ от crypto-js/index
  • использование динамических импортов
  • анализ бандла через webpack-bundle-analyzer или аналогичные инструменты

Tree-shaking и реальная эффективность

Несмотря на поддержку современных сборщиков, Crypto-js не является tree-shake-friendly библиотекой. Причины:

  • CommonJS экспорт
  • побочные эффекты в модулях
  • отсутствие ES module build

Фактически tree-shaking работает только на уровне модульного импорта файлов, а не внутренних функций.


Типичные ошибки при интеграции

  • импорт через корневой пакет вместо конкретных модулей
  • ожидание автоматического удаления неиспользуемых алгоритмов
  • смешивание CJS и ESM без настройки commonjs-плагинов
  • отсутствие анализа итогового бандла

Практика разделения криптографических функций

В архитектуре фронтенд-приложений криптографические операции часто выделяются в отдельный слой:

/crypto
  sha.js
  aes.js
  hmac.js

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


Итоговые особенности поведения в сборщиках

Поведение Crypto-js в современных инструментах сборки определяется не самим API библиотеки, а форматом её распространения. Webpack, Rollup и Vite по-разному обрабатывают CommonJS-модули, однако во всех случаях ключевым фактором оптимизации остаётся точность импортов и отказ от глобального подключения пакета целиком.