web-dev-qa-db-ja.com

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

私は自分のアプリケーションでWebpackを使用しています。そこでは、2つのエントリポイントを作成します。すべてのJavaScriptファイル/コード用のbundle.jsと、jQueryやReactなどのすべてのライブラリ用のvendors.jsです。依存関係として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;

しかしこれにもかかわらず、それはまだブラウザコンソールでエラーを投げます:

不明な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が私のJavaScriptコードとともにbundle.jsにバンドルされているので、これは私がやりたいことではありません。また、すべてのjQueryプラグインをvendors.jsバンドルに含めることをお勧めします。では、どうやってこれを達成するのでしょうか。

391
booleanhunter

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

1. distよりもunminifiedのCommonJS/AMDを優先する

ほとんどのモジュールは、それらのpackage.jsondistフィールドでmainバージョンをリンクします。これはほとんどの開発者にとって有用ですが、webpackの場合はsrcバージョンを別名にする方が良いでしょう。なぜならこの方法ではwebpackは依存性をより良く最適化できるからです(例えば DedupePlugin を使うとき)。

// 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を設定します。

いくつかのレガシーモジュールはthiswindowオブジェクトであることに依存しています。 thismodule.exportsと等しいCommonJSコンテキストでモジュールが実行されると、これが問題になります。この場合、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. imports-loader を使用してAMDを無効にします

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

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はモジュールを解析せずに単にインクルードします。これはビルド時間を改善するために使用できます。これは、ProvidePluginのように、 _ ast _ を必要とする機能は機能しないことを意味します。

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

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

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

これは、jqueryがグローバル参照$およびjQueryを介してJavaScriptソースコード内からアクセス可能であることを意味します。

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

$ npm i jquery --save

このアプローチの実用的な例として、 github で私のアプリをフォークしてください。

80
arcseldon

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

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

jqueryplugin.min.jswindow.$が必要な場所であればどこでもプラグインで拡張する必要があります。

51
sanfilippopablo

Webpack 3.8.1以降で$jQueryをグローバル変数として公開しながら、うまく動作するようになりました。

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

npm install --save [email protected]

まだインストールされていない場合は、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'
    })
  ]
}
17
HarlemSquirrel

これをwebpack.config.jsのプラグイン配列に追加してください。

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

それから通常jqueryが必要です

require('jquery');

他のスクリプトにそれを見てもらうのに苦痛が持続するならば、(エントリーjsの中で)を通して明示的にそれをグローバルコンテキストに置くことを試みなさい

window.$ = jQuery;
15
KhaledMohamedP

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.$ = $;

これは私のために働きました。 :)

13
ashwini

これは webpack 3で動作します:

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

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

そして ProvidePlugin を使ってください。

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

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

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

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

6
Cam Tullos

これは私にとってはwebpack.config.js上で動作します。

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

別のJavaScriptまたはHTMLに追加:

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

私が見つけた最良の解決策は以下のとおりです。

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

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

2
the.fabricio

編集:ときには、単純な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;
0
frdnrdb