wake-up-neo.com

Verwalten der Abhängigkeit von jQuery-Plugins im Webpack

Ich verwende Webpack in meiner Anwendung, in der ich zwei Einstiegspunkte erstelle - bundle.js für alle meine JavaScript-Dateien/-Codes und vendors.js für alle Bibliotheken wie jQuery und React. Was mache ich, um Plugins zu verwenden, deren Abhängigkeiten jQuery sind und die ich 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 . Die Webpack-Dokumentation erwähnt supplyPlugin und den Import-Loader. Ich habe provisionPlugin verwendet, aber das jQuery-Objekt ist immer noch nicht verfügbar. So sieht meine webpack.config.js aus:

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;

Trotzdem wird immer noch ein Fehler in der Browserkonsole ausgegeben:

Nicht erfasster ReferenceError: jQuery ist nicht definiert

Wenn ich den Import-Loader verwende, wird auf ähnliche Weise ein Fehler ausgegeben.

erfordern ist nicht definiert '

in dieser Zeile:

var jQuery = require("jquery")

Ich könnte jedoch dasselbe Plugin verwenden, wenn ich es nicht zu meiner vendors.js-Datei hinzufüge und stattdessen auf die normale AMD-Art und Weise benötige, wie ich meine anderen JavaScript-Codedateien einbinde, z.

define(
[
    'jquery',
    'react',
    '../../common-functions',
    '../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
    $("#myInput").elastic() //It works

});

Dies ist jedoch 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 enthalten ist und alle meine jQuery-Plug-ins im Bundle vendors.js enthalten sein sollen. Wie gehe ich vor, um dies zu erreichen?

412
booleanhunter

Sie haben verschiedene Ansätze zum Einbeziehen von älteren Anbietermodulen gemischt. So würde ich es angehen:

1. Bevorzugen Sie nicht abgeschlossenes CommonJS/AMD gegenüber dist

Die meisten Module verknüpfen die Version dist im Feld main ihres package.json. Während dies für die meisten Entwickler nützlich ist, ist es für Webpack besser, die Version von src als Alias ​​zu verwenden, da auf diese Weise Abhängigkeiten besser optimiert werden können (z. B. bei Verwendung von DedupePlugin ).

// webpack.config.js

module.exports = {
    ...
    resolve: {
        alias: {
            jquery: "jquery/src/jquery"
        }
    }
};

In den meisten Fällen funktioniert die Version dist jedoch auch einwandfrei.


2. Verwenden Sie ProvidePlugin, um implizite globale Variablen einzufügen

Die meisten älteren Module sind auf das Vorhandensein bestimmter globaler Elemente angewiesen, wie dies bei jQuery-Plugins für $ oder jQuery der Fall ist. In diesem Szenario können Sie das Webpack so konfigurieren, dass var $ = require("jquery") jedes Mal vorangestellt wird, wenn es auf den globalen Bezeichner $ stößt.

var webpack = require("webpack");

    ...

    plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        })
    ]

3. Verwenden Sie den Import-Loader , um this zu konfigurieren.

Einige ältere Module setzen voraus, dass this das window-Objekt ist. Dies wird zu einem Problem, wenn das Modul in einem CommonJS-Kontext ausgeführt wird, in dem thismodule.exports entspricht. In diesem Fall können Sie this mit dem Imports-Loader überschreiben.

Führen Sie npm i imports-loader --save-dev und dann aus

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?this=>window"
        }
    ]
}

Der Import-Loader kann auch zum manuellen Einfügen von Variablen aller Art verwendet werden. Meistens ist der ProvidePlugin jedoch nützlicher, wenn es um implizite globale Variablen geht.


4. Verwenden Sie den Import-Loader , um AMD zu deaktivieren

Es gibt Module, die verschiedene Modulstile unterstützen, z. B. AMD, CommonJS und Legacy. In den meisten Fällen wird jedoch zuerst nach define gesucht, und anschließend wird zum Exportieren von Eigenschaften etwas eigenartiger Code verwendet. In diesen Fällen kann es hilfreich sein, den CommonJS-Pfad durch Festlegen von define = false zu erzwingen.

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?define=>false"
        }
    ]
}

5. Verwenden Sie script-loader , um Skripte global zu importieren

Wenn Sie sich nicht für globale Variablen interessieren und nur möchten, dass ältere Skripte funktionieren, können Sie auch den Skriptlader verwenden. Es führt das Modul in einem globalen Kontext aus, als ob Sie sie über das Tag <script> eingebunden hätten.


6. Verwenden Sie noParse, um große Distanzen einzuschließen

Wenn es keine AMD/CommonJS-Version des Moduls gibt und Sie dist einschließen möchten, können Sie dieses Modul als noParse kennzeichnen. Dann enthält das Webpack nur das Modul, ohne es zu analysieren, was zur Verbesserung der Erstellungszeit verwendet werden kann. Dies bedeutet, dass alle Funktionen, für die AST erforderlich ist, wie z. B. ProvidePlugin, nicht funktionieren.

module: {
    noParse: [
        /[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
    ]
}
731
Johannes Ewald

Für den globalen Zugriff auf jquery gibt es mehrere Optionen. In meinem letzten Webpack-Projekt wollte ich einen globalen Zugriff auf jquery, daher habe ich meinen Plugins-Deklarationen Folgendes hinzugefügt:

 plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery"
    })
  ]

Dies bedeutet dann, dass auf jquery aus dem JavaScript-Quellcode über die globalen Verweise $ und jQuery zugegriffen werden kann.

Natürlich müssen Sie auch jquery via npm installiert haben:

$ npm i jquery --save

Ein funktionierendes Beispiel für diesen Ansatz finden Sie unter github

82
arcseldon

Ich weiß nicht, ob ich sehr gut verstehe, was Sie versuchen, aber ich musste jQuery-Plugins verwenden, für die jQuery im globalen Kontext (Fenster) sein musste, und ich habe Folgendes in mein entry.js eingefügt:

var $ = require('jquery');
window.jQuery = $;
window.$ = $;

Das muss ich nur verlangen wo immer ich will das jqueryplugin.min.js und window.$ wie erwartet mit dem Plugin erweitert wird.

51
sanfilippopablo

Ich habe gute Arbeit geleistet, als ich $ und jQuery mit Webpack 3.8.1 und den folgenden als globale Variablen verfügbar gemacht habe.

Installieren Sie jQuery als Projektabhängigkeit. Sie können @3.2.1 weglassen, um die neueste Version zu installieren oder eine andere Version anzugeben.

npm install --save [email protected]

Installieren Sie expose-loader als Entwicklungsabhängigkeit, falls noch nicht installiert.

npm install expose-loader --save-dev

Konfigurieren Sie Webpack, um jQuery für uns zu laden und verfügbar zu machen.

// webpack.config.js
const webpack = require('webpack')

module.exports = {
  entry: [
    // entry bits
  ],
  output: {
    // output bits
  },
  module: {
    rules: [
      // any other rules
      {
        // Exposes jQuery for use outside Webpack build
        test: require.resolve('jquery'),
        use: [{
          loader: 'expose-loader',
          options: 'jQuery'
        },{
          loader: 'expose-loader',
          options: '$'
        }]
      }
    ]
  },
  plugins: [
    // Provides jQuery for other JS bundled with Webpack
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery'
    })
  ]
}
18
HarlemSquirrel

Fügen Sie dies zu Ihrem Plugins-Array in webpack.config.js hinzu

new webpack.ProvidePlugin({
    'window.jQuery': 'jquery',
    'window.$': 'jquery',
})

dann benötigen Sie normalerweise eine Abfrage

require('jquery');

Wenn andere Skripte weiterhin Probleme haben, es zu sehen, platzieren Sie es explizit im globalen Kontext über (im Eintrag js).

window.$ = jQuery;
16
KhaledMohamedP

Fügen Sie in der Datei webpack.config.js Folgendes hinzu:

 var webpack = require("webpack");
 plugins: [
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
    })
 ],

Installieren Sie jQuery mit npm:

$ npm i jquery --save

Fügen Sie in der Datei app.js die folgenden Zeilen hinzu:

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

Das hat bei mir funktioniert. :)

15
ashwini

Ich habe einige der gelieferten Antworten ausprobiert, aber keine davon schien zu funktionieren. Dann habe ich es versucht:

new webpack.ProvidePlugin({
    'window.jQuery'    : 'jquery',
    'window.$'         : 'jquery',
    'jQuery'           : 'jquery',
    '$'                : 'jquery'
});

Scheint zu funktionieren, egal welche Version ich benutze

8
Cam Tullos

Dies funktioniert in Webpack 3:

in der Datei webpack.config.babel.js:

resolve: {
    alias: {
         jquery: "jquery/src/jquery"
    },
 ....
}

Und benutze ProvidePlugin

new webpack.ProvidePlugin({
        '$': 'jquery',
        'jQuery': 'jquery',
    })
7
SharpCoder

Das funktioniert bei mir auf der webpack.config.js

    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery'
    }),

in einem anderen Javascript oder in HTML hinzufügen:

global.jQuery = require('jquery');
2
JPRLCol

Die beste Lösung, die ich gefunden habe, war:

https://github.com/angular/angular-cli/issues/5139#issuecomment-283634059

Grundsätzlich müssen Sie eine Dummy-Variable in typings.d.ts einfügen, "import * as $ from 'jquery" aus Ihrem Code entfernen und dann Ihrem SPA-HTML-Code manuell ein Tag zum jQuery-Skript hinzufügen. Auf diese Weise wird Webpack nicht von Ihnen beeinträchtigt, und Sie sollten in allen Skripten auf dieselbe globale jQuery-Variable zugreifen können.

2
Fabricio

Bearbeiten: Manchmal möchten Sie Webpack einfach als Modulbündler für ein einfaches Webprojekt verwenden - um Ihren eigenen Code zu organisieren. Die folgende Lösung ist für diejenigen gedacht, die nur möchten, dass eine externe Bibliothek in ihren Modulen wie erwartet funktioniert - ohne viel Zeit für das Eintauchen in Webpack-Setups zu benötigen. (Bearbeitet nach -1)

Schnelle und einfache (es6) Lösung, wenn Sie immer noch Probleme haben oder die externe Konfiguration/zusätzliche Konfiguration des Webpack-Plugins vermeiden möchten:

<script src="cdn/jquery.js"></script>
<script src="cdn/underscore.js"></script>
<script src="etc.js"></script>
<script src="bundle.js"></script>

innerhalb eines Moduls:

const { jQuery: $, Underscore: _, etc } = window;
0
frdnrdb