es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

css-loader crea un archivo de imagen vacío si se incluye file-loader en la configuración de webpack.

Mientras investigaba sobre webpack, me encontré con un ejemplo en la guía oficial “Asset Management” que no funciona como se esperaba. Se utiliza la misma imagen para insertar una etiqueta en el DOM de un archivo js y como fondo de un elemento en los estilos css. Cuando se utiliza style-loader y css-loader para el css, así como file-loader para las imágenes, se generan dos archivos de salida para una imagen: uno normal para el elemento y otro vacío para el fondo en el css. Si eliminamos toda la lógica asociada al file-loader del proyecto, entonces el archivo de imagen para el fondo en el css es correcto. ¿Por qué no funciona el ejemplo oficial como se esperaba?

proyecto

  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
    |- style.css
    |- index.js
    |- icon.png
  |- /node_modules

src/index.js

  import _ from 'lodash';
  import './style.css';
  import Icon from './icon.png';

  function component() {
    const element = document.createElement('div');

    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');

    const myIcon = new Image();
    myIcon.src = Icon;
    element.appendChild(myIcon);

    return element;
  }
  document.body.appendChild(component());

src/style.css

.hello {
  color: red;
  background: url('./icon.png');
}

webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader',
                ],
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: [
                    'file-loader',
                ],
            },
        ],
    },    
};
Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El ejemplo oficial no está funcionando como se esperaba porque el archivo CSS se está procesando por separado del archivo JS, lo que provoca que se ejecuten dos instancias de file-loader. Esto resulta en la generación de dos archivos de salida diferentes para la misma imagen. Un archivo se utiliza para el elemento y el otro está vacío (0 bytes) y se utiliza para el fondo en CSS.

    Para solucionar este problema, necesitamos utilizar la misma instancia de file-loader tanto para los archivos JS como para los archivos CSS. Esto se puede lograr modificando la configuración de webpack de la siguiente manera:

    module.exports = {
      // ...
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: {
                  importLoaders: 1,
                },
              },
              'resolve-url-loader',
            ],
          },
          {
            test: /\.(png|svg|jpg|gif)$/,
            use: [
              {
                loader: 'file-loader',
                options: {
                  name: '[name].[ext]',
                  outputPath: 'images',
                },
              },
            ],
          },
        ],
      },
    };
    

    Al utilizar resolve-url-loader en la cadena de carga del CSS y configurar la opción publicPath para file-loader, podemos asegurarnos de que tanto el elemento como el fondo en CSS estén correctamente vinculados al mismo archivo de salida.

Comments are closed.