Esbuild предоставляет механизм external, позволяющий
исключать определённые зависимости из процесса бандлинга и оставлять их
в виде импортов в итоговом коде. Эта опция критична при сборке
библиотек, работе с внешними зависимостями, интеграции с CDN и
управлении peer-dependencies.
При стандартной сборке esbuild анализирует граф импортов и стремится инлайнить все найденные модули внутрь результирующего бандла. Это поведение не всегда желательно: некоторые зависимости должны оставаться внешними и резолвиться в окружении выполнения.
Опция external изменяет поведение резолвера: указанные
модули исключаются из графа бандлинга и сохраняются как
import или require в выходном файле.
Ключевая особенность:
external не удаляет импорт — он запрещает его обработку как внутренней зависимости сборки.
import esbuild from 'esbuild';
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
external: ['react', 'react-dom']
});
В этом примере react и react-dom не попадут
в бандл, а останутся внешними зависимостями.
esbuild src/index.js --bundle --outfile=dist/bundle.js --external:react --external:react-dom
CLI-форма использует префикс --external: для каждого
пакета.
При использовании external esbuild:
Пример:
import React from 'react';
import { createRoot } from 'react-dom/client';
console.log(React.version);
При external: ['react'] результат будет:
import React from 'react';
import { createRoot } from 'react-dom/client';
console.log(React.version);
react не инлайнится, но импорт остаётся.
Один из наиболее распространённых сценариев — библиотеки.
package.json:
{
"peerDependencies": {
"react": "^18.0.0"
}
}
Сборка библиотеки:
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/index.js',
external: ['react']
});
Смысл:
Часто требуется исключить все зависимости из
node_modules.
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/bundle.js',
external: [/node_modules/]
});
Однако более корректный и распространённый подход:
external: ['*']
или более точечно:
external: ['react', 'react-dom', 'lodash']
Практика массового исключения должна учитывать, что чрезмерное использование снижает пользу бандлинга как инструмента доставки зависимостей.
При сборке под Node.js часто требуется сохранить встроенные модули:
esbuild.build({
entryPoints: ['src/server.js'],
bundle: true,
platform: 'node',
outfile: 'dist/server.js',
external: ['fs', 'path', 'http']
});
Хотя platform: 'node' уже автоматически помечает
встроенные модули как внешние, явное указание используется для контроля
поведения в сложных конфигурациях.
В браузерных сборках external используется для:
external: ['jquery']
В результате:
import $ from 'jquery';
Остаётся как есть и предполагается глобальная загрузка
jquery.
Используется для сохранения require() или
import на уровне рантайма.
external: ['@company/*']
Используется для монорепозиториев, где пакеты поставляются отдельно.
external: [
'react',
'react-dom',
/^@internal\//
]
Позволяет комбинировать точечные и групповые исключения.
При сборке библиотеки для браузера:
esbuild.build({
entryPoints: ['src/widget.js'],
bundle: true,
format: 'esm',
outfile: 'dist/widget.js',
external: ['vue']
});
Ожидается, что Vue загружается отдельно:
<script src="https://unpkg.com/vue@3"></script>
external полностью исключает модуль из анализа графа:
Это важный поведенческий момент: external — это граница оптимизации.
| Механизм | Поведение |
|---|---|
| external | исключает модуль из сборки |
| alias | заменяет путь на другой |
| resolve | управляет поиском модуля |
external не заменяет модуль, а полностью выводит его за пределы процесса сборки.
external: ['react']
Ожидание: React исчезнет из результата.
Фактическое поведение: React остаётся импортом.
external: ['*']
Результат: бандл перестаёт быть самодостаточным, теряется смысл сборки для фронтенда.
При смешанных форматах может возникнуть ситуация, когда external приводит к несовместимым импортам в разных окружениях.
Использование external определяется архитектурной ролью модуля:
import React from 'react';
const React = require('react');
external сохраняет синтаксис в зависимости от format, но
не изменяет факт исключения из бандла.
external в esbuild — это механизм декларативного
управления границами сборки. Он определяет, какие зависимости
принадлежат текущему артефакту, а какие остаются ответственностью
внешней среды выполнения, формируя чёткое разделение между компиляцией и
рантаймом.