1. ホーム
  2. javascript

[解決済み] webpackでjQueryプラグインの依存関係を管理する

2022-03-20 19:05:58

質問

私は自分のアプリケーションでWebpackを使用しています。その中で私は2つのエントリーポイントを作成します - すべてのJavaScriptファイル/コード用のbundle.jsと、jQueryやReactなどのすべてのライブラリ用のvendor.jsです。jQueryを依存関係に持つプラグインを使用するために、それらをvendor.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 が私の JavaScript コードと一緒に bundle.js にバンドルされることになり、私はすべての jQuery プラグインを vendors.js バンドルに入れたいので、これは私がやりたいことではありません。では、どうすればこれを実現できるのでしょうか?

どのように解決するのですか?

レガシーベンダーのモジュールをどのように取り込むか、さまざまなアプローチが混在していますね。私ならこう取り組みます。

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

ほとんどのモジュールは dist バージョンで main のフィールドを使用します。 package.json . これはほとんどの開発者にとって便利ですが、webpack ではこのようなエイリアスを作成する方がよいでしょう。 src なぜなら、こうすることでwebpackは依存関係をより最適化することができるからです。 DedupePlugin ).

// webpack.config.js

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

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


2. を使用します。 ProvidePlugin 暗黙のグローバルをインジェクトする

レガシーモジュールの多くは、jQuery プラグインのように特定のグローバルの存在に依存しています。 $ または jQuery . このシナリオでは、webpack を設定することで、前置詞として var $ = require("jquery") に遭遇するたびに、グローバルな $ という識別子があります。

var webpack = require("webpack");

    ...

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


3. 3. インポート・ローダー を設定します。 this

一部のレガシーモジュールは this である。 window オブジェクトを作成します。これは、モジュールが CommonJS コンテキストで実行されたときに問題になります。 this イコール module.exports . この場合 this を使用しています。 インポート・ローダー .

実行 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$/
    ]
}