Параметр output.library используется для экспорта
собранного бандла как библиотеки. Вместо обычного приложения, которое
просто выполняется в браузере, Webpack может сформировать модуль,
доступный внешнему коду через глобальную переменную, CommonJS, AMD, UMD
или современные ES-модули.
Такой режим применяется при разработке:
Webpack позволяет контролировать:
Минимальная конфигурация библиотеки:
// webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
filename: 'my-lib.js',
library: {
name: 'MyLibrary',
type: 'umd'
}
}
};
После сборки библиотека становится доступной:
<script src="my-lib.js"></script>
<script>
MyLibrary.someMethod();
</script>
libraryВ современных версиях Webpack параметр имеет объектную форму:
output: {
library: {
name: 'MyLibrary',
type: 'umd',
export: 'default'
}
}
Поддерживаются свойства:
| Свойство | Назначение |
|---|---|
name |
Имя библиотеки |
type |
Тип экспорта |
export |
Что именно экспортировать |
library.nameОпределяет имя библиотеки в целевом окружении.
Пример:
output: {
library: {
name: 'Utils',
type: 'window'
}
}
Результат:
window.Utils = ...
Использование:
<script src="bundle.js"></script>
<script>
Utils.formatDate();
</script>
library.nameНаиболее распространённый вариант:
name: 'MyLibrary'
Создание вложенных пространств имён:
name: ['App', 'Utils']
Результат:
window.App = window.App || {};
window.App.Utils = ...
Использование:
App.Utils.method();
Позволяет задавать разные имена для разных типов библиотек.
library: {
name: {
root: 'MyLibrary',
amd: 'my-library',
commonjs: 'my-common-library'
},
type: 'umd'
}
Это особенно важно при публикации универсальных npm-пакетов.
library.typeОпределяет способ экспорта библиотеки.
От этого зависит:
type: 'var'output: {
library: {
name: 'MyLibrary',
type: 'var'
}
}
Результат:
var MyLibrary = ...
Особенности:
type: 'assign'Присваивание значения существующей переменной.
library: {
name: 'MyLibrary',
type: 'assign'
}
Результат:
MyLibrary = ...
Webpack не создаёт переменную самостоятельно.
type: 'this'Экспорт в this.
library: {
name: 'MyLibrary',
type: 'this'
}
Результат:
this.MyLibrary = ...
Поведение зависит от контекста выполнения.
В браузере:
window.MyLibrary
В strict mode значение this может быть
undefined.
type: 'window'Экспорт в объект window.
library: {
name: 'MyLibrary',
type: 'window'
}
Результат:
window.MyLibrary = ...
Используется только в браузере.
type: 'global'Экспорт в глобальный объект.
library: {
name: 'MyLibrary',
type: 'global'
}
Webpack использует globalThis.
Подходит для:
type: 'commonjs'Экспорт через CommonJS.
library: {
type: 'commonjs'
}
Результат:
exports = ...
Чаще используется в Node.js.
type: 'commonjs2'Наиболее распространённый CommonJS-формат.
library: {
type: 'commonjs2'
}
Результат:
module.exports = ...
Используется большинством npm-пакетов.
type: 'amd'Экспорт через AMD.
library: {
name: 'my-library',
type: 'amd'
}
Результат:
define('my-library', [], factory);
Подходит для:
type: 'umd'Самый популярный режим для библиотек.
library: {
name: 'MyLibrary',
type: 'umd'
}
UMD автоматически определяет среду:
Webpack генерирует универсальную обёртку:
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else
root["MyLibrary"] = factory();
})(self, () => {});
Один bundle работает:
Библиотека может подключаться через <script>:
<script src="my-lib.js"></script>
Модуль можно импортировать:
const lib = require('my-lib');
UMD создаёт:
Для современных приложений чаще используют ES Modules.
type: 'module'output: {
module: true,
library: {
type: 'module'
}
}
Использование:
import { sum } from './my-lib.js';
Нельзя использовать некоторые legacy-возможности Webpack.
ESM позволяет:
Поддерживается:
type: 'jsonp'Редко используемый формат.
library: {
name: 'MyLibrary',
type: 'jsonp'
}
Использует JSONP-обёртку.
Практически не применяется в современных проектах.
type: 'system'Экспорт для SystemJS.
library: {
type: 'system'
}
Используется в некоторых enterprise-проектах и микрофронтендах.
| Тип | Браузер | Node.js | AMD | ESM |
|---|---|---|---|---|
| var | Да | Нет | Нет | Нет |
| window | Да | Нет | Нет | Нет |
| global | Да | Да | Нет | Нет |
| commonjs | Нет | Да | Нет | Нет |
| commonjs2 | Нет | Да | Нет | Нет |
| amd | Да | Нет | Да | Нет |
| umd | Да | Да | Да | Нет |
| module | Да | Да | Нет | Да |
library.exportПозволяет экспортировать конкретную часть модуля.
Исходный код:
export default {
sum,
sub
};
Конфигурация:
library: {
name: 'MathLib',
type: 'umd',
export: 'default'
}
Внешний код получит:
MathLib.sum();
exportЕсли параметр не указан:
library: {
name: 'MathLib',
type: 'umd'
}
Экспортируется весь namespace модуля.
Результат:
MathLib.default.sum();
или
MathLib.sum();
в зависимости от конфигурации transpiler.
Исходный модуль:
export const utils = {
format() {}
};
export const api = {};
Конфигурация:
library: {
name: 'MyLibrary',
type: 'umd',
export: 'utils'
}
Результат:
MyLibrary.format();
Поддерживается массив:
export const tools = {
math: {
sum() {}
}
};
library: {
export: ['tools', 'math']
}
Результат:
MyLibrary.sum();
// src/index.js
export function sum(a, b) {
return a + b;
}
export function sub(a, b) {
return a - b;
}
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'math-lib.js',
library: {
name: 'MathLib',
type: 'umd'
},
clean: true
}
};
<script src="math-lib.js"></script>
<script>
console.log(MathLib.sum(2, 3));
</script>
const MathLib = require('./math-lib');
MathLib.sum(2, 3);
import * as MathLib from './math-lib.js';
MathLib.sum(2, 3);
function sum(a, b) {
return a + b;
}
function sub(a, b) {
return a - b;
}
export default {
sum,
sub
};
library: {
name: 'MathLib',
type: 'umd',
export: 'default'
}
Иногда создают несколько сборок:
module.exports = [
{
output: {
filename: 'lib.umd.js',
library: {
name: 'MyLib',
type: 'umd'
}
}
},
{
output: {
filename: 'lib.esm.js',
module: true,
library: {
type: 'module'
}
}
}
];
Типичная структура:
{
"main": "dist/lib.cjs.js",
"module": "dist/lib.esm.js",
"browser": "dist/lib.umd.js"
}
output.moduleДля library.type = 'module' требуется:
output: {
module: true
}
И дополнительно:
experiments: {
outputModule: true
}
Полный пример:
module.exports = {
experiments: {
outputModule: true
},
output: {
module: true,
library: {
type: 'module'
}
}
};
Webpack может удалять неиспользуемые части библиотеки.
Важно:
{
"sideEffects": false
}
Babel может изменять структуру export/import.
Например:
exports.default = ...
В результате приходится использовать:
MyLib.default.method();
Для исправления используют:
library: {
export: 'default'
}
library.nameОшибка:
library: {
type: 'window'
}
Webpack не знает имя глобальной переменной.
Правильно:
library: {
name: 'MyLib',
type: 'window'
}
window в Node.jsОшибка:
type: 'window'
в серверной среде.
Следствие:
ReferenceError: window is not defined
Проблема:
type: 'var'
npm-пакет не работает через require().
Для npm лучше:
type: 'commonjs2'
или:
type: 'umd'
Проблема:
name: 'Utils'
Глобальная переменная уже существует.
Следствие:
Рекомендуется:
type: 'umd'
или:
type: 'module'
Предпочтителен ESM:
type: 'module'
Подходит:
type: 'umd'
Лучший вариант:
type: 'commonjs2'
| Сценарий | Рекомендуемый тип |
|---|---|
| npm package | umd / module |
| Browser CDN | umd |
| Node.js | commonjs2 |
| Modern frontend | module |
| Legacy browser | umd |
| RequireJS | amd |
| Global utility | window |
Большинство современных библиотек публикуют:
Пример:
dist/
├── library.esm.js
├── library.cjs.js
└── library.umd.js
Это обеспечивает: