Webpack ProvidePlugin проти зовнішніх?


84

Я досліджую ідею використання Webpack з Backbone.js .

Я дотримувався короткого керівництва і маю загальне уявлення про те, як працює Webpack, але мені незрозуміло, як завантажувати бібліотеку залежностей, таку як jquery / backbone / underscore.

Чи слід їх завантажувати зовні, <script>або це щось Webpack може впоратись, як шим RequireJS?

Згідно з веб- пакетом doc: модулі , що обробляються , ProvidePluginі, externalsсхоже, пов’язані з цим (так само bundle!десь завантажувач), але я не можу зрозуміти, коли використовувати які.

Дякую

Відповіді:


153

Можливо і те, і інше: Ви можете включити бібліотеки з <script>(тобто використовувати бібліотеку з CDN) або включити їх у згенерований пакет.

Якщо ви завантажуєте його через <script>тег, ви можете використовувати externalsопцію, щоб дозволити писати require(...)у своїх модулях.

Приклад з бібліотекою з CDN:

<script src="https://code.jquery.com/jquery-git2.min.js"></script>

// the artifial module "jquery" exports the global var "jQuery"
externals: { jquery: "jQuery" }

// inside any module
var $ = require("jquery");

Приклад з бібліотекою, що входить до комплекту:

copy `jquery-git2.min.js` to your local filesystem

// make "jquery" resolve to your local copy of the library
// i. e. through the resolve.alias option
resolve: { alias: { jquery: "/path/to/jquery-git2.min.js" } }

// inside any module
var $ = require("jquery");

Ви ProvidePluginможете зіставити модулі з (вільними) змінними. Таким чином , ви можете визначити: «Кожен раз , коли я використовую (безкоштовно) змінний xyzвсередині модуля ви (WebPack) слід встановити xyzв require("abc")

Приклад без ProvidePlugin:

// You need to require underscore before you can use it
var _ = require("underscore");
_.size(...);

Приклад з ProvidePlugin:

plugins: [
  new webpack.ProvidePlugin({
    "_": "underscore"
  }) 
]

// If you use "_", underscore is automatically required
_.size(...)

Короткий зміст:

  • Бібліотека з CDN: Використовуйте <script>тег та externalsпараметр
  • Бібліотека з файлової системи: включіть бібліотеку в комплект. (Можливо, змінити resolveпараметри, щоб знайти бібліотеку)
  • externals: Зробити глобальні вари доступними як модуль
  • ProvidePlugin: Зробіть модулі доступними як вільні змінні всередині модулів

Потрібно додати newперед webpack.ProvidePlugin webpack.github.io/docs/list-of-plugins.html
MK Yung

Чому б просто не використовувати скрипт-завантажувач? Це набагато простіше, як пояснював
@dtothefp

Якщо мій файл webpack.config знаходиться в папці під назвою javascript, і всередині нього є папка з назвою vendor з моїм файлом jquery. якщо шлях не повинен бути. вирішення: {псевдонім: {jquery: "vendor / jquery-1.10.2.js"}}. Мені все одно не вдається використовувати псевдонім
me-me

3
Просто пройдіть абсолютний шлях до варіанту псевдоніма. Якщо ви передаєте відносний шлях, це відносно місця розташування require / import у webpack 1. У webpack 2 це відносно файлу webpack.config.js, відповідно. варіант контексту.
Тобіас К.

@TobiasK. Абсолютний шлях не співпрацює з експортом за замовчуванням. Я отримую об’єкт, {__esModule: true, default: MY_DEFAULT_EXPORT}а не MY_DEFAULT_EXPORTу файлах.
mgol

25

Щось здорово відзначити, це те, що якщо ви використовуєте ProvidePluginв поєднанні з externalsвластивістю, це дозволить вам перейти jQueryдо закриття модуля вашого веб-пакета без необхідності явно requireце робити . Це може бути корисно для рефакторингу застарілого коду з великою кількістю різних посилань на файли $.

//webpack.config.js
module.exports = {
  entry: './index.js',
  output: { 
    filename: '[name].js' 
  },
  externals: {
    jquery: 'jQuery'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
    })
  ]
};

тепер у index.js

console.log(typeof $ === 'function');

матиме скомпільований вивід із таким, як показано нижче, переданим у webpackBootstrapзакриття:

/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    /* WEBPACK VAR INJECTION */(function($) {
        console.log(typeof $ === 'function');

    /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

    module.exports = jQuery;

/***/ }
/******/ ])

Таким чином, ви можете бачити, що $посилання на глобальний / вікно jQueryз CDN, але передається в закриття. Я не впевнений, що це призначена функціональність чи щасливий хак, але, здається, це добре працює для мого випадку використання.


вам не знадобився жоден плагін, якщо ви не збираєтесь на require/importнього. $просто спрацював би, бо, незважаючи ні на що, він досягне глобального масштабу. ProviderPluginВимагає розбору AST , так це дорогий плагін і додати в свій час збирання помітно. Отже, це в основному марнотратство.
faceyspacey.com

@dtohefp ця відповідь є знахідкою. Чи можете ви пояснити, чому ProvidePluginповернув такий об’єкт, myModule.defaultякби я не додав модуль до зовнішніх? Я ніколи не знав, що будуть якісь прямі стосунки.
Slbox

11

Я знаю, що це стара публікація, але вважаю, що було б корисно згадати, що завантажувач сценаріїв webpack може бути корисним і в цьому випадку. З документів webpack:

"скрипт: виконує файл JavaScript один раз у глобальному контексті (наприклад, у тезі сценарію), вимагає, щоб не був проаналізований."

http://webpack.github.io/docs/list-of-loaders.html

https://github.com/webpack/script-loader

Я вважаю це особливо корисним при міграції старих процесів збірки, які поєднують файли постачальників JS та файли програм разом. Словом попередження є те, що завантажувач сценаріїв, здається, працює лише через перевантаження require()і не працює, наскільки я можу зрозуміти, вказаний у файлі webpack.config. Хоча багато хто стверджує, що перевантаження requireє поганою практикою, це може бути дуже корисним для об'єднання сценарію постачальника та програми в одному наборі, і одночасно викриваючи JS Globals, які не потрібно перетворювати на додаткові пакети веб-пакетів. Наприклад:

require('script!jquery-cookie/jquery.cookie');
require('script!history.js/scripts/bundled-uncompressed/html4+html5/jquery.history');
require('script!momentjs');

require('./scripts/main.js');

Це зробить $ .cookie, History та moment глобально доступними всередині та за межами цього набору, та об’єднає ці бібліотеки постачальників із скриптом main.js та всіма його requireфайлами d.

Також корисно з цією технікою:

resolve: {
  extensions: ["", ".js"],
  modulesDirectories: ['node_modules', 'bower_components']
},
plugins: [
  new webpack.ResolverPlugin(
    new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
   )
]

який використовує Bower, перегляне mainфайл у кожній required бібліотеці package.json. У наведеному вище прикладі у History.js не mainвказано файл, тому шлях до нього необхідний.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.