I'm mit Webpack in meiner Anwendung, in der ich zwei Einstiegspunkte erstellen - bundle.js für alle meine JavaScript-Dateien/Codes und vendors.js für alle Bibliotheken wie jQuery und React. Was muss ich tun, wenn ich Plugins verwenden möchte, die jQuery als Abhängigkeit haben und ich sie auch in vendors.js haben möchte? Was ist, wenn diese Plugins mehrere Abhängigkeiten haben?
Derzeit versuche ich, dieses jQuery-Plugin hier zu verwenden - https://github.com/mbklein/jquery-elastic. In der Webpack-Dokumentation werden providePlugin und imports-loader erwähnt. Ich habe providePlugin verwendet, aber immer noch das jQuery-Objekt ist nicht verfügbar. Hier ist, wie meine webpack.config.js aussieht
var webpack = require('webpack');
var bower_dir = __dirname + '/bower_components';
var node_dir = __dirname + '/node_modules';
var lib_dir = __dirname + '/public/js/libs';
var config = {
addVendor: function (name, path) {
this.resolve.alias[name] = path;
this.module.noParse.push(new RegExp(path));
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jquery: "jQuery",
"window.jQuery": "jquery"
}),
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js', Infinity)
],
entry: {
app: ['./public/js/main.js'],
vendors: ['react','jquery']
},
resolve: {
alias: {
'jquery': node_dir + '/jquery/dist/jquery.js',
'jquery.elastic': lib_dir + '/jquery.elastic.source.js'
}
},
output: {
path: './public/js',
filename: 'bundle.js'
},
module: {
loaders: [
{ test: /\.js$/, loader: 'jsx-loader' },
{ test: /\.jquery.elastic.js$/, loader: 'imports-loader' }
]
}
};
config.addVendor('react', bower_dir + '/react/react.min.js');
config.addVendor('jquery', node_dir + '/jquery/dist/jquery.js');
config.addVendor('jquery.elastic', lib_dir +'/jquery.elastic.source.js');
module.exports = config;
Aber trotzdem wird in der Browserkonsole ein Fehler angezeigt:
Ungefangener ReferenceError: jQuery ist nicht definiert
Ähnlich verhält es sich, wenn ich den Import-Loader verwende, der einen Fehler auslöst,
require ist nicht definiert'
in dieser Zeile:
var jQuery = require("jquery")
Allerdings könnte ich das gleiche Plugin verwenden, wenn ich don't fügen Sie es zu meinem vendors.js Datei und stattdessen benötigt es in der normalen AMD Weg, wie ich meine anderen JavaScript-Code-Dateien, wie-
define(
[
'jquery',
'react',
'../../common-functions',
'../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
$("#myInput").elastic() //It works
});
Aber das ist nicht das, was ich tun möchte, da dies bedeuten würde, dass jquery.elastic.source.js zusammen mit meinem JavaScript-Code in bundle.js gebündelt wird, und ich möchte, dass alle meine jQuery-Plugins im vendors.js-Bündel sind. Wie kann ich dies also erreichen?
Sie haben verschiedene Ansätze für die Einbeziehung von Modulen von Altanbietern gemischt. Ich würde es folgendermaßen angehen:
dist
Die meisten Module verlinken die dist
Version im main
Feld ihrer package.json
. Waehrend dies fuer die meisten Entwickler nuetzlich ist, ist es fuer Webpack besser, die src
Version zu aliasieren, weil auf diese Weise Webpack in der Lage ist, Abhaengigkeiten besser zu optimieren (z.B. wenn es das DedupePlugin
verwendet).
// webpack.config.js
module.exports = {
...
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
}
};
In den meisten Fällen funktioniert jedoch auch die dist
-Version.
ProvidePlugin
um implizite Globals zu injizierenDie meisten Legacy-Module verlassen sich auf das Vorhandensein bestimmter Globals, wie jQuery-Plugins auf $
oder jQuery
. In diesem Szenario kann man Webpack so konfigurieren, dass es var $ = require("jquery")
jedes Mal vorangestellt wird, wenn es auf den globalen $
Bezeichner trifft.
var webpack = require("webpack");
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
this
zu konfigurierenEinige Legacy-Module verlassen sich darauf, dass this
das Window
-Objekt ist. Dies wird zu einem Problem, wenn das Modul in einem CommonJS-Kontext ausgeführt wird, in dem "this" gleich "module.exports" ist. In diesem Fall können Sie this
mit dem imports-loader außer Kraft setzen.
Führen Sie npm i imports-loader --save-dev
aus und dann
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?this=>window"
}
]
}
Der imports-loader kann auch verwendet werden, um Variablen aller Art manuell zu injizieren. Aber die meiste Zeit ist das ProvidePlugin
nützlicher, wenn es um implizite Globals geht.
Es gibt Module, die verschiedene Modulstile unterstützen, wie AMD, CommonJS und legacy. Meistens prüfen sie jedoch zuerst auf define
und verwenden dann einen eigenartigen Code, um Eigenschaften zu exportieren. In diesen Fällen kann es helfen, den CommonJS-Pfad zu erzwingen, indem man define = false
setzt.
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?define=>false"
}
]
}
Wenn Sie sich nicht um globale Variablen kümmern und nur wollen, dass die alten Skripte funktionieren, können Sie auch den script-loader verwenden. Er führt das Modul in einem globalen Kontext aus, so als ob Sie es über den <script>
-Tag eingebunden hätten.
noParse
, um große Listen einzubindenWenn es keine AMD/CommonJS Version des Moduls gibt und Sie die dist
einbinden wollen, können Sie dieses Modul als noParse
kennzeichnen. Dann wird webpack das Modul einfach einbinden, ohne es zu parsen, was zur Verbesserung der Erstellungszeit genutzt werden kann. Das bedeutet, dass jede Funktion, die AST benötigt, wie das ProvidePlugin
, nicht funktionieren wird.
module: {
noParse: [
/[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
]
}
Für den globalen Zugriff auf jquery gibt es mehrere Möglichkeiten. In meinem letzten Webpack-Projekt wollte ich globalen Zugriff auf jquery, also fügte ich das Folgende zu meinen Plugin-Deklarationen hinzu:
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
Das bedeutet, dass jquery aus dem JavaScript-Quellcode über die globalen Referenzen $ und jQuery zugänglich ist.
Natürlich müssen Sie auch jquery über npm installiert haben:
$ npm i jquery --save
Für ein funktionierendes Beispiel dieses Ansatzes können Sie gerne meine App auf github forken.
Ich weiß nicht, ob ich sehr gut verstehe, was Sie zu tun versuchen, aber ich musste jQuery-Plugins verwenden, die jQuery in den globalen Kontext (Fenster) erforderlich, und ich habe die folgenden in meinem entry.js
:
var $ = require('jquery');
window.jQuery = $;
window.$ = $;
Dann muss ich nur noch die "jqueryplugin.min.js" einbinden und "window.$" wird wie erwartet um das Plugin erweitert.