Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack relative css url() with file-loader / css-loader

Im quite new to webpack/npm and i'm trying to get my head around how to work with css urls in other project dependancies.

Folder structure

src
  fonts/
  scss/
    app.scss
  js/
    app.js
  img/
  index.html

webpack.config.js

var path = require('path');
var extractPlugin = require('extract-text-webpack-plugin');
var cleanWebpackPlugin = require('clean-webpack-plugin');
var htmlWebpackPlugin = require('html-webpack-plugin');
var webpack = require("webpack");

module.exports = {
    entry: './src/js/app.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'js/app.js'
    },
    devServer: {
        stats: 'errors-only',
        compress: true,
        open: true,
        port: 9000
    },
    module: {

        rules: [

            // ES6 -> ES5 transpiler

            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['es2015']
                    }
                }
            }, 

            // SCSS to CSS -> Autoprefix -> Load CSS

            {
                test: /\.(scss|css)$/,
                use: extractPlugin.extract({
                    use: [
                        'css-loader',
                        {
                            loader: 'postcss-loader', 
                            options: { 
                                plugins: (loader) => [require('autoprefixer')()]
                            }
                        },
                        'sass-loader'
                    ]
                })
            },

            // HTML Loader
            {
                test: /\.html$/,
                use: ['html-loader']
            },

            // Image Loader
            {
                test: /\.(jpg|png|svg|gif)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            outputPath: 'img/',
                            name: '[name].[ext]'
                        }
                    }
                ]
            },
            // Font Loader
            {
                test: /\.(eot|ttf|woff)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            outputPath: 'fonts/',
                            name: '[name].[ext]'
                        }
                    }
                ]
            }


        ]

    }, 
    plugins: [
        new extractPlugin({filename: 'scss/app.css'}),
        new cleanWebpackPlugin(['dist']),
        new htmlWebpackPlugin({ template: 'src/index.html' }),
        new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery' })
    ]
};

I've successfully included lightGallery in my project like so:

app.js

import 'lightgallery';

app.scss

@import '~lightgallery/dist/css/lightgallery.css';

The light gallery stylesheet references fonts which i'm successfully loading into the fonts/ using the webpack file-loader

My problem is that the built css file is trying to reference the fonts relative from the scss folder instead of my root.

ie: http://localhost:9000/scss/img/loading.gif

I need all assets linked to from css to resolve from my root dir

ie http://localhost:9000/img/loading.gif

Is there anyway i can configure my css-loader to prepend all url's with a / ?

Help!

like image 288
Samuel Avatar asked Jan 03 '23 23:01

Samuel


1 Answers

The file-loader respects output.publicPath, but because you've not set it, the resulting path will be a relative path. You can set the public path to /.

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/app.js',
    publicPath: '/'
},

This will affect other loaders and plugins as well, which handle any assets. This is generally what you want and therefore recommended, but if you'd like to change it only for specific files you can use the publicPath option on file-loader.

{
    loader: 'file-loader',
    options: {
        outputPath: 'img/',
        name: '[name].[ext]',
        publicPath: '/'
    }
}
like image 156
Michael Jungo Avatar answered Jan 14 '23 13:01

Michael Jungo