Spec-Zone.ru › webpack 5

Внешние зависимости

Параметр конфигурации externals предоставляет способ исключения зависимостей из выходных пакетов. Вместо этого создаваемый пакет полагается на то, что эта зависимость присутствует в среде потребителя (любого приложения-пользователя). Эта функция обычно наиболее полезна для разработчиков библиотек, однако у неё есть множество применений.

внешние зависимости

string object function RegExp [string, object, function, RegExp]

Предотвратить объединение определенных import пакетов и вместо этого извлечь эти внешние зависимости во время выполнения.

Например, чтобы включить jQuery с CDN вместо объединения:

index.html

<script
  src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous"
></script>

webpack.config.js

module.exports = {
  //...
  externals: {
    jquery: 'jQuery',
  },
};

Это оставляет любые зависимые модули неизменными, т.е. приведенный ниже код по-прежнему будет работать:

import $ from 'jquery';

$('.my-element').animate(/* ... */);

Имя свойства jquery , указанное в externals в вышеупомянутом webpack.config.js, указывает, что модуль jquery в import $ from 'jquery' должен быть исключён из объединения. Для замены этого модуля будет использовано значение jQuery, для получения глобальной jQuery переменной, так как тип внешней библиотеки по умолчанию — var, см. externalsType.

Хотя мы показали пример использования внешней глобальной переменной выше, внешняя зависимость может быть доступна в любом из этих форматов: глобальная переменная, CommonJS, AMD, ES2015 Module, см. больше в externalsType.

строка

В зависимости от externalsType, это может быть имя глобальной переменной (см. 'global', 'this', 'var', 'window') или имя модуля (см. amd, commonjs, module, umd).

Также можно использовать сокращённый синтаксис, если определена только 1 внешняя зависимость:

module.exports = {
  //...
  externals: 'jquery',
};

равно

module.exports = {
  //...
  externals: {
    jquery: 'jquery',
  },
};

Вы можете указать тип внешней библиотеки внешней библиотеки для внешней зависимости с помощью синтаксиса ${externalsType} ${libraryName}. Он переопределит тип внешней библиотеки по умолчанию, указанный в параметре externalsType.

Например, если внешняя библиотека — модуль CommonJS, вы можете указать

module.exports = {
  //...
  externals: {
    jquery: 'commonjs jquery',
  },
};

[строка]

module.exports = {
  //...
  externals: {
    subtract: ['./math', 'subtract'],
  },
};

subtract: ['./math', 'subtract'] позволяет выбрать часть модуля, где ./math — это модуль, и ваш пакет требует только подмножества под переменной subtract.

Когда externalsType равно commonjs, этот пример переводится в require('./math').subtract;, а когда externalsType равно window, этот пример переводится в window["./math"]["subtract"];

Аналогично синтаксису строки, вы можете указать тип внешней библиотеки с помощью синтаксиса ${externalsType} ${libraryName}, в первом элементе массива, например:

module.exports = {
  //...
  externals: {
    subtract: ['commonjs ./math', 'subtract'],
  },
};

объект

предупреждение

Объект с { root, amd, commonjs, ... } разрешен только для libraryTarget: 'umd' и externalsType: 'umd'. Он не разрешен для других целей библиотек.

module.exports = {
  //...
  externals: {
    react: 'react',
  },

  // or

  externals: {
    lodash: {
      commonjs: 'lodash',
      amd: 'lodash',
      root: '_', // indicates global variable
    },
  },

  // or

  externals: {
    subtract: {
      root: ['math', 'subtract'],
    },
  },
};

Этот синтаксис используется для описания всех возможных способов доступности внешней библиотеки. lodash здесь доступен как lodash в системах модулей AMD и CommonJS, но доступен как _ в форме глобальной переменной. subtract здесь доступен через свойство subtract в глобальном объекте math (например, window['math']['subtract']).

функция

  • function ({ context, request, contextInfo, getResolve }, callback)
  • function ({ context, request, contextInfo, getResolve }) => promise 5.15.0+

Может быть полезно определить собственную функцию для управления поведением того, что вы хотите внешне экспортировать из webpack. webpack-node-externals, например, исключает все модули из каталога node_modules и предоставляет параметры для разрешения пакетов.

Вот аргументы, которые может получить функция:

  • ctx (object): Объект, содержащий детали файла.
    • ctx.context (string): Каталог файла, содержащего импорт.
    • ctx.request (string): Запрашиваемый путь импорта.
    • ctx.contextInfo (object): Содержит информацию о передатчике (например, слое и компиляторе)
    • ctx.getResolve 5.15.0+: Получить функцию разрешения с текущими параметрами разрешения.
  • callback (function (err, result, type)): Функция обратного вызова, используемая для указания, как модуль должен быть экспортирован.

Функция обратного вызова принимает три аргумента:

  • err (Error): Используется для указания наличия ошибки при экспорте импорта. При возникновении ошибки этот параметр должен быть единственным используемым.
  • result (string [string] object): Описывает внешний модуль с другими форматами внешних зависимостей (string, [string] или object)
  • type (string): Необязательный параметр, указывающий тип внешней зависимости модуля external type (если он не был уже указан в параметре result).

В качестве примера, чтобы экспортировать все импорты, где путь импорта соответствует регулярному выражению, можно сделать следующее:

webpack.config.js

module.exports = {
  //...
  externals: [
    function ({ context, request }, callback) {
      if (/^yourregex$/.test(request)) {
        // Externalize to a commonjs module using the request path
        return callback(null, 'commonjs ' + request);
      }

      // Continue without externalizing the import
      callback();
    },
  ],
};

Другие примеры с использованием различных форматов модулей:

webpack.config.js

module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a `commonjs2` module located in `@scope/library`
      callback(null, '@scope/library', 'commonjs2');
    },
  ],
};

webpack.config.js

module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a global variable called `nameOfGlobal`.
      callback(null, 'nameOfGlobal');
    },
  ],
};

webpack.config.js

module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a named export in the `@scope/library` module.
      callback(null, ['@scope/library', 'namedexport'], 'commonjs');
    },
  ],
};

webpack.config.js

module.exports = {
  externals: [
    function (ctx, callback) {
      // The external is a UMD module
      callback(null, {
        root: 'componentsGlobal',
        commonjs: '@scope/components',
        commonjs2: '@scope/components',
        amd: 'components',
      });
    },
  ],
};

RegExp

Каждая зависимость, соответствующая заданному регулярному выражению, будет исключена из выходных пакетов.

webpack.config.js

module.exports = {
  //...
  externals: /^(jquery|\$)$/i,
};

В этом случае любая зависимость с именем jQuery, заглавными или строчными буквами, или $ будет экспортирована.

Комбинирование синтаксисов

Иногда вам может потребоваться использовать комбинацию вышеперечисленных синтаксисов. Это можно сделать следующим образом:

webpack.config.js

module.exports = {
  //...
  externals: [
    {
      // String
      react: 'react',
      // Object
      lodash: {
        commonjs: 'lodash',
        amd: 'lodash',
        root: '_', // indicates global variable
      },
      // [string]
      subtract: ['./math', 'subtract'],
    },
    // Function
    function ({ context, request }, callback) {
      if (/^yourregex$/.test(request)) {
        return callback(null, 'commonjs ' + request);
      }
      callback();
    },
    // Regex
    /^(jquery|\$)$/i,
  ],
};
предупреждение

Тип по умолчанию будет использован, если вы укажете externals без типа, например, externals: { react: 'react' } вместо externals: { react: 'commonjs-module react' }.

Для получения дополнительной информации о том, как использовать эту конфигурацию, обратитесь к статье как создать библиотеку.

byLayer

function object

Укажите внешние зависимости по слоям.

webpack.config.js

module.exports = {
  externals: {
    byLayer: {
      layer: {
        external1: 'var 43',
      },
    },
  },
};

externalsType

string = 'var'

Укажите тип внешних зависимостей по умолчанию. amd, umd, system и jsonp внешние зависимости зависит от output.libraryTarget, установленного в то же значение, т.е. вы можете использовать amd внешние зависимости только в библиотеке amd.

Поддерживаемые типы:

  • 'amd'
  • 'amd-require'
  • 'assign' - то же, что и 'var'
  • 'commonjs'
  • 'commonjs-module'
  • 'global'
  • 'import' - использует import() для загрузки модуля EcmaScript (асинхронный модуль)
  • 'jsonp'
  • 'module'
  • 'import'
  • 'module-import'
  • 'node-commonjs'
  • 'promise' - то же, что и 'var' , но ожидает результата (асинхронный модуль)
  • 'self'
  • 'system'
  • 'script'
  • 'this'
  • 'umd'
  • 'umd2'
  • 'var'
  • 'window'

webpack.config.js

module.exports = {
  //...
  externalsType: 'promise',
};

externalsType.commonjs

Укажите тип внешних зависимостей по умолчанию как 'commonjs'. Webpack сгенерирует код вроде const X = require('...') для внешних зависимостей, используемых в модуле.

Пример

import fs from 'fs-extra';

webpack.config.js

module.exports = {
  // ...
  externalsType: 'commonjs',
  externals: {
    'fs-extra': 'fs-extra',
  },
};

Сгенерирует что-то вроде:

const fs = require('fs-extra');

Обратите внимание, что в выходном пакете будет require().

externalsType.global

Укажите тип внешних зависимостей по умолчанию как 'global'. Webpack будет читать внешнюю зависимость как глобальную переменную в globalObject.

Пример

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'global',
  externals: {
    jquery: '$',
  },
  output: {
    globalObject: 'global',
  },
};

Сгенерирует что-то вроде

const jq = global['$'];
jq('.my-element').animate(/* ... */);

externalsType.module

Укажите тип внешних зависимостей по умолчанию как 'module'. Webpack сгенерирует код вроде import * as X from '...' для внешних зависимостей, используемых в модуле.

Убедитесь, что вы сначала включили experiments.outputModule, иначе webpack выдаст ошибки.

Пример

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  experiments: {
    outputModule: true,
  },
  externalsType: 'module',
  externals: {
    jquery: 'jquery',
  },
};

Сгенерирует что-то вроде

import * as __WEBPACK_EXTERNAL_MODULE_jquery__ from 'jquery';

const jq = __WEBPACK_EXTERNAL_MODULE_jquery__['default'];
jq('.my-element').animate(/* ... */);

Обратите внимание, что в выходном пакете будет инструкция import.

externalsType.import

5.94.0+

Укажите тип внешних зависимостей по умолчанию как 'import'. Webpack сгенерирует код вроде import('...') для внешних зависимостей, используемых в модуле.

Пример

async function foo() {
  const jq = await import('jQuery');
  jq('.my-element').animate(/* ... */);
}

webpack.config.js

module.exports = {
  externalsType: 'import',
  externals: {
    jquery: 'jquery',
  },
};

Сгенерирует что-то вроде нижеследующего:

var __webpack_modules__ = {
  jQuery: (module) => {
    module.exports = import('jQuery');
  },
};

// webpack runtime...

async function foo() {
  const jq = await Promise.resolve(/* import() */).then(
    __webpack_require__.bind(__webpack_require__, 'jQuery')
  );
  jq('.my-element').animate(/* ... */);
}

Обратите внимание, что выходной пакет будет содержать инструкцию import().

externalsType.module-import

5.94.0+

Укажите тип внешних зависимостей по умолчанию как 'module-import'. Это объединяет 'module' и 'import'. Webpack автоматически определит тип синтаксиса импорта, установив его в 'module' для статических импортов и 'import' для динамических импортов.

Убедитесь, что вы сначала включили experiments.outputModule, если существуют статические импорты, в противном случае webpack выдаст ошибки.

Пример

import { attempt } from 'lodash';

async function foo() {
  const jq = await import('jQuery');
  attempt(() => jq('.my-element').animate(/* ... */));
}

webpack.config.js

module.exports = {
  externalsType: 'import',
  externals: {
    jquery: 'jquery',
  },
};

Сгенерирует что-то вроде следующего:

import * as __WEBPACK_EXTERNAL_MODULE_lodash__ from 'lodash';
const lodash = __WEBPACK_EXTERNAL_MODULE_jquery__;

var __webpack_modules__ = {
  jQuery: (module) => {
    module.exports = import('jQuery');
  },
};

// webpack runtime...

async function foo() {
  const jq = await Promise.resolve(/* import() */).then(
    __webpack_require__.bind(__webpack_require__, 'jQuery')
  );
  (0, lodash.attempt)(() => jq('.my-element').animate(/* ... */));
}

Обратите внимание, что выходной пакет будет содержать оператор import или import().

Когда модуль не импортирован с помощью import или import(), webpack будет использовать тип "module" externals в качестве резервного варианта. Если вы хотите использовать другой тип externals в качестве резервного, вы можете указать его с помощью функции в опции externals. Например:

module.exports = {
  externalsType: "module-import",
  externals: [
    function (
      { request, dependencyType },
      callback
    ) {
      if (dependencyType === "commonjs") {
        return callback(null, `node-commonjs ${request}`);
      }
      callback();
    },
  ]

externalsType.node-commonjs

Укажите тип externals по умолчанию как 'node-commonjs'. Webpack импортирует createRequire из 'module', чтобы создать функцию require для загрузки внешних зависимостей, используемых в модуле.

Пример

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.export = {
  experiments: {
    outputModule: true,
  },
  externalsType: 'node-commonjs',
  externals: {
    jquery: 'jquery',
  },
};

Будет сгенерировано что-то вроде

import { createRequire } from 'module';

const jq = createRequire(import.meta.url)('jquery');
jq('.my-element').animate(/* ... */);

Обратите внимание, что в выходном пакете будет оператор import.

Это полезно, когда зависимости полагаются на встроенные модули Node.js или требуют функцию require типа CommonJS для сохранения прототипов, что необходимо для функций, таких как util.inherits. Подробнее см. данный вопрос.

Для кода, который полагается на структуры прототипов, такие как:

function ChunkStream() {
  Stream.call(this);
}
util.inherits(ChunkStream, Stream);

Вы можете использовать node-commonjs для обеспечения сохранения цепочки прототипов:

const { builtinModules } = require('module');

module.exports = {
  experiments: { outputModule: true },
  externalsType: 'node-commonjs',
  externals: ({ request }, callback) => {
    if (/^node:/.test(request) || builtinModules.includes(request)) {
      return callback(null, 'node-commonjs ' + request);
    }
    callback();
  },
};

Это приводит к результату примерно такого вида:

import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "node:module";
// ...
/***/ 2613:
/***/ ((module) => {

module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("stream");

/***/ }),

Эта настройка сохраняет структуру прототипов, устраняя проблемы со встроенными модулями Node.js.

externalsType.promise

Укажите тип externals по умолчанию как 'promise'. Webpack прочитает внешнюю зависимость как глобальную переменную (аналогично 'var') и await её.

Пример

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'promise',
  externals: {
    jquery: '$',
  },
};

Будет сгенерировано что-то вроде

const jq = await $;
jq('.my-element').animate(/* ... */);

externalsType.self

Укажите тип externals по умолчанию как 'self'. Webpack прочитает внешнюю зависимость как глобальную переменную объекта self.

Пример

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'self',
  externals: {
    jquery: '$',
  },
};

Будет сгенерировано что-то вроде

const jq = self['$'];
jq('.my-element').animate(/* ... */);

externalsType.script

Укажите тип externals по умолчанию как 'script'. Webpack загрузит внешнюю зависимость как скрипт, экспонирующий предварительно определённые глобальные переменные с помощью HTML-элемента <script>. Тег <script> будет удалён после загрузки скрипта.

Синтаксис

module.exports = {
  externalsType: 'script',
  externals: {
    packageName: [
      'http://example.com/script.js',
      'global',
      'property',
      'property',
    ], // properties are optional
  },
};

Вы также можете использовать сокращённый синтаксис, если не собираетесь указывать какие-либо свойства:

module.exports = {
  externalsType: 'script',
  externals: {
    packageName: 'global@http://example.com/script.js', // no properties here
  },
};

Обратите внимание, что output.publicPath не будет добавлен к предоставленному URL.

Пример

Загрузим lodash с CDN:

webpack.config.js

module.exports = {
  // ...
  externalsType: 'script',
  externals: {
    lodash: ['https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js', '_'],
  },
};

Затем используем его в коде:

import _ from 'lodash';
console.log(_.head([1, 2, 3]));

Вот как мы задаём свойства для вышеприведённого примера:

module.exports = {
  // ...
  externalsType: 'script',
  externals: {
    lodash: [
      'https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js',
      '_',
      'head',
    ],
  },
};

Обе локальные переменные head и глобальные window._ будут экспортированы, когда вы import lodash.

import head from 'lodash';
console.log(head([1, 2, 3])); // logs 1 here
console.log(window._.head(['a', 'b'])); // logs a here
Подсказка

При загрузке кода с помощью HTML-тегов <script>, загрузчик webpack попытается найти существующий тег <script>, который соответствует атрибуту src или имеет определённый атрибут data-webpack. Для загрузки фрагментов атрибут data-webpack будет иметь значение '[output.uniqueName]:chunk-[chunkId]', в то время как для внешнего скрипта значение '[output.uniqueName]:[global]'.

Подсказка

Настройки, такие как output.chunkLoadTimeout, output.crossOriginLoading и output.scriptType, также будут влиять на внешние скрипты, загруженные таким образом.

externalsType.this

Укажите тип externals по умолчанию как 'this'. Webpack прочитает внешнюю зависимость как глобальную переменную объекта this.

Пример

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'this',
  externals: {
    jquery: '$',
  },
};

Будет сгенерировано что-то вроде

const jq = this['$'];
jq('.my-element').animate(/* ... */);

externalsType.var

Укажите тип externals по умолчанию как 'var'. Webpack прочитает внешнюю зависимость как глобальную переменную.

Пример

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'var',
  externals: {
    jquery: '$',
  },
};

Будет сгенерировано что-то вроде

const jq = $;
jq('.my-element').animate(/* ... */);

externalsType.window

Укажите тип externals по умолчанию как 'window'. Webpack прочитает внешнюю зависимость как глобальную переменную объекта window.

Пример

import jq from 'jquery';
jq('.my-element').animate(/* ... */);

webpack.config.js

module.exports = {
  // ...
  externalsType: 'window',
  externals: {
    jquery: '$',
  },
};

Будет сгенерировано что-то вроде

const jq = window['$'];
jq('.my-element').animate(/* ... */);

externalsPresets

object

Включить наборы предварительных настроек для внешних зависимостей для определённых целей.

Опция Описание Тип ввода
electron Обрабатывает распространённые встроенные модули электронных приложений в контекстах main и preload, такие как electron, ipc или shell, как внешние зависимости и загружает их с помощью require() при использовании. boolean
electronMain Обрабатывает встроенные модули электронных приложений в контексте main, такие как app, ipc-main или shell, как внешние зависимости и загружает их с помощью require() при использовании. boolean
electronPreload Обрабатывает встроенные модули электронных приложений в контексте preload, такие как web-frame, ipc-renderer или shell, как внешние зависимости и загружает их с помощью require() при использовании. boolean
electronRenderer Обрабатывает встроенные модули электронных приложений в контексте renderer, такие как web-frame, ipc-renderer или shell, как внешние зависимости и загружает их с помощью require() при использовании. boolean
node Обрабатывает встроенные модули node.js, такие как fs, path или vm, как внешние зависимости и загружает их с помощью require() при использовании. boolean
nwjs Обрабатывает устаревший модуль NW.js nw.gui как внешнюю зависимость и загружает его с помощью require() при использовании. boolean
web Обрабатывает ссылки на http(s)://... и std:... как внешние зависимости и загружает их с помощью import при использовании. (Обратите внимание, что это меняет порядок выполнения, так как внешние зависимости выполняются до любого другого кода в фрагменте). boolean
webAsync Обрабатывает ссылки на http(s)://... и std:... как внешние зависимости и загружает их с помощью async import() при использовании. (Обратите внимание, что этот тип внешней зависимости — это модуль async, который оказывает различное влияние на выполнение). boolean

Обратите внимание, что если вы собираетесь выводить ES Модули с этими наборами предварительных настроек, связанных с node.js, webpack установит тип externals по умолчанию в node-commonjs, который будет использовать createRequire для построения функции require вместо require().

Пример

Использование набора предварительных настроек node не будет включать встроенные модули, обрабатывает их как внешние зависимости и загружает их с помощью require() при использовании.

webpack.config.js

module.exports = {
  // ...
  externalsPresets: {
    node: true,
  },
};

© JS Foundation and other contributors
Licensed under the Creative Commons Attribution License 4.0.
https://webpack.js.org/configuration/externals

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API