Использование с системами сборки

Модульная архитектура и форматы поставки

Cleave.js распространяется в нескольких форматах, ориентированных на разные сценарии сборки: CommonJS, ES Modules и UMD. Выбор формата напрямую влияет на то, как библиотека будет интегрироваться в проект и как сборщик сможет выполнять оптимизации.

Основные форматы:

  • ESM (ES Modules) — предпочтительный вариант для современных сборщиков
  • CommonJS (CJS) — совместимость с Node.js и устаревшими конфигурациями
  • UMD — использование через <script> без сборки

ESM-версия обеспечивает корректный tree-shaking, что особенно важно при использовании Vite, Rollup и современных конфигураций Webpack.


Подключение через Webpack

Webpack поддерживает оба основных формата, но оптимальная интеграция достигается через ESM-импорт.

Установка зависимости

npm install cleave.js

Базовый импорт

import Cleave from 'cleave.js';
import 'cleave.js/dist/addons/cleave-phone.i18n';

При использовании Webpack 5 модуль будет автоматически включён в граф зависимостей. Важно учитывать, что некоторые версии Cleave.js могут экспортировать как default, так и named exports, поэтому конфигурация esModuleInterop в TypeScript может влиять на поведение импорта.

Использование в компоненте

const input = document.querySelector('#phone');

const cleave = new Cleave(input, {
  phone: true,
  phoneRegionCode: 'US'
});

Tree-shaking и sideEffects

Для корректной оптимизации важно учитывать поле sideEffects:

{
  "sideEffects": false
}

Однако для Cleave.js это не всегда безопасно, так как библиотека модифицирует DOM. В Webpack рекомендуется не форсировать агрессивное удаление модулей без проверки.


Интеграция с Vite

Vite использует ESBuild для дев-сервера и Rollup для production-сборки, что делает работу с Cleave.js более предсказуемой.

Установка и импорт

npm install cleave.js
import Cleave from 'cleave.js';

Vite автоматически оптимизирует зависимости, поэтому дополнительная конфигурация обычно не требуется.

Особенности работы в dev-режиме

  • быстрый HMR не всегда корректно пересоздаёт инстансы Cleave
  • при обновлении компонента требуется ручной destroy
let cleave;

export function init() {
  const input = document.querySelector('#card');

  cleave = new Cleave(input, {
    creditCard: true
  });
}

export function destroy() {
  if (cleave) {
    cleave.destroy();
    cleave = null;
  }
}

Rollup и оптимальная сборка библиотек

Rollup чаще всего используется при создании библиотек, где Cleave.js подключается как внешняя зависимость.

Конфигурация external

export default {
  input: 'src/index.js',
  output: {
    format: 'esm',
    file: 'dist/bundle.js'
  },
  external: ['cleave.js']
};

Такой подход предотвращает дублирование кода библиотеки в итоговом бандле.

Плагин node-resolve

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

export default {
  plugins: [
    resolve()
  ]
};

Parcel и нулевая конфигурация

Parcel автоматически обрабатывает зависимости, включая Cleave.js, без дополнительной настройки.

import Cleave from 'cleave.js';

new Cleave('#date', {
  date: true,
  datePattern: ['d', 'm', 'Y']
});

Особенности Parcel:

  • автоматическое преобразование CommonJS → ESM
  • встроенный транспайлинг
  • отсутствие необходимости в ручной настройке loaders

TypeScript и типизация

При использовании TypeScript могут возникать расхождения типов из-за различий между CommonJS и ESM экспортом Cleave.js.

Базовый импорт

import Cleave from 'cleave.js';

const input = document.getElementById('price') as HTMLInputElement;

new Cleave(input, {
  numeral: true,
  numeralThousandsGroupStyle: 'thousand'
});

Проблема с дефолтным импортом

При отсутствии esModuleInterop:

import * as Cleave from 'cleave.js';

В таком случае доступ к конструктору осуществляется через:

const cleave = new (Cleave as any).default(input, options);

Babel и транспиляция

При использовании Babel важно учитывать, что Cleave.js не требует трансформации синтаксиса, но может зависеть от настроек модулей.

preset-env

{
  "presets": [
    ["@babel/preset-env", {
      "modules": "auto"
    }]
  ]
}

Проблема двойной трансформации

Неправильная конфигурация может привести к:

  • двойному оборачиванию модулей
  • нарушению tree-shaking
  • увеличению размера bundle

Использование в SSR (Node.js)

Cleave.js ориентирован на работу с DOM, поэтому при серверном рендеринге требуется изоляция клиентской логики.

Проверка окружения

if (typeof window !== 'undefined') {
  const Cleave = require('cleave.js');

  new Cleave('#ssr-input', {
    numeral: true
  });
}

Lazy initialization

В SSR-приложениях (Next.js, Nuxt) инициализация выполняется только на клиенте:

useEffect(() => {
  const Cleave = require('cleave.js');

  const instance = new Cleave(inputRef.current, {
    phone: true
  });

  return () => instance.destroy();
}, []);

Работа с alias и монорепозиториями

В монорепозиториях (pnpm, yarn workspaces) важно избегать дублирования зависимостей Cleave.js.

Webpack alias

resolve: {
  alias: {
    'cleave.js': require.resolve('cleave.js')
  }
}

pnpm hoisting особенности

  • возможна множественная установка пакета
  • важно фиксировать версию через lockfile
  • рекомендуется единая точка импорта

Оптимизация загрузки

При использовании сборщиков критично контролировать момент загрузки Cleave.js.

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

async function loadMask() {
  const { default: Cleave } = await import('cleave.js');

  new Cleave('#dynamic', {
    numeral: true
  });
}

Code splitting

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


Частые проблемы при сборке

1. Несовместимость CommonJS и ESM

Ошибки вида:

  • Cleave is not a constructor
  • default is undefined

Причина — неправильная интерпретация экспорта.

2. Дублирование инстансов

При повторной инициализации без destroy() возникают конфликтующие обработчики событий.

3. Tree-shaking и побочные эффекты

Cleave.js активно работает с DOM, поэтому удаление модулей сборщиком может приводить к некорректному поведению.

4. HMR в dev-среде

Hot Module Replacement не всегда корректно пересоздаёт DOM-инстансы, требуется ручной контроль жизненного цикла.


Итоговая модель интеграции в сборках

Использование Cleave.js в современных системах сборки строится вокруг нескольких ключевых принципов:

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