31

I have a problem with getting my mp3 files to work using the webpack file loader.

This is the issue:

I have a mp3 file on my harddisk, that if I open using chrome by for example "c:\somefolder\somemp3file.mp3" opens up in a tab in the browser and plays just fine.

However, when I serve the exact same file using webpack it does not work. I have configured the loader in webpack like this:

{
    test: /\.(gif|jpg|png|mp3|aac|ogg)$/,
    loader: 'file'
}

Then, when I'm trying to link to the file I require it inside my javascript, like this:

require('file!./../content/somemp3file.mp3');

this correctly returns me the url for the mp3 file.

If I try to manually go to localhost:8080 followed by the url returned by require, the mp3 player in Chrome pops up like I expect it to, but the file cannot be played, and it's not possible to click on the play button like the file is corrupted or something.

Anyone knows what I'm doing wrong here?

Øyvind Bråthen
  • 59,338
  • 27
  • 124
  • 151
  • 4
    Try removing the `file!` when you call `require()`. That actually causes a second `.mp3` file to be generated, probably ~80bytes. If you look at the file it's just a module export of a string (URL to the actual `.mp3` file that is bundled). So leave the webpack config as you have it, and in your js file, `var src = require('./../content/somemp3file.mp3'); document.getElementById('myAudio').src = src;` – Eric Lease Feb 03 '17 at 15:06

8 Answers8

17

Use file-loader like this:

{
    test: /\.mp3$/,
    loader: 'file-loader'
}
nawaz1989
  • 410
  • 4
  • 7
14

Start off with webpack 5, Asset Modules replaces the old raw-loader, url-loader and file-loader.

Add the following rule to your webpack.config.js file,

   rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif|ogg|mp3|wav)$/i,
        type: 'asset/resource',
      },
   ]

In your project .js file, create an audio file and play it like this,

import myAudioResource from './path-to-your-audio-file/audio.wav';
const myAudio = new Audio(myAudiolResource);
myAudio.play();

You don't have to configure images and audios separately. asset/resource can process (png|svg|jpg|jpeg|gif|ogg|mp3|wav) all at a time.

You can change the folder of emitted files by setting output.assetModuleFilename in your webpack configuration. For example, the following script will emit your images and audio files under the dist/assets/ folder.

  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
    assetModuleFilename: 'assets/[hash][ext][query]' // add this line
  },

For more information, check the official doc Asset Modules.

Chris Weber
  • 5,555
  • 8
  • 44
  • 52
shen
  • 933
  • 10
  • 19
  • Thanks for the detailed answer – just a heads-up that there's a typo: `myAudiolResource` should be `myAudioResource` – NaN Aug 28 '23 at 15:50
7

https://stackoverflow.com/a/41158166/11878375 - it's correctly answer, but define SRC like this:

var path = require('path');

var SRC = path.resolve(__dirname, 'src/main/js');

For example, I am using react-chat-ui with webpack and this is my webpack.config.js:

const path = require('path');

const SRC = path.resolve(__dirname, 'node_modules');

module.exports = {
  entry: './jsx/App.jsx',
  mode: "development",
  output: {
    path:
        '/java/helios-backend/src/main/resources/static/js'
        // __dirname + '/js/'
    ,
    filename: 'bundle.js'
  },
  devtool: '#sourcemap',
  stats: {
   colors: true,
   reasons: true
  },
  module: {
    rules: [
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loaders: ['babel-loader']
      },
      {
        test: /\.(gif|png|jpe?g|svg)$/i,
        use: [
          'file-loader',
          {
            loader: 'image-webpack-loader',
            options: {
              bypassOnDebug: true,
              disable: true, 
            },
          },
        ]},
      {
        test: /\.mp3$/,
        include: SRC,
        loader: 'file-loader'
      }

    ]
  }
};

And do not forget to install the file-loader before:

npm install file-loader --save-dev
5

This is how I process mp3 files using Webpack in Nuxt 2:

  build: {
  
    loaders: {
      vue: {
        transformAssetUrls: {
          audio: 'src',
        },
      },
    },

    extend(config, ctx) {
      config.module.rules.push({
        test: /\.mp3$/,
        loader: 'file-loader',
        options: {
          name: '[path][name].[ext]',
        },
      })
    },
  },

Now you can write <audio src="@/assets/water.mp3"></audio> in your templates and it should work.

Jérôme Pott
  • 185
  • 2
  • 6
3

My solution: install the file-loader. Update webpack.config.js:

// webpack.config.js
rules: [
            {
                test: /\.mp3$/,
                loader: 'file-loader',
                options: {
                    name: '[path][name].[ext]'
                }
            }

Project.js :

const smthn = require('../sound.mp3');
const sound = new Audio('./sound.mp3');
(() => sound.play())();
Alex
  • 41
  • 2
0

Check the version of the file-loader, I solved this by upgrading the file-loader from 4.x.x to 6.x.x, then add mp3 to the normal webpack config plugin settings for files =>

// webpack.config.js

      { 
        test: /\.(gif|png|jpe?g|svg|xml|mp3)?$/i,
        use: "file-loader"
      }
      // OR
      {
        test: /\(mp3|wav|mpe?g|ogg)?$/i,
        use: 'file-loader'
      }
      
      // OR BOTH
alfrednoble
  • 91
  • 1
  • 5
0
// webpack.config.js
{
    test: /\.(mp3|wav)$/,
    loader: 'file-loader',
    query: {
        name: 'media/[name].[ext]'
    }
}
GrumpyGary
  • 201
  • 2
  • 6
0

This worked for me in an electron application with React :

npm install file-loader

then added this in webpack.common.js inside module object and inside rules array :

  {
    test: /\.(mp3|wav)$/,
    loader: "file-loader",
  }

then simply import your_sound from "/your_path/your_sound.wav";

Vaggelis
  • 912
  • 5
  • 17
  • That's for older version of Webpack. No need additional loader for 5-th version. `asset/resource` type for the same operation out of the box. – hastrb Oct 25 '22 at 22:09