Webpack ProvidePlugin a zewnętrzne?


84

Badam pomysł wykorzystania Webpack z Backbone.js .

Postępowałem zgodnie z przewodnikiem szybkiego startu i mam ogólne pojęcie o tym, jak działa Webpack, ale nie jestem pewien, jak załadować bibliotekę zależności, taką jak jquery / backbone / underscore.

Czy powinny być ładowane zewnętrznie, <script>czy jest to coś, co Webpack może obsługiwać, jak podkładka RequireJS?

Według doc WebPACK: podkładek modułów , ProvidePlugini externalswydają się być podobne do tego (tak jest bundle!ładowarka gdzieś), ale nie mogę dowiedzieć się, kiedy używać które.

Dzięki

Odpowiedzi:


153

Jest to możliwe: możesz dołączyć biblioteki za pomocą <script>(tj. Użyć biblioteki z CDN) lub dołączyć je do wygenerowanego pakietu.

Jeśli załadujesz go za pomocą <script>tagu, możesz użyć externalsopcji, aby zezwolić na zapis require(...)w swoich modułach.

Przykład z biblioteką z 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");

Przykład z biblioteką zawartą w pakiecie:

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");

ProvidePluginMoże odwzorowywać moduły do (wolnych) zmiennych. Tak można określić: „Za każdym razem używam (bezpłatny) zmienną xyzwewnątrz modułu, który (WebPack) należy ustawić xyzna require("abc")”.

Przykład bez ProvidePlugin:

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

Przykład z ProvidePlugin:

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

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

Podsumowanie:

  • Biblioteka z CDN: użyj <script>tagu i externalsopcji
  • Biblioteka z systemu plików: dołącz bibliotekę do pakietu. (Może zmodyfikuj resolveopcje, aby znaleźć bibliotekę)
  • externals: Udostępnij zmienne globalne jako moduł
  • ProvidePlugin: Udostępnij moduły jako wolne zmienne wewnątrz modułów

Należy dodać newprzed webpack.ProvidePlugin webpack.github.io/docs/list-of-plugins.html
— MK Yung

Dlaczego po prostu nie użyć programu ładującego skrypt? Jest to znacznie łatwiejsze, jak wyjaśnił
— @dtothefp

Jeśli mój plik webpack.config znajduje się w folderze o nazwie javascript, a wewnątrz niego znajduje się folder o nazwie vendor z moim plikiem jquery. czy ścieżka nie powinna być. rozwiąż: {alias: {jquery: "vendor / jquery-1.10.2.js"}}. Nadal nie działa dla mnie przy użyciu aliasu
— me-me

3
Po prostu podaj bezwzględną ścieżkę do opcji aliasu. Jeśli podasz ścieżkę względną, jest ona względna w stosunku do lokalizacji wymagania / importu w pakiecie internetowym 1. W pakiecie internetowym 2 jest to względne w stosunku do pliku webpack.config.js. opcja kontekstowa.
— Tobias K.

@TobiasK. Ścieżka bezwzględna nie współpracuje z domyślnymi eksportami. Otrzymuję obiekt {__esModule: true, default: MY_DEFAULT_EXPORT}zamiast MY_DEFAULT_EXPORTw plikach.
— mgol

25

Warto zauważyć, że jeśli użyjesz atrybutu ProvidePluginw połączeniu z externalswłaściwością, pozwoli ci to jQueryprzejść do zamknięcia modułu webpacka bez konieczności jawnego requiretego. Może to być przydatne do refaktoryzacji starszego kodu z odwołaniami do wielu różnych plików $.

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

teraz w index.js

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

będzie miał skompilowane wyjście z czymś takim jak poniżej przekazanym do webpackBootstrapzamknięcia:

/******/ ([
/* 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;

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

Dlatego widzisz, że $odwołuje się do global / window jQueryz CDN, ale jest przekazywany do zamknięcia. Nie jestem pewien, czy jest to zamierzona funkcjonalność, czy szczęśliwy hack, ale wydaje się, że działa dobrze w moim przypadku użycia.


nie potrzebowałeś żadnej wtyczki, jeśli nie zamierzałeś tego robić require/import. $zadziała, ponieważ bez względu na wszystko osiągnie zasięg globalny. ProviderPluginWymaga analizowania AST więc jest to drogie wtyczki i doda do czasu kompilacji zauważalnie. Więc to w zasadzie marnotrawstwo.
— faceyspacey.com

@dtohefp ta odpowiedź jest wybawieniem. Czy możesz ewentualnie wyjaśnić, dlaczego ProvidePluginzwrócił obiekt taki jak, myModule.defaultchyba że dodałem moduł do zewnętrznych? Nigdy nie wiedziałem, że będzie jakikolwiek bezpośredni związek.
— Slbox

11

Wiem, że to stary post, ale pomyślałem, że warto wspomnieć, że moduł ładujący skrypt pakietu webpack może być przydatny również w tym przypadku. Z dokumentów pakietu internetowego:

„script: jednorazowo wykonuje plik JavaScript w kontekście globalnym (np. w tagu skryptu), wymagania nie są analizowane”.

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

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

Zauważyłem, że jest to szczególnie przydatne podczas migracji starszych procesów kompilacji, które łączą ze sobą pliki dostawców JS i pliki aplikacji. Ostrzeżenie jest takie, że moduł ładujący skrypt wydaje się działać tylko przez przeciążenie require()i nie działa tak daleko, jak mogę to stwierdzić, ponieważ jest określony w pliku webpack.config. Chociaż wielu twierdzi, że przeciążanie requirejest złą praktyką, może być całkiem przydatne do łączenia skryptu dostawcy i aplikacji w jednym pakiecie, a jednocześnie ujawniania JS Globals, których nie trzeba umieszczać w dodatkowych pakietach webpack. Na przykład:

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

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

Spowodowałoby to, że $ .cookie, historia i moment byłyby globalnie dostępne w tym pakiecie i poza nim oraz wiązałyby te biblioteki dostawców ze skryptem main.js i wszystkimi jego requireplikami d.

Przydatne w tej technice jest również:

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

który używa Bower, przejrzy mainplik w każdej z requirebibliotek pakiet.json. W powyższym przykładzie History.js nie ma mainokreślonego pliku, więc ścieżka do pliku jest niezbędna.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.