Опция packages: "external" управляет тем, как сборщик
обрабатывает зависимости из node_modules. При её активации
все пакеты, установленные через npm/yarn/pnpm, перестают встраиваться в
итоговый бандл и вместо этого остаются внешними импортами, которые будут
разрешаться во время выполнения.
Ключевая идея: сборщик перестаёт «впитывать» зависимости и превращает их в ссылки на рантайм-окружение Node.js или другого загрузчика модулей.
externalВ стандартной конфигурации esbuild пытается собрать зависимости в один или несколько файлов. Это означает:
node_modules могут попасть внутрь
бандла;При использовании:
packages: "external"
происходит иная модель:
node_modules остаётся импортом;require("lodash") или import "lodash".Если в коде есть:
import express from "express";
import lodash from "lodash";
После сборки с packages: "external" результат будет
концептуально таким:
import express from "express";
import lodash from "lodash";
Но уже в контексте скомпилированного файла (например, CommonJS или ESM), без внедрения исходников этих библиотек.
Важно: esbuild не удаляет импорты, а меняет стратегию их обработки.
externalВ esbuild существует также поле:
external: []
Оно работает точечно: разработчик вручную перечисляет пакеты, которые не нужно бандлить.
Пример:
external: ["react", "react-dom"]
Это означает:
packages: "external" — глобальная стратегия:
node_modules.Наиболее частый кейс:
node_modules доступны;В этом случае сборка превращается в транспиляцию:
// исходник
import db from "database-lib";
// результат
import db from "database-lib";
Иногда используется обратная стратегия — полное бандлирование. Однако
packages: "external" полезна, если:
В монорепо с workspace-зависимостями:
Использование packages: "external" приводит к:
node_modules.Но важно понимать:
node_modules.import "chalk";
Остаётся без изменений, но не инлайнится.
const chalk = require("chalk");
Также сохраняется как внешний require.
esbuild src/index.js --bundle --packages=external --outfile=dist/bundle.js
Эта команда:
node_modules внешними;platformОпция packages: "external" часто используется вместе
с:
platform: "node"
Совместное поведение:
node — включает Node.js-специфику;packages: "external" — сохраняет внешние
зависимости.Tree-shaking внутри сторонних библиотек фактически отключается:
node_modules;Если пакет не установлен в runtime:
Error: Cannot find module 'some-package'
node_modules.Для браузера эта стратегия обычно неприемлема:
node_modules недоступны;external паттернамиИногда используется гибрид:
external: ["react", "react-dom"],
packages: "external"
Логика:
При packages: "external" esbuild превращается из
полноценного бандлера в:
Это особенно заметно в архитектурах, где:
node_modules устанавливаются отдельно;import("express").then(mod => {
mod.default();
});
При external-режиме:
При использовании с TypeScript:
.ts файлы компилируются как обычно;import type { Request } from "express";
Типовой импорт исчезает, но runtime-пакет остаётся внешним.
import esbuild from "esbuild";
esbuild.build({
entryPoints: ["src/index.ts"],
bundle: true,
platform: "node",
packages: "external",
outfile: "dist/index.js"
});
Такой подход фиксирует:
node_modules;Использование packages: "external" фактически делит
систему на две части:
Это меняет характер сборки: