web-dev-qa-db-ja.com

NPMを介してロードされたモジュールを複数のBrowserifyまたはWebpackバンドル間で共有するためのシンプルなソリューション

複数のBrowserifyまたはWebpackバンドル間で、NPMを介して必要な、コードを共有するためのsimpleソリューションを探してここで髪を引っ張っています。考えてみると、ファイル「ブリッジ」のようなものはありますか?

これはコンパイル時間によるものではなく(私はwatchifyを知っています)、ベンダー固有のライブラリをすべてvendor.jsに抽出して、app.jsファイルサイズを抑えてクラッシュしないようにしたいという願望です。大量のソースマップを備えたブラウザ。さらに、コンパイルされたjsを表示する必要が生じた場合は、はるかにクリーンであることがわかります。など:

// vendor.js

require('react');
require('lodash');
require('other-npm-module');
require('another-npm-module');

コードをBowerではなくNPMからロードするか、相対パスを介してインポートしてシムを介して識別するために、「ベンダー」ディレクトリに保存することが非常に重要です。実際のアプリケーションソースを除いて、すべてのライブラリ参照をNPM経由でプルしたままにしておきたいです。

app.jsにすべてのソースコードを保持し、externals配列を介して、上記のベンダーライブラリをコンパイルから除外します。

// app.js 

var React = require('react');
var _     = require('lodash');

var Component = React.createClass()

// ...

そして、index.htmlで、両方のファイルが必要です

// index.html
<script src='vendor.js'></script>
<script src='app.js'></script>

BrowserifyまたはWebpackを使用して、app.jsがnpmを介してロードされたモジュールを「見る」ことができるようにするにはどうすればよいですか?外部とのバンドルを作成し、エイリアスを介して直接ファイル(たとえば、node_modules)を参照することは知っていますが、より自動で「Require.js」の少ないソリューションを見つけたいと思っています。 " お気に入り。

基本的に、依存関係を解決するためにapp.jsvendor.jsの内部を調べることができるように、2つをブリッジすることが可能かどうか疑問に思っています。これは単純で簡単な操作のように思えますが、この幅の広いWebのどこにも答えが見つからないようです。

ありがとう!

16
cnp

Webpackでは、複数のエントリポイントと CommonChunkPlugin を使用します。

webpack docs から取得:


アプリをapp.jsvendor.jsのように2つのファイルに分割するには、vendor.jsにベンダーファイルを要求できます。次に、以下に示すように、この名前をCommonChunkPluginに渡します。

module.exports = {
  entry: {
    app: "./app.js",
    vendor: ["jquery", "underscore", ...],
  },
  output: {
    filename: "bundle.js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(
        /* chunkName= */"vendor",
        /* filename= */"vendor.bundle.js"
    )
  ]
};

これにより、ベンダーチャンク内のすべてのモジュールがアプリチャンクから削除されます。 bundle.jsには、依存関係のないアプリコードのみが含まれるようになります。これらはvendor.bundle.jsにあります。

HTMLページで、vendor.bundle.jsの前にbundle.jsをロードします。

<script src="vendor.bundle.js"></script>
<script src="bundle.js"></script>

11
Johannes Ewald

すべてのベンダーファイル/モジュールを一覧表示し、 CommonChunkPlugin を使用することは確かに推奨される方法です。ただし、これはかなり面倒で、エラーが発生しやすくなります。

次のNPMモジュールについて考えてみます:fastclickおよびmprogressCommonJS モジュール形式を採用していないため、次のようにwebpackに手を渡す必要があります。

_require('imports?define=>false!fastclick')(document.body);
require('mprogress/mprogress.min.css');
var Mprogress = require('mprogress/mprogress.min.js'),
_

ここで、ベンダーチャンクにfastclickmprogressの両方が必要であると仮定すると、おそらくこれを試してみます。

_module.exports = {
  entry: {
    app: "./app.js",
    vendor: ["fastclick", "mprogress", ...]
_

残念ながら、それは機能しません。 require()の呼び出しを一致させる必要があります。

_module.exports = {
  entry: {
    app: "./app.js",
    vendor: [
      "imports?define=>false!fastclick", 
      "mprogress/mprogress.min.css", 
      "mprogress/mprogress.min.js", 
      ...]
_

_resolve.alias_のトリックがあっても、古くなります。これが私の回避策です。 CommonChunkPluginを使用すると、モジュールをベンダーチャンクに含めるかどうかを返すコールバックを指定できます。独自のソースコードが特定のsrcディレクトリにあり、残りが_node_modules_ディレクトリにある場合は、パスに基づいてモジュールを拒否するだけです。

_var node_modules_dir = path.join(__dirname, 'node_modules'),
    app_dir          = path.join(__dirname, 'src');

module.exports = {
  entry: {
    app: "./app.js",
  },
  output: {
    filename: "bundle.js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(
      /* chunkName= */"vendor",
      /* filename= */"vendor.bundle.js"
      function (module, count) {
       return module.resource && module.resource.indexOf(app_dir) === -1;
      }
    )
  ]
};
_

ここで、_module.resource_は、検討中のモジュールへのパスです。逆のこともできます。モジュールが_node_modules_dir_内にある場合、つまり次の場合にのみモジュールを含めます。

_       return module.resource && module.resource.indexOf(node_modules_dir) === 0;
_

しかし、私の状況では、「ソースソースツリーにないものはすべてベンダーチャンクに入れてください」と言いたいです。

お役に立てば幸いです。

26
sebastien.b
// vendor anything coming from node_modules
minChunks: module => /node_modules/.test(module.resource)

ソース: https://github.com/webpack/webpack/issues/2372#issuecomment-21314917

0
Alex