danielrvt
danielrvt

Reputation: 10926

Webpack 4: mini-css-extract-plugin + file-loader not loading assets

I'm trying to move assets (images and fonts) used in one of my .scssfiles, but it seems that they get ignored:

This is my .scss file:

@font-face {
    font-family: 'myfont';
    src: url('../../assets/fonts/myfont.ttf') format('truetype');
    font-weight: 600;
    font-style: normal;
}

body {
    color: red;
    font-family: 'myfont';
    background: url('../../assets/images/bg.jpg');
}

And this is my webpack.config.js:

const path = require('path');
const { CheckerPlugin } = require('awesome-typescript-loader');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    target: 'node',
    entry: path.resolve(__dirname, 'server.tsx'),
    output: {
        filename: 'server_bundle.js',
        path: path.resolve(__dirname, 'build'),
        publicPath: '/build'
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js', '.jsx']
    },
    module: {
        rules: [{
                test: /\.(tsx|ts)?$/,
                loader: 'awesome-typescript-loader',
                options: {
                    jsx: 'react'
                }
            },
            {
                test: /\.(scss|sass|css)$/,                
                use: [
                    MiniCssExtractPlugin.loader,
                    { loader: 'css-loader', options: { url: false, sourceMap: true } },
                    { loader: 'sass-loader', options: { sourceMap: true } },                    
                ]
            },
            {
                test: /\.(png|svg|jpg|jpeg|gif)$/,
                loader: 'file-loader',
                options: { outputPath: 'public/images' }
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                loader: 'file-loader',
                options: { outputPath: 'public/fonts' }
            }
        ]
    },
    plugins: [
        new CheckerPlugin(),
        new MiniCssExtractPlugin({
            filename: 'public/styles_bundle.css',
            chunkFilename: "public/styles/[id].css"
        })
    ]
}

I'm getting this .css file in my browser as the output (Note the name of the image):

body {
  color: red;
  background: url("../../assets/images/myimage.jpg"); 
}

And in my public directory I get this:

public/
    styles_bundle.css

There are two problems here:

  1. Fonts are not compiled (No public/fonts/etc...)
  2. Images are not compiled

I've been trying everything, but I don't know what may be happening here... Any Ideas?

Upvotes: 14

Views: 17916

Answers (6)

PattyOK
PattyOK

Reputation: 991

Had the exact problem with webpack 5. The answer is in Asset Modules

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
   assetModuleFilename: 'images/[hash][ext][query]' //set the pattern for your filename here
  },
  module: {
    rules: [
      {
        test: /\.png/,
        type: 'asset/resource' //replaces file-loader, url-loader etc
      }
    ]
  },
};

Upvotes: 0

thomi
thomi

Reputation: 1697

The mini-css-extract-plugin has a 'publicPath' option (see here). It basically tells the generated css where the external resources like fonts, images, etc are to be found. In my case, setting it to '../' and configuring all the file loaders to their proper directories, this worked perfectly. Basically looks like:

rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '/public/path/to/',  // <-- This is what was helping. 
            },
          },
          'css-loader',
        ],
      },
    ],

Upvotes: 1

cda01
cda01

Reputation: 1278

I had this issue too. I was using the following versions:

package.json

"mini-css-extract-plugin": "^0.10.1",
"webpack": "^5.3.1",

For me everything was compiling just fine until I added the following into a scss file:

.xmas {
    background-image: url("./img/Xmas2020/SurveyBanner.png");
    height: 150px;
}

The backgound-image url was the problem. When I changed it to an absolute path it worked:

.xmas {
    background-image: url("/img/Xmas2020/SurveyBanner.png");
    height: 150px;
}

webpack.config.js

This is just to show how I was putting images into the output directory. I guess there are different ways to do this, but I was using CopyWebpackPlugin.

plugins: [
   new CopyWebpackPlugin({
        patterns: [
            { from: './src/static/img', to: './img', force: true },
        ]
    }),
  ]

This link helped me https://github.com/webpack-contrib/mini-css-extract-plugin/issues/286#issuecomment-455917803

Upvotes: 0

Santhanam
Santhanam

Reputation: 348

try the below configuration

{
    test: /\.s[ac]ss$/i,
    use: [
      {
        loader: MiniCssExtractPlugin.loader, 
        options: {
            publicPath: ''
        }
    },
    {
        loader: "css-loader", 
        options: { sourceMap: true}
    },{
      loader: "sass-loader", 
      options: { sourceMap: true }
    }
    ]
  },
  {
    test: /\.(png|jpg|jpeg|gif)$/i,
    loader: 'file-loader',
    options: { outputPath: 'assets/images', publicPath: '../images', useRelativePaths: true }
  },
  {
    test: /\.(woff|woff2|eot|ttf|otf)$/i,
    loader: 'file-loader',
    options: { outputPath: 'assets/fonts', publicPath: '../fonts', useRelativePaths: true }
  }

enter image description here

After this my scss file started accepting the relative URL and the compiled files also mapped accordingly using relative path.

Upvotes: 2

David Zambrano
David Zambrano

Reputation: 658

you need url-loader

           {
               test: /\.(jpg|png|gif|woff|eot|ttf|svg)/,
                use: {
                    loader: 'url-loader', // this need file-loader
                    options: {
                        limit: 50000

                    }
                }
           }

Upvotes: 4

Sheng
Sheng

Reputation: 834

I have just fixed a similar issue. If you change the url option to true, you might see failed image URL references.

{ loader: 'css-loader', options: { url: false, sourceMap: true } },

Or you can manual check whether the path reference is correct.

url('../../assets/images/bg.jpg')

I think the images folder doesn't get created because all the image resource links are incorrect.

For the problem I was fixing, the references were all wrong and I couldn't fix them so I just used this webpack copy plugin to copy files to the right dist folder location.

Upvotes: 8

Related Questions