Интеграция с webpack и rollup

Библиотека jsrsasign распространяется в виде UMD-модуля и ориентирована на работу как в браузере, так и в Node.js, однако при использовании современных сборщиков модулей возникают специфические сложности, связанные с устаревшими предположениями о среде выполнения и отсутствием нативных Node.js-полифиллов в Webpack 5 и Rollup 3+.

jsrsasign содержит реализацию криптографических алгоритмов (RSA, ECDSA, SHA, HMAC, X.509) полностью на JavaScript. Это делает её независимой от WebCrypto API, но одновременно приводит к следующим особенностям:

  • использование глобальных объектов (window, navigator, Buffer в некоторых сценариях)
  • наличие большого UMD-бандла
  • отсутствие ESM-версии в классическом распространении
  • зависимость от псевдо-Node окружения в отдельных модулях

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

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

Основные сложности при интеграции:

  • отсутствие crypto, stream, buffer в Webpack 5 по умолчанию
  • некорректное определение глобальных переменных в Rollup без плагинов
  • невозможность tree-shaking в классическом варианте импорта
  • увеличение размера бандла при неправильной настройке импорта

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

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

Установка и базовое подключение

npm install jsrsasign

Простейший импорт:

import KJUR from 'jsrsasign';

или более точечный:

import { KEYUTIL, KJUR } from 'jsrsasign';

Однако в большинстве случаев UMD-структура приводит к загрузке всей библиотеки.

Настройка Webpack 5

Webpack 5 не предоставляет автоматические полифиллы Node.js, поэтому необходимо вручную добавить зависимости:

npm install crypto-browserify stream-browserify buffer process

Конфигурация webpack:

const webpack = require('webpack');

module.exports = {
  resolve: {
    fallback: {
      crypto: require.resolve('crypto-browserify'),
      stream: require.resolve('stream-browserify'),
      buffer: require.resolve('buffer/'),
      process: require.resolve('process/browser')
    }
  },
  plugins: [
    new webpack.ProvidePlugin({
      Buffer: ['buffer', 'Buffer'],
      process: 'process/browser'
    })
  ]
};

Важный момент при работе с crypto

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

Если требуется уменьшить размер сборки, часто используют альтернативный подход:

module.exports = {
  externals: {
    jsrsasign: 'jsrsasign'
  }
};

В этом случае библиотека подключается через CDN:

<script src="https://cdn.jsdelivr.net/npm/jsrsasign/lib/jsrsasign-all-min.js"></script>

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

Rollup требует более явной конфигурации для CommonJS-зависимостей, так как jsrsasign не поставляется как ESM-модуль.

Установка плагинов

npm install @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-replace

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

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

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'esm',
    sourcemap: true
  },
  plugins: [
    resolve({
      browser: true,
      preferBuiltins: false
    }),
    commonjs(),
    replace({
      preventAssignment: true,
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ]
};

Обработка Node-зависимостей

При использовании Rollup важно отключить попытки подтянуть Node core modules:

resolve({
  browser: true,
  preferBuiltins: false
})

В некоторых случаях дополнительно требуется ручная заглушка:

export default {
  plugins: [
    resolve(),
    commonjs(),
    replace({
      'global.Buffer': 'Buffer',
      preventAssignment: true
    })
  ]
};

Оптимизация размера бандла

jsrsasign изначально довольно тяжёлая библиотека, поэтому важны способы ограничения объёма включаемого кода.

Импорт только нужных частей

Вместо полного объекта:

import KJUR from 'jsrsasign';

предпочтительнее точечные импорты:

import KEYUTIL from 'jsrsasign/lib/keyutil';
import KJUR from 'jsrsasign/lib/jsrsasign';

Однако структура пакета не всегда гарантирует стабильные пути, поэтому требуется проверка конкретной версии библиотеки.

Исключение через externals

При использовании CDN-версии:

externals: {
  jsrsasign: 'KJUR'
}

и подключение:

<script src="https://cdn.jsdelivr.net/npm/jsrsasign/lib/jsrsasign-all-min.js"></script>

Такой подход полностью убирает библиотеку из бандла.

Минификация и дедупликация

Rollup по умолчанию обеспечивает tree-shaking, но только при ESM-совместимых модулях. Так как jsrsasign CommonJS-ориентирован, реальная оптимизация ограничена, и чаще используется terser:

npm install @rollup/plugin-terser
import terser from '@rollup/plugin-terser';

plugins: [
  terser()
]

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

Ошибка Buffer is not defined

Возникает при отсутствии полифилла:

new webpack.ProvidePlugin({
  Buffer: ['buffer', 'Buffer']
});

crypto is not found

Исправляется через fallback:

crypto: require.resolve('crypto-browserify')

Module parse failed (CommonJS)

Решается подключением:

@rollup/plugin-commonjs

или настройкой Webpack:

module: {
  rules: [
    {
      test: /\.js$/,
      type: 'javascript/auto'
    }
  ]
}

Увеличенный размер бандла

Причина обычно в полном импорте:

import * as jsrsasign from 'jsrsasign';

Это подтягивает всю библиотеку, включая RSA, ECDSA, ASN.1 и вспомогательные утилиты.

Более контролируемый вариант требует прямого импорта конкретных модулей или использования CDN.

Особенности использования в ESM-проектах

При работе с современными ES-модулями важно учитывать, что jsrsasign остаётся CommonJS-библиотекой. Это приводит к необходимости интеропа:

import jsrsasignPkg from 'jsrsasign';
const { KJUR } = jsrsasignPkg;

или через динамический импорт:

const jsrsasign = await import('jsrsasign');

В некоторых сборках это уменьшает проблемы с tree-shaking, но не устраняет их полностью.

Поведение в разных окружениях сборки

Webpack чаще скрывает проблемы за polyfill-слоем, тогда как Rollup требует явной декларации каждого внешнего модуля. Это приводит к следующему различию поведения:

  • Webpack: больше автоматической совместимости, но тяжелее итоговый бандл
  • Rollup: более чистый результат, но требуется ручная настройка окружения

При использовании jsrsasign это различие становится особенно заметным из-за его монолитной структуры и отсутствия ESM-разделения