1. ホーム
  2. javascript

[解決済み] Webpackのファイルローダー出力 [object モジュール]について

2023-04-18 13:42:42

質問

私はwebpackを HtmlWebpackPlugin , html-loaderfile-loader . 私はフレームワークを使わず、タイプスクリプトだけを使ったシンプルなプロジェクト構造を持っています。したがって、私はHTMLコードを直接 index.html . また、この HTML ファイルをテンプレートとして HtmlWebpackPlugin .

すべてのWebサイトがそうであるように、私はassetsフォルダにPNGを参照する画像を置く必要があります。 file-loader の中に新しいファイル名を入れて、ファイルを正しく読み込ませる必要があります。 src タグの中に置くべきですが、そうはなっていません。代わりに src タグの値として、私は [object Module] . 私は、この file-loader が何らかのオブジェクトを生成し、そのオブジェクトが .toString() メソッドが実行されたとき、このように表現されます。しかし、私は file-loader は正常にファイルを処理し、新しい名前を出力パスに出力していることがわかります。エラーは出ていません。 以下は私の webpack の設定と index.html .

const projectRoot = path.resolve(__dirname, '..');

{
  entry: path.resolve(projectRoot, 'src', 'app.ts'),
  mode: 'production',
  output: {
    path: path.resolve(projectRoot, 'dist'),
    filename: 'app.bundle.js'
  },
  resolve: {
    extensions: ['.ts', '.js']
  },
  module: {
    rules: [
      {
        test: /\.html$/i,
        use: 'html-loader'
      },
      {
        test: /\.(eot|ttf|woff|woff2|svg|png)$/i,
        use: 'file-loader'
      },
      {
        test: /\.scss$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              hmr: false
            }
          },
          {
            loader: 'css-loader',
            options: {
              sourceMap: false
            }
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: false
            }
          }
        ]
      },
      {
        exclude: /node_modules/,
        test: /\.ts$/,
        use: 'ts-loader'
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(projectRoot, 'src', 'index.html')
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[hash].css',
      chunkFilename: '[id].[hash].css',
      ignoreOrder: false
    })
  ]
};

index.htmlを表示します。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
  </head>
  <body class="dark">
    <header>
      <nav class="navigation">
        <div class="left">
          <img src="assets/logo.png" class="logo"> <!-- This logo is output as [object Module] -->
        </div>
        <div class="right">

        </div>
      </nav>
    </header>
  </body>
</html>

プロジェクトの構成です。

config/
    webpack.config.js
dist/
src/
    styles/
    assets/
        logo.png
    index.html
    app.ts

編集 私のpackage.jsonの依存関係です。

"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.2.0",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"ts-loader": "^6.2.1",
"typescript": "^3.7.2",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"

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

ファイルローダーあたり ドキュメント :

デフォルトでは、file-loaderはESモジュールの構文を使用したJSモジュールを生成します。モジュールの連結やツリーシェイクのように、ESモジュールを使用することが有益なケースもあります。

webpack は ES モジュールを解決しているようです require() の呼び出しを、以下のようなオブジェクトに変換しているようです。 {default: module} のようなオブジェクトを呼び出します。この挙動は多少議論の余地があり、以下の記事で説明されています。 この問題 .

したがって、あなたの src 属性が正しく解決されるためには default プロパティにアクセスできる必要があります。フレームワークを使用している場合、このようなことができるはずです。

<img src={require('assets/logo.png').default}/> <!-- React -->
<!-- OR -->
<img src="require('assets/logo.png').default"/> <!-- Vue -->

また、file-loaderのCommonJSモジュール構文を有効にすると、webpackがモジュールそのものを直接解決するようになります。設定 esModule:false を webpack の設定に追加します。

webpack.config.jsに記述します。

 {
        test: /\.(png|jpe?g|gif)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              esModule: false,
            },
          },
        ],
      },