Keluaran file-loader Webpack [Modul objek]

40

Saya menggunakan paket web dengan HtmlWebpackPlugin, html-loaderdan file-loader. Saya memiliki struktur proyek sederhana di mana saya tidak menggunakan kerangka kerja, tetapi hanya naskah. Jadi, saya menulis kode HTML saya langsung ke index.html. Saya juga menggunakan file HTML ini sebagai templat saya di HtmlWebpackPlugin.

Karena semua situs web harus saya masukkan gambar yang merujuk ke PNG di folder aset saya. file-loaderharus memuat file dengan benar memasukkan nama file baru di dalam srctag tetapi bukan itu yang terjadi. Sebagai gantinya, sebagai nilai srctag, saya punya [object Module]. Saya menganggap file-loadermemancarkan beberapa objek dan diwakili seperti ini ketika .toString()metodenya dijalankan. Namun, saya dapat melihat bahwa file-loaderfile telah diproses dengan sukses dan dipancarkan dengan nama baru ke jalur output. Saya tidak mendapatkan kesalahan. Ini adalah konfigurasi webpack saya dan 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>

Struktur proyek:

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

Edit dependensi package.json saya:

"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"
Bora
sumber

Jawaban:

70

Per dokumen pemuat file :

Secara default, file-loader menghasilkan modul JS yang menggunakan sintaks modul ES. Ada beberapa kasus di mana menggunakan modul ES bermanfaat, seperti dalam kasus penggabungan modul dan pengocokan pohon.

Tampaknya webpack menyelesaikan require()panggilan modul ES ke objek yang terlihat seperti ini {default: module}:, alih-alih ke modul yang diratakan itu sendiri. Perilaku ini agak kontroversial dan dibahas dalam masalah ini .

Oleh karena itu, untuk mendapatkan srcatribut Anda untuk diselesaikan dengan benar, Anda harus dapat mengakses defaultproperti modul yang diekspor. Jika Anda menggunakan kerangka kerja, Anda harus dapat melakukan sesuatu seperti ini:

<img src="require('assets/logo.png').default"/>

Atau, Anda dapat mengaktifkan sintaksis modul CommonJS pemuat file, yang webpack akan atasi langsung ke modul itu sendiri. Diatur esModule:falsedalam konfigurasi webpack Anda.

webpack.config.js:

 {
        test: /\.(png|jpe?g|gif)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              esModule: false,
            },
          },
        ],
      },
stellr42
sumber
Itu berhasil. Namun itu masih sedikit ajaib. Jika Anda memiliki ide tentang mengapa hal ini dapatkah Anda juga menjelaskannya dalam jawaban Anda? Terima kasih.
Bora
@Bora - Melakukan sedikit riset dan jawaban yang diperbarui.
stellr42
terima kasih, inilah yang saya butuhkan
Matan Tubul
Ini menggigit saya selama pembaruan dari Angular 8ke Angular 9yang dibawa file-loaderdari versi 4.2.0ke 6.0.0. Menggunakannya require(...).defaultuntuk saya.
ebhh2001
8

@ stellr42 menyarankan perbaikan esModule: falsedalam file-loaderkonfigurasi Anda adalah solusi terbaik saat ini.

Namun, ini sebenarnya adalah bug html-loaderyang sedang dilacak di sini: https://github.com/webpack-contrib/html-loader/issues/203

Sepertinya dukungan ES Modul telah ditambahkan ke file-loader, css-loaderdan teman-teman lain, tapi html-loaderitu tidak terjawab.

Setelah bug ini diperbaiki, akan lebih baik untuk menghapus esModule: falsedan hanya memutakhirkan html-loader, karena Modul ES menawarkan beberapa manfaat kecil (seperti yang disebutkan dalam dokumen )

Atau, jika (seperti saya), Anda menemukan masalah ini karena Anda mengalami masalah saat memuat gambar dari CSS (bukan dari HTML), maka perbaikannya hanya untuk memutakhirkan css-loader, tidak perlu menonaktifkan Modul ES.

brindyblitz
sumber
2

Ini terjadi pada file-loader versi 5.0.2, versi sebelumnya berfungsi dengan baik tanpa memanggil defaultproperti

Jora
sumber
0

Baru saja memperbarui pemuat file saya ke ^ 5.0.2 menit yang lalu.

Saya tahu esModule: falseadalah perbaikan yang disarankan tetapi tidak berhasil untuk saya.

Perbaikan saya adalah <img src={require('assets/logo.png').default}/>yang aneh. Pertama kali menggunakan .defaulttetapi berhasil.

kerubim
sumber