web-dev-qa-db-ja.com

Webpack ProvidePluginと外部の比較

WebpackBackbone.js を併用するというアイデアを模索しています。

クイックスタートガイドに従って、Webpackがどのように機能するかについての一般的な考えを持っていますが、jquery/backbone/underscoreのような依存ライブラリをロードする方法についてはわかりません。

外部で<script>でロードする必要がありますか、それともWebpackはRequireJSのシムのように処理できますか?

webpack doc:shimming modules 、によれば、ProvidePluginexternalsはこれに関連しているようです(したがって、bundle! loaderはどこかにあります)どれを使うか。

ありがとう

80
Henry

両方の可能性があります:<script>でライブラリを含める(つまり、CDNからライブラリを使用する)か、生成されたバンドルに含めることができます。

<script>タグを介してロードする場合、externalsオプションを使用して、モジュールにrequire(...)を書き込むことができます。

CDNのライブラリを使用した例:

<script src="https://code.jquery.com/jquery-git2.min.js"></script>

// the artifial module "jquery" exports the global var "jQuery"
externals: { jquery: "jQuery" }

// inside any module
var $ = require("jquery");

バンドルにライブラリが含まれる例:

copy `jquery-git2.min.js` to your local filesystem

// make "jquery" resolve to your local copy of the library
// i. e. through the resolve.alias option
resolve: { alias: { jquery: "/path/to/jquery-git2.min.js" } }

// inside any module
var $ = require("jquery");

ProvidePluginは、モジュールを(無料の)変数にマップできます。だから、定義することができます:「(フリー)変数xyzをモジュール内で使用するたびに、(Webpack)はxyzrequire("abc")に設定する必要があります。」

ProvidePluginなしの例:

// You need to require underscore before you can use it
var _ = require("underscore");
_.size(...);

ProvidePluginの例:

plugins: [
  new webpack.ProvidePlugin({
    "_": "underscore"
  }) 
]

// If you use "_", underscore is automatically required
_.size(...)

概要:

  • CDNのライブラリ:<script>タグとexternalsオプションを使用します
  • ファイルシステムのライブラリ:バンドルにライブラリを含めます。 (ライブラリを見つけるためにresolveオプションを変更するかもしれません)
  • externals:グローバル変数をモジュールとして利用可能にします
  • ProvidePlugin:モジュール内の自由変数としてモジュールを使用可能にします
147
Tobias K.

注意すべき点は、ProvidePluginexternalsプロパティと組み合わせて使用​​すると、jQueryを明示的に指定しなくても、requireをwebpackモジュールクロージャーに渡すことができることです。これは、$を参照する多くの異なるファイルでレガシーコードをリファクタリングするのに役立ちます。

//webpack.config.js
module.exports = {
  entry: './index.js',
  output: { 
    filename: '[name].js' 
  },
  externals: {
    jquery: 'jQuery'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
    })
  ]
};

今index.jsで

console.log(typeof $ === 'function');

以下のようなものがwebpackBootstrapクロージャーに渡されたコンパイル済み出力があります。

/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    /* WEBPACK VAR INJECTION */(function($) {
        console.log(typeof $ === 'function');

    /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

    module.exports = jQuery;

/***/ }
/******/ ])

したがって、$はCDNからグローバル/ウィンドウjQueryを参照しているが、クロージャーに渡されていることがわかります。これが意図された機能であるか幸運なハックであるかはわかりませんが、私のユースケースではうまくいくようです。

22
dtothefp

私はこれが古い投稿であることを知っていますが、この場合にもwebpackスクリプトローダーが役立つかもしれないと言及することは有益だと思いました。 Webpackドキュメントから:

「script:JavaScriptファイルをグローバルコンテキスト(scriptタグなど)で1回実行しますが、要求は解析されません。」

http://webpack.github.io/docs/list-of-loaders.html

https://github.com/webpack/script-loader

これは、JSベンダーファイルとアプリファイルを一緒に連結する古いビルドプロセスを移行する場合に特に役立ちます。警告の言葉は、スクリプトローダーがrequire()のオーバーロードを介してのみ動作するようであり、webpack.configファイル内で指定することでわかる限り動作しないことです。 requireをオーバーロードするのは悪い習慣であると多くの人が主張していますが、ベンダーとアプリのスクリプトを1つのバンドルに連結し、同時に追加のWebpackバンドルに詰め込む必要のないJSグローバルを公開するのに非常に役立ちます。例えば:

require('script!jquery-cookie/jquery.cookie');
require('script!history.js/scripts/bundled-uncompressed/html4+html5/jquery.history');
require('script!momentjs');

require('./scripts/main.js');

これにより、このバンドルの内外で$ .cookie、History、momentがグローバルに利用可能になり、これらのベンダーライブラリがmain.jsスクリプトとすべてのrequiredファイルにバンドルされます。

また、この手法で役立つのは次のとおりです。

resolve: {
  extensions: ["", ".js"],
  modulesDirectories: ['node_modules', 'bower_components']
},
plugins: [
  new webpack.ResolverPlugin(
    new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
   )
]

bowerを使用している場合、各maindライブラリpackage.jsonのrequireファイルを調べます。上記の例では、History.jsにはmainファイルが指定されていないため、ファイルへのパスが必要です。

11
dtothefp