Webpack dosya yükleyici çıkışları [nesne Modülü]


40

Birlikte WebPack kullanıyorum HtmlWebpackPlugin, html-loaderve file-loader. İçinde çerçeve yok, sadece daktilo kullandığım basit bir proje yapım var. Böylece, HTML kodumu doğrudan yazıyorum index.html. Bu HTML dosyasını şablonum olarak da kullanıyorum HtmlWebpackPlugin.

Tüm web sitelerinde olduğu gibi, öğeler klasörümdeki PNG'ye işaret eden bir resim koymam gerekiyor. file-loaderdosyayı doğru şekilde yüklemeli, yeni dosya adını srcetiketin içine koymalı, ancak olan şey bu değil. Bunun yerine, srcetiketin değeri olarak var [object Module]. file-loaderBazı nesne yayar ve onun .toString()yöntemi çalıştırıldığında böyle temsil edilir varsayalım . Ancak, file-loaderdosyayı başarıyla işlediğini ve çıktı yoluna yeni bir adla yaydığını görebiliyorum . Hata almıyorum. İşte benim webpack yapılandırmam ve 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>

Proje yapısı:

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

Edit My package.json bağımlılıkları:

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

Yanıtlar:


70

Dosya yükleyici belgelerine göre :

Varsayılan olarak, dosya yükleyici ES modülleri sözdizimini kullanan JS modüllerini oluşturur. Modül birleştirme ve ağaç çalkalama gibi ES modüllerinin kullanılmasının faydalı olduğu bazı durumlar vardır.

Görünüşe göre webpack , düzleştirilmiş modülün kendisi yerine ES modül require()çağrılarını şöyle görünen bir nesneye çözüyor {default: module}. Bu davranış biraz tartışmalıdır ve bu konuda tartışılmaktadır .

Bu nedenle, srcözniteliğinizin doğru şekilde çözülmesini defaultsağlamak için dışa aktarılan modülün özelliğine erişebilmeniz gerekir . Bir çerçeve kullanıyorsanız, böyle bir şey yapabilmeniz gerekir:

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

Alternatif olarak, web paketinin doğrudan modülün kendisine çözümleyeceği dosya yükleyicinin CommonJS modülü sözdizimini etkinleştirebilirsiniz. Web esModule:falsepaketi yapılandırmanızda ayarlayın .

webpack.config.js:

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

İşe yaradı. Ancak yine de biraz sihir. Durumun neden böyle olduğuna dair fikirleriniz varsa cevabınızda da açıklayabilir misiniz? Teşekkürler.
Bora

@Bora - Biraz daha araştırma yaptı ve cevap güncellendi.
stellr42

teşekkürler, tam olarak ihtiyacım olan şey
Matan Tubul

Bu güncelleme yaparken ısırdı Angular 8için Angular 9o getirdi file-loadersürümden 4.2.0için 6.0.0. require(...).defaultBunu kullanmak benim için düzeltti.
ebhh2001

8

@ ait stellr42 önerdiği düzeltme esModule: falsesizin de file-loaderyapılandırma geçerli zamanda en iyi çözüm olduğunu.

Ancak, bu aslında html-loaderburada takip edilen bir hatadır : https://github.com/webpack-contrib/html-loader/issues/203

Bu ES Modül desteği eklendi benziyor file-loader, css-loaderve diğer arkadaşlar, ancak html-loaderkaçırılan.

Bu hata giderildikten sonra , ES Modülleri bazı küçük faydalar sunduğundan ( dokümanlarda belirtildiği gibi ) kaldırmak esModule: falseve basitçe yükseltmek daha iyi olacaktır.html-loader

Alternatif olarak, (benim gibi), CSS'den (HTML yerine) bir görüntü yükleme konusunda sorun yaşadığınız için bu sorunu bulduysanız , düzeltme sadece yükseltmek içindir css-loader, ES Modüllerini devre dışı bırakmanıza gerek yoktur.


2

Bu dosya yükleyici sürüm 5.0.2'de gerçekleşir, önceki sürüm defaultözellik çağrılmadan iyi çalışır


0

Dosya yükleyicimi ^ 5.0.2 dakika önce güncelledi.

esModule: falseÖnerilen düzeltme olduğunu biliyorum ama bu benim için işe yaramadı.

Benim düzeltmem <img src={require('assets/logo.png').default}/>tuhaftı. İlk kez kullanarak .defaultama işe yaradı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.