Output del caricatore di file Webpack [modulo oggetto]


40

Sto usando il webpack con HtmlWebpackPlugin, html-loadere file-loader. Ho una struttura di progetto semplice in cui non uso quadri, ma solo dattiloscritto. Pertanto, scrivo il mio codice HTML direttamente su index.html. Uso anche questo file HTML come modello in HtmlWebpackPlugin.

Come tutti i siti Web, devo inserire un'immagine che si riferisce a un file PNG nella mia cartella delle risorse. file-loadercaricare correttamente il file, inserire il nuovo nome file all'interno del srctag ma non è quello che sta succedendo. Invece, come valore del srctag, ho [object Module]. Presumo che file-loaderemetta un oggetto ed è rappresentato in questo modo quando .toString()viene eseguito il suo metodo. Tuttavia, posso vedere che file-loaderha elaborato correttamente il file ed emesso con un nuovo nome nel percorso di output. Non ricevo errori. Ecco la mia configurazione webpack e 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>

Struttura del progetto:

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

Modifica le mie dipendenze 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"

Risposte:


70

Per il file-loader docs :

Per impostazione predefinita, il caricatore di file genera moduli JS che utilizzano la sintassi dei moduli ES. Ci sono alcuni casi in cui l'uso dei moduli ES è vantaggioso, come nel caso della concatenazione dei moduli e della vibrazione degli alberi.

Sembra che il webpack risolva le require()chiamate del modulo ES a un oggetto simile al seguente: {default: module}invece che al modulo appiattito stesso. Questo comportamento è alquanto controverso ed è discusso in questo numero .

Pertanto, per ottenere la srccorretta risoluzione dell'attributo, è necessario poter accedere alla defaultproprietà del modulo esportato. Se stai usando un framework, dovresti essere in grado di fare qualcosa del genere:

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

In alternativa, è possibile abilitare la sintassi del modulo CommonJS del caricatore di file, che il webpack risolverà direttamente sul modulo stesso. Imposta esModule:falsenella configurazione del tuo webpack.

webpack.config.js:

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

Ha funzionato Tuttavia è ancora un po 'magico. Se hai idee sul perché sia ​​così, potresti spiegarlo anche nella tua risposta? Grazie.
Bora,

@Bora - Ha fatto un po 'più di ricerca e una risposta aggiornata.
stellr42,

grazie, questo è esattamente ciò di cui ho bisogno
Matan Tubul,

Questo mi ha morso durante un aggiornamento da Angular 8a Angular 9come quello portato file-loaderdalla versione 4.2.0a 6.0.0. Usandolo require(...).defaultriparato per me.
ebhh2001,

8

La soluzione suggerita da @ stellr42 esModule: falsenella file-loaderconfigurazione è la soluzione alternativa migliore al momento.

Tuttavia, questo è in realtà un bug in html-loadercui viene tracciato qui: https://github.com/webpack-contrib/html-loader/issues/203

Sembra che il supporto ES modulo inserito file-loader, css-loadere altri amici, ma html-loaderè stato mancato.

Una volta risolto questo bug, sarà meglio rimuovere esModule: falsee semplicemente aggiornare html-loader, poiché i moduli ES offrono alcuni vantaggi minori (come menzionato nei documenti )

In alternativa, se (come me), hai riscontrato questo problema perché hai riscontrato problemi nel caricamento di un'immagine da CSS (anziché da HTML), la soluzione è solo l'aggiornamento css-loader, non è necessario disabilitare i moduli ES.


2

Questo succede con il caricatore di file versione 5.0.2, la versione precedente funziona bene senza chiamare la defaultproprietà


0

Ho appena aggiornato il mio caricatore di file a ^ 5.0.2 minuti fa.

So che è esModule: falsestata la soluzione suggerita ma che non ha funzionato per me.

La mia soluzione era quella <img src={require('assets/logo.png').default}/>che era strana. Prima volta usando .defaultma ha funzionato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.