При сборке библиотеки в Vite одним из ключевых параметров становится формат выходного файла. От выбранного формата зависит:
Vite использует Rollup в качестве системы сборки, поэтому поддерживает несколько стандартных форматов:
escjsumdiifeНастройка выполняется через build.lib.formats.
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: 'src/index.js',
name: 'MyLibrary',
formats: ['es', 'cjs', 'umd']
}
}
})
В результате Vite создаёт несколько файлов библиотеки в разных форматах одновременно.
es)Формат es основан на стандарте ECMAScript Modules (ESM).
Это современный стандарт модульной системы JavaScript.
Файлы используют:
export
import
Этот формат считается основным для современных библиотек.
Импорты анализируются ещё до выполнения кода.
import { sum } from './math.js'
Это позволяет:
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: 'src/index.js',
formats: ['es'],
fileName: 'my-lib'
}
}
})
dist/
my-lib.js
Содержимое будет выглядеть примерно так:
function sum(a, b) {
return a + b
}
export { sum }
<script type="module">
import { sum } from './my-lib.js'
console.log(sum(2, 3))
</script>
import { sum } from 'my-lib'
esСборщики могут удалить неиспользуемый код.
export function a() {}
export function b() {}
export function c() {}
Если импортируется только a, остальные функции не
попадут в итоговый бандл.
Поддерживается:
ESM позволяет:
esСтарые версии:
могут требовать дополнительные настройки.
Internet Explorer не поддерживает ES-модули.
cjs)cjs — модульная система Node.js, существовавшая до
появления ESM.
Использует:
require()
module.exports
function sum(a, b) {
return a + b
}
module.exports = {
sum
}
Импорт:
const { sum } = require('./math')
cjsimport { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: 'src/index.js',
formats: ['cjs']
}
}
})
dist/
my-lib.cjs
Модули загружаются во время выполнения.
const lib = require('./lib')
Это ухудшает возможности оптимизации по сравнению с ESM.
Большая часть старой экосистемы npm использует CommonJS.
Формат нужен для:
cjsИз-за динамической природы require() сборщики хуже
анализируют зависимости.
Современная экосистема постепенно переходит на ESM.
CommonJS изначально создавался для Node.js.
cjsФормат нужен, если библиотека:
umd)umd означает Universal Module Definition.
Формат предназначен для работы одновременно:
UMD автоматически определяет среду выполнения.
Пример структуры:
(function (global, factory) {
if (typeof exports === 'object') {
module.exports = factory()
} else if (typeof define === 'function' && define.amd) {
define(factory)
} else {
global.MyLibrary = factory()
}
})(this, function () {
return {}
})
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: 'src/index.js',
name: 'MyLibrary',
formats: ['umd']
}
}
})
nameДля UMD необходимо указать:
name: 'MyLibrary'
Это имя глобальной переменной:
window.MyLibrary
<script src="./my-lib.umd.js"></script>
<script>
console.log(MyLibrary)
</script>
UMD работает практически везде.
Подходит для CDN и <script>.
Многие библиотеки раньше распространялись именно в UMD:
UMD содержит дополнительную обвязку.
Оптимизация хуже, чем у ESM.
Современные библиотеки всё реже используют UMD как основной формат.
iife)iife — Immediately Invoked Function Expression.
Код оборачивается в самовызывающуюся функцию.
(function () {
console.log('library loaded')
})()
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: 'src/index.js',
name: 'MyLibrary',
formats: ['iife']
}
}
})
var MyLibrary = (function () {
function sum(a, b) {
return a + b
}
return {
sum
}
})()
<script src="./my-lib.iife.js"></script>
<script>
console.log(MyLibrary.sum(1, 2))
</script>
Не требует модульной системы.
Код выполняется сразу после загрузки.
Достаточно одного тега <script>.
Формат не поддерживает модульную архитектуру.
Весь код всегда включается в файл.
Библиотека попадает в глобальный объект.
IIFE подходит только для простых сценариев.
| Формат | Модули | Tree-shaking | Node.js | Browser Script | Современность |
|---|---|---|---|---|---|
| es | Да | Отличный | Да | Да (type="module") |
Высокая |
| cjs | Да | Ограниченный | Отличный | Нет | Средняя |
| umd | Частично | Слабый | Да | Да | Низкая |
| iife | Нет | Нет | Нет | Да | Низкая |
На практике библиотеки часто публикуют несколько сборок.
Пример:
formats: ['es', 'cjs']
или:
formats: ['es', 'umd']
dist/
my-lib.js
my-lib.cjs
my-lib.umd.js
fileNamefileName: (format) => `my-library.${format}.js`
dist/
my-library.es.js
my-library.cjs.js
my-library.umd.js
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: 'src/index.js',
name: 'MyLibrary',
formats: ['es', 'cjs', 'umd'],
fileName: (format) => `my-library.${format}.js`
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue'
}
}
}
}
})
externalexternal: ['vue']
Vue не попадёт внутрь библиотеки.
При использовании UMD или IIFE внешние зависимости должны быть доступны глобально.
globals: {
vue: 'Vue'
}
Тогда библиотека ожидает:
<script src="vue.global.js"></script>
mainОбычно указывает на CommonJS-сборку.
{
"main": "./dist/my-lib.cjs.js"
}
moduleУказывает на ESM-сборку.
{
"module": "./dist/my-lib.es.js"
}
exportsСовременный способ описания экспортов.
{
"exports": {
".": {
"import": "./dist/my-lib.es.js",
"require": "./dist/my-lib.cjs.js"
}
}
}
Наиболее распространённая схема:
ESM -> основной формат
CJS -> совместимость с Node.js
UMD -> CDN и браузеры
IIFE используется значительно реже.
esПодходит для:
cjsПодходит для:
umdПодходит для:
iifeПодходит для:
Максимальная эффективность достигается только в ESM.
Причина — статический анализ импортов.
import { button } from 'ui-lib'
Сборщик может удалить всё остальное.
UMD и IIFE:
При библиотечной сборке:
build.lib
Vite автоматически:
Для всех форматов можно включить sourcemap:
build: {
sourcemap: true
}
Все форматы поддерживают минификацию:
build: {
minify: 'esbuild'
}
или:
build: {
minify: 'terser'
}
Code splitting работает ограниченно или недоступен.
Причина — браузерная природа форматов и необходимость единого файла.
Обычно:
ESM -> минимальный размер
CJS -> немного больше
UMD -> ещё больше
IIFE -> максимальный размер
Причина — дополнительные runtime-обёртки.
formats: ['es', 'cjs']
formats: ['es', 'umd']
formats: ['es', 'cjs', 'umd']
Причины:
ESM обеспечивает:
Именно поэтому большинство современных библиотек Vite ориентируются
прежде всего на формат es.