web-dev-qa-db-ja.com

Webpackと外部ライブラリ:ProvidePlugin対エントリーvsグローバルインポート?

1. ProvidePlugin()

一般的に使用されるアプローチのように見えます。それについて Gist があり、whatwg-fetchポリフィルをWebpackビルドに含める方法を紹介しています。 StackOverflowでの多くの回答は here および here を使用しています。

_new webpack.ProvidePlugin({
  '$': 'jquery',
  'jQuery': 'jquery',
  'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
})
_

????長所

  • できます。 (何か不足している場合は、このリストを更新してください)

????短所

  • Webpack構成でグローバルライブラリを追跡する必要があります。

2. _entry: [...]_

this Gist でこのアプローチを発見したとき、私はこのアプローチに少し驚いていましたが、同じように機能します。

_entry: [
    'babel-polyfill',
    'whatwg-fetch',
    'jquery',
    'webpack-hot-middleware/client',
    path.join(process.cwd(), 'app/app.js')
],
_

????長所

  • できます。
  • ProvidePlugin()を完全に削除できます。

????短所

  • Webpack構成でグローバルライブラリを追跡する必要があります。

3.トップレベルimport

これは非常に簡単です。この app.js の例を参照してください。このファイルは、Reactアプリケーションへのエントリポイントです。

_/**
 * app.js
 */

import 'whatwg-fetch';
import 'babel-polyfill';
import 'jquery';
_

????長所

  • それも同様に動作します。
  • 簡単な追加/削除。 Webpack設定を変更する必要はありません。

????短所

  • このアプローチだけではjQueryプラグインで機能するようには見えません。 bootstrap.js

観察:3つのアプローチすべての間で、バンドルサイズの変化に気づきませんでした。

Webpack(およびReact)でグローバルライブラリを処理するための推奨される方法はありますか?これらのソリューションのいずれかにより、サーバーサイドレンダリングで問題が発生しますか?

ありがとう!

22
Sahat Yalkabov

本当に必要でない限り、ライブラリをグローバルとして公開することはお勧めしません。つまり、モジュールシステムの目的は、依存関係を明示的に宣言することです。

// app.js
import $ from 'jquery';
$.ajax(...);

サードパーティのスクリプトがページで、またはコンソールでのデバッグのためにjQueryを必要とするため、グローバルで絶対にjQueryが必要な場合は、リストしたアプローチに関するいくつかの情報を次に示します。

ProvidePlugin

ProvidePluginはjQueryをグローバルに公開せず、グローバルモジュールの存在に誤って依存するサードパーティモジュールを修正するように設計されているため、これはお勧めしません。

// app.js
$.ajax(...);

に効果的に移されます:

// app.js
require('jquery').ajax(...);

エントリー&トップレベルのインポート

これらのアプローチは、jQueryなどの通常のUMDモジュールでは機能しません。jQueryは、commonjs/AMD/es6対応ローダーによってロードされたときにグローバルに公開されないほどスマートです。

ただし、これらの2つのアプローチは、babel-polyfill/whatwg-fetchなどの副作用のあるモジュールには理想的です。何もエクスポートされないため、本質的にグローバル環境が変化します。


したがって、jQueryに対する私の推奨は、モジュールのエクスポートをグローバルに公開するように設計された expose-loader を使用することです。

// webpack.config.js
{
    module: {
        loaders: [
            test: require.resolve('jquery'),
            loader: 'expose-loader?jQuery!expose-loader?$'
        ]
    }
}

その後、それをアプリのコードにインポートする必要があります。

// app.js
import $ from 'jquery';
$.ajax(...)

しかし、絶対に必要な場合は、ページ上の他のスクリプトがアクセスできるように、グローバルで使用できます。

// console
window.$
window.jQuery

注:技術的には、公開ローダーを使用するときにエントリポイントでimport 'jquery'を1回だけ実行し、他のモジュールのグローバルに依存することができます。

ただし、私が言っているように、他のすべてのモジュールで現在使用している場合でも、必要がない場合はモジュールを公開することはお勧めできません。

22
riscarrott

ProvidePluginを使用するときに1つのページに複数のパック(エントリポイント)を含める場合、提供されたlibが上書きされることを確認してください。例はRoRとWebpackerの場合ですが、問題ではないと思います。

たとえば、あなたはあなたのレイアウトに持っています:

  javascript_pack_tag 'application',
                      'metronic'

そして、あなたが持っている設定では:

  environment.plugins.append('Provide', new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      "window.jQuery": "jquery",
      "window.$": "jquery",
      _: 'underscore',
      Handlebars: 'handlebars'
  }));

application.jsでJQueryを変更するライブラリが必要な場合、metronic.jsとブラウザでこの変更をすべて失うことになります。これは、expose-loaderでJQueryを公開した場合でも同じです。

私が間違っている場合は修正してください。ProvidePluginは各エントリポイントにlibsをインポートするだけです。

0
01ghost13