Stanford JS Crypto Library изначально проектировалась как универсальная криптографическая библиотека с акцентом на полноту алгоритмов и совместимость. Это приводит к тому, что при стандартном подключении в проект попадает значительно больше кода, чем требуется конкретному приложению.
Основные факторы разрастания:
В результате минимальный импорт часто тянет за собой десятки килобайт лишнего JavaScript-кода, который никогда не выполняется в рантайме.
Библиотека организована как набор модулей внутри глобального объекта
sjcl, где каждый компонент регистрируется через расширение
пространства имён.
Типичная структура:
sjcl.core — базовые утилиты и математические
операцииsjcl.cipher — AES и режимы шифрованияsjcl.hash — SHA-256, SHA-512 и др.sjcl.misc — вспомогательные функции (bitArray,
codec)sjcl.keyexchange — Diffie-Hellman и ECDHsjcl.prng — генератор случайных чиселОсобенность архитектуры заключается в том, что модули не являются ESM или CommonJS в современном смысле. Это влияет на работу tree-shaking в Webpack/Rollup.
Современные сборщики ориентируются на статический анализ импортов. SJCL же:
Из-за этого:
Даже при импорте только AES в сборку часто попадает hash, prng и codec.
Наиболее эффективный подход — использование исходных файлов SJCL напрямую, без подключения всей библиотеки.
Пример структуры:
import './sjcl/core.js';
import './sjcl/cipher/aes.js';
import './sjcl/misc/bitArray.js';
Ключевой принцип — импортировать только те файлы, которые реально используются.
Ограничения подхода:
На практике наибольший выигрыш даёт исключение следующих компонентов:
Ручное удаление достигается через кастомную сборку или патчинг исходников:
// удаление лишних модулей перед сборкой
delete sjcl.ecc;
delete sjcl.keyexchange;
Однако такой подход нестабилен и применяется только в специфических сборках.
Webpack в случае SJCL работает преимущественно как транспилятор и бандлер, а не как оптимизатор структуры кода.
Типичная проблема:
import sjcl from 'sjcl';
Такой импорт гарантирует попадание всей библиотеки в бандл.
Более эффективный вариант:
import sjcl from './vendor/sjcl/core.js';
import './vendor/sjcl/cipher/aes.js';
Даже в этом случае Webpack сохраняет побочные эффекты, если не
указать sideEffects: false в package.json, что
для SJCL обычно невозможно без риска поломки логики.
Попытка включить агрессивное удаление кода:
{
"sideEffects": false
}
Для SJCL часто приводит к:
Причина — модули рассчитывают на выполнение кода при загрузке, а не на чистые экспорты.
Наиболее эффективный подход — сборка собственной версии библиотеки.
Структура:
sjcl-custom/
core.js
aes.js
bitArray.js
sha256.js
Скрипт сборки (пример с Rollup):
export default {
input: 'sjcl-custom/index.js',
output: {
file: 'dist/sjcl.min.js',
format: 'iife',
name: 'sjcl'
},
plugins: []
};
index.js:
import './core.js';
import './aes.js';
import './bitArray.js';
import './sha256.js';
Такой подход даёт полный контроль над итоговым размером бандла.
Terser эффективно удаляет:
Ограничение — он не понимает архитектуру SJCL, поэтому не удаляет целые модули.
Closure Compiler даёт более глубокую оптимизацию:
Однако SJCL требует адаптации:
ADVANCED_OPTIMIZATIONS без проверкиНаиболее значительное уменьшение размера достигается за счёт выбора алгоритмов.
Пример минимального набора:
Исключение:
Такой набор покрывает большинство прикладных задач (шифрование токенов, локальное хранение секретов).
Практика разделения криптографии на отдельный chunk:
crypto.chunk.js
app.chunk.js
vendor.chunk.js
Используется динамический импорт:
const sjcl = await import('./crypto.chunk.js');
Преимущества:
После минимизации критично использовать:
SJCL хорошо сжимается из-за:
Типичный эффект:
Webpack alias позволяет исключить лишние части:
resolve: {
alias: {
sjcl: path.resolve('./sjcl-custom/minimal.js')
}
}
Такой подход фиксирует использование строго контролируемой версии библиотеки и предотвращает случайное расширение зависимостей.
Наиболее стабильная схема уменьшения размера:
Результат выражается не только в уменьшении размера бандла, но и в снижении времени инициализации криптографических операций в браузере.