WebpackでのjQueryプラグインの依存関係の管理


451

私はアプリケーションでWebpackを使用しています。ここでは、すべてのJavaScriptファイル/コード用のbundle.jsと、jQueryやReactなどのすべてのライブラリ用のvendors.jsの2つのエントリポイントを作成しています。依存関係としてjQueryがあり、vendors.jsにもそれらを含めたいプラグインを使用するにはどうすればよいですか?これらのプラグインに複数の依存関係がある場合はどうなりますか?

現在、私はこのjQueryプラグインをここで使用しようとしています-https ://github.com/mbklein/jquery-elastic。Webpackのドキュメントでは、providePluginとimports-loader について言及しています。私はprovidePluginを使用しましたが、それでもjQueryオブジェクトは利用できません。これが私のwebpack.config.jsがどのように見えるかです-

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;

しかし、それにもかかわらず、ブラウザコンソールでエラーが発生します。

Uncaught ReferenceError:jQueryが定義されていません

同様に、imports-loaderを使用すると、エラーがスローされます。

requireは定義されていません '

この行で:

var jQuery = require("jquery")

ただし、vendors.jsファイルに追加しない場合は、同じプラグインを使用できます。代わりに、他のJavaScriptコードファイルを含める方法と同じように、通常のAMDの方法でそれを必要としました。

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

});

しかし、これは私がやりたいことではありません。これは、jquery.elastic.source.jsがbundle.jsのJavaScriptコードと一緒にバンドルされ、すべてのjQueryプラグインをvendors.jsバンドルに含めたいことを意味するためです。これを達成するにはどうすればよいですか?


3
これが問題であるかどうかはわかりませんが、windows.jQueryを "window.jQuery": "jquery"に変更する必要があります。あなたがそのコードを入手したと私が仮定しているウェブパックのウェブサイトにタイプミスがあります。
Alex Hawkins

@AlexHawkinsそうそう、私はそれに気づき、それを修正しました。指摘してくれてありがとう!
ブールハンター、

回答:


770

レガシーベンダーモジュールを含める方法はさまざまです。これは私がそれに取り組む方法です:

1.縮小されていないCommonJS / AMDを優先する dist

ほとんどのモジュールdistは、そのmainフィールドでバージョンをリンクしますpackage.json。これはほとんどの開発者にとって便利ですが、srcwebpackは依存関係をより適切に最適化できるため(たとえばを使用する場合DedupePlugin)、webpackのバージョンにエイリアスを付けることをお勧めします。

// webpack.config.js

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

ただし、ほとんどの場合、distバージョンも問題なく動作します。


2.を使用 ProvidePluginて暗黙的グローバルを注入する

ほとんどのレガシーモジュールは、jQueryプラグインが$やで行うように、特定のグローバルの存在に依存していますjQuery。このシナリオvar $ = require("jquery")では、グローバル$識別子を検出するたびに先頭に付加するようにwebpackを構成できます。

var webpack = require("webpack");

    ...

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

3. imports-loaderを使用するを使用して構成しますthis

一部のレガシーモジュールthisは、windowオブジェクトであることに依存しています。モジュールはCommonJSコンテキストで実行されたとき、これは問題になりthisイコールmodule.exports。この場合thisimports-loaderでオーバーライドできます。

走る npm i imports-loader --save-devしてから

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

imports-loaderは、あらゆる種類の変数を手動で注入するためにも使用できます。しかし、ほとんどの場合ProvidePlugin場合、暗黙のグローバルに関してはより便利です。


4.を使用 インポートローダーを使用してAMDを無効にします

AMD、CommonJS、レガシーなど、さまざまなモジュールスタイルをサポートするモジュールがあります。ただし、ほとんどの場合、最初に確認してdefineから、風変わりなコードを使用してプロパティをエクスポートします。これらの場合、を設定することでCommonJSパスを強制するのに役立ちますdefine = false

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

5.を使用 スクリプトローダーをををグローバルにインポートする

グローバル変数を気にせず、レガシースクリプトを機能させたい場合は、script-loaderを使用することもできます。<script>タグを介してそれらを含めたかのように、グローバルコンテキストでモジュールを実行します。


6.使用 noParse大きな距離を含めるためにする

AMD / CommonJSバージョンのモジュールがなくdist、を含めたい場合は、このモジュールにとしてフラグを付けることができますnoParse。次に、webpackはモジュールを解析せずに含めるだけで、ビルド時間を改善するために使用できます。これは、のようなASTを必要とする機能が機能しないことを意味しますProvidePlugin

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

3
ProvidePluginすべてのファイル内の指定された識別子のすべての出現に適用されます。imports-loaderのみ、特定のファイルに適用することができますが、同じ変数/依存性の両方を使用しないでください。
Johannes Ewald 2015年

5
私はこれで混乱しています。jqueryは実際にはどこから来ていますか?ローカルまたはCDN?それ以降が必要かどうか。webpackを使用してjqueryをプロジェクトに統合する実際の手順は何ですか。CDN経由で利用できるバージョンをバイパスしますか?
HelpMeStackOverflowMyOnlyHope 2015年

2
CDNからのすべてはwebpackの範囲外なので、これはローカルjqueryインストールを指します。jqueryが必要になるだけで、それを統合するために必要な特別な手順はありません。この質問は、グローバル$変数に依存するjqueryプラグインを統合する方法についてです。
Johannes Ewald、

8
これはすべてうまくいきましたが、まだ機能していません。次に追加:"module": { "loaders": [ { test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" },そしてそれはうまくいきました。
musicformellons 2016年

5
jqueryパッケージだけを含めるために、これをすべて行いますか?私は私の大胆なビルドに戻ります
Rahul Gupta 2017

89

jqueryへのグローバルアクセスには、いくつかのオプションがあります。私の最新のwebpackプロジェクトでは、jqueryへのグローバルアクセスが必要だったので、プラグイン宣言に以下を追加しました。

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

つまり、JavaScriptのソースコード内からグローバル参照$とjQueryを介してjqueryにアクセスできます。

もちろん、npm経由でjqueryもインストールしておく必要があります。

$ npm i jquery --save

このアプローチの実際の例については、githubで私のアプリを自由にフォークしてください


2
理由を説明する投票を格下げする場合、コメントを残してください。上記の情報は正確です。上記のアプローチを使用して、github.com / arcseldon / react-babel-webpack-starter- appにある私の作業中のアプリを参照してください。
arcseldon

私は賛成者ではありませんが、おそらくこれは、ProvidePlugin提案されたソリューションがすでに提案されているためでしょうか?
レオ・ラム

@LéoLam-コメントありがとうございます。あなたのポイントに感謝します-私は別々の問い合わせを介して答えを導き出し、ここでスニペットを共有しました。私がしたことをエミュレートしたい他の人におそらく最も関連性があると思いました。あなたは正しいですが、公式の答えはこのオプションをカバーしています。
arcseldon 2015

1
動作していますが、2つの警告が表示されます。./~/jQuery/dist/jquery.js There is another module with an equal name when case is ignored.同じ警告が表示されます./~/jquery/dist/jquery.js
ピストウ

7
'window.jQuery': 'jquery'ms-signalr-client npmパッケージをロードするには、そのリストに追加する必要がありました。私も'window.$': 'jquery'かなりの量を入れました:)
Sammi

57

私があなたがやろうとしていることをよく理解しているかどうかはわかりませんが、jQueryがグローバルコンテキスト(ウィンドウ)にあることを必要とするjQueryプラグインを使用する必要がありましたentry.js

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

私はちょうど私が好きな場所必要としなければならないjqueryplugin.min.jswindow.$予想されるように、プラグインで拡張されます。


2
基本的に、私はnoParse条件と合わせてProvidePluginを使用することを間違えていました。回答のポイント6で述べられているように、NoParseを実行すると、ProvidePluginなどのプラグインは機能しません。コードにその誤りがあることがわかります
booleanhunter '26

ええ、私はそれが提供プラグインなどよりもプラグイン全体で一貫して機能することを発見しました...特に、スクリプトローダーを介して角度1.xを取り込む場合。
Tracker1 2017

27

露出$しながらうまく機能し、jQueryWebpack 3.8.1以降では、グローバル変数として。

プロジェクトの依存関係としてjQueryをインストールします。@3.2.1最新バージョンのインストールを省略したり、別バージョンを指定したりできます。

npm install --save jquery@3.2.1

expose-loaderまだインストールされていない場合は、開発依存関係としてインストールします。

npm install expose-loader --save-dev

jQueryをロードして公開するようにWebpackを構成します。

// 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'
    })
  ]
}

5
あなたはexpose-loaderそれが適切に動作するため にインストールする必要があることを言及するのを忘れていましたnpm install expose-loader --save-dev
Paulo Griiettner '15 / 11/17

4
これは私のために働いた👍。jquery:3.3.1、expose-loader:0.7.5、webpack:4.20.2
AKT

expose-loaded私のためにそれをやりました。コンパイル時にエラーは発生しませんでしたが、Chromeデベロッパーツールでエラーが発生しました。これで解決しました。
Johan Vergeer

ありがとうございました!これは、「jquery」:「^ 3.4.1」、および「webpack」:「^ 4.41.5」で機能しました。それは私だけですか、それともjQueryをWebpackで動作させるのはそれほどばかげるべきではありませんか?
カルレスアルコレア

18

これをwebpack.config.jsのプラグイン配列に追加します

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

その後、jqueryを通常必要とします

require('jquery');

他のスクリプトがそれを見るのに苦痛が続く場合は、(エントリjsで)グローバルコンテキストに明示的に配置してみてください

window.$ = jQuery;

18

webpack.config.jsファイルに以下を追加します。

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

npmを使用してjQueryをインストールします。

$ npm i jquery --save

app.jsファイルに次の行を追加します。

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

これでうまくいきました。:)


あなたが元に持っている場合、これはどのように機能しますか?app.js、jquery-module.js、どちらもjqueryが必要ですか?私にとっては、jquery13981378127とjquery12389723198がウィンドウ上のインスタンスとして取得されますか?
Martea、

8

私は提供された回答のいくつかを試しましたが、どれもうまくいかなかったようです。それから私はこれを試しました:

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

私が使用しているバージョンに関係なく動作するようです


+1は、ここで追加されたグローバルがウィンドウに対して自動的に設定されるという誤解のようであり、明示的にする必要があるようには機能しないようです。
James

正しい、これはウィンドウオブジェクトに追加しません。webpack内にウィンドウエイリアスを作成します。したがって$、webpackの必要なファイル以外で使用しようとすると、未定義になります。
Cam Tullos 2017

7

これはwebpack 3で機能します。

webpack.config.babel.jsファイル内:

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

そして、ProvidePluginを使用します

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

1
WebPACKのでスーパー新しく追加された他の人のために(!私のような)「解決」module.exportsは下にwebpack.config.jsに行く= {}ちょうどエントリのように、出力、プラグイン、モジュール、など。
DavGarcia

1
そして、新しいwebpack.ProvidePluginがplugins配列の中にあります。
DavGarcia

2

私が見つけた最良の解決策は:

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

基本的に、typings.d.tsにダミー変数を含め、コードから "import * as $ from 'jquery"を削除してから、jQueryスクリプトへのタグをSPA htmlに手動で追加する必要があります。この方法では、webpackが邪魔にならず、すべてのスクリプトで同じグローバルjQuery変数にアクセスできるはずです。


2

これはwebpack.config.jsで私のために働きます

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

別のJavaScriptまたはHTMLに追加:

global.jQuery = require('jquery');

0

編集:独自のコードを整理しておくために、単純なWebプロジェクトのモジュールバンドルとして単にWebpackを使用したい場合があります。次の解決策は、モジュール内で外部ライブラリが期待どおりに機能することを望んでいる人向けです。多くの時間をWebpack設定に費やすことなく使用できます。(-1の後に編集)

まだ苦労している場合、または外部設定/追加のWebpackプラグイン設定を回避したい場合は、すばやく簡単な(es6)ソリューション:

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

モジュール内:

const { jQuery: $, Underscore: _, etc } = window;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.