web-dev-qa-db-ja.com

Webpack Uncaught ReferenceError:bundle.jsからnode_modulesを削除した後、requireが定義されていません

bundle.js      2.83 kB   0  [emitted]  main
bundle.js.map  3.36 kB   0  [emitted]  main

以下のコードをカスタム外部で追加すると、node_modulesbundle.js出力に直接含まれないようにすることができます。

bundle.js      743 kB       0  [emitted]  main
bundle.js.map  864 kB       0  [emitted]  main

これにより、バンドルサイズが大幅に削減されます。 しかし、ブラウザで次のようなエラーが発生します:Uncaught ReferenceError: require is not definedブラウザで。誰かがこの問題を修正する方法を知っていますか?

var path = require("path"),
  fs = require("fs");

// return what's in the node modules folder apart from ".bin"
const nodeModules = fs
  .readdirSync("./node_modules")
  .filter(d => d != ".bin");

/**
 * Remove non-direct references to modules from bundles
 *
 * @param {any} context
 * @param {any} request
 * @param {any} callback
 * @returns
 */
function ignoreNodeModules(context, request, callback) {
  // IF someone is importing a module e.g. "import {chatModule} from
  // "./components/chat" using a relative path, then we're okay with them bringing
  // in into the bundle
  if (request[0] == ".") 
    return callback();

  // IF someone is doing "import {Subject} from "rxjs/Subject" only want to know
  // if first part is a node_module
  const module = request.split("/")[0];
  if (nodeModules.indexOf(module) !== -1) {
    // append "commonjs " - tells webpack to go and grab from node_modules instead
    // of including in bundle
    return callback(null, "commonjs " + request);
  }

  return callback();
}

module.exports = {
  entry: "./src/index.tsx",
  output: {
    filename: "bundle.js"
  },
  devtool: "source-map",
  resolve: {
    extensions: ["", ".ts", ".tsx", ".js"]
  },
  module: {
    loaders: [
      {
        test: /\.ts(x?)$/,
        loader: "ts-loader"
      }
    ]
  },
  // Runs our custom function everytime webpack sees a module
  externals: [ignoreNodeModules]
}
5
Clement

_node_modules_が含まれていないため、バンドルは小さくなりますが、これは根本的な問題につながります:依存関係をブラウザーに送信しなくなったため、コードを送信できませんまったく実行します。ご存知かもしれませんが、ブラウザはrequire()をネイティブにサポートしていないため、現在のignoreNodeModules関数はWebpackにバンドルをスキップして、require()のままにするように指示しますが、ブラウザはそれを処理する方法を知りません。

バンドルサイズを縮小したい場合は、Webpackの コード分割 を使用して、各ページ/セクションに必要な依存関係のみをバンドルすることを検討してください。または、 RequireJS などのブラウザ側のrequire()ローダーの使用を検討することもできます。

externalsの使用は、サーバー側のNodeライブラリを配布する場合にのみ非常に役立ちます。この場合、ライブラリのコンシューマーは、ライブラリにバンドルするのではなく、依存関係を提供することが期待されます。

externals に関するドキュメントも、この問題に関する詳細なコンテキストについて読む価値があります。

10
Aurora0001