Search code examples
webpackmetalsmith

Bundled assets seem to have a wrong path when using webpack's file-loader


I am new to Webpack and have a hard time melting it together with metalsmith. Currently I have the following folder structure:

├───content         // markdown files
├───dist
│   ├───assets      // contains bundle.js
│   │   ├───fonts   // contains ttf's with hashed names 
│   │   └───img     // contains img's with hashed names
│   └───site        // contains html files with <script src="../assets/bundle.js"></script>
└───src
    ├───assets
    │   ├───fonts   // contains real-name-fonts.ttf
    │   ├───img     // contains real-name-images.jpg
    │   ├───js      // contains my entry point site.js
    │   └───scss
    ├───config
    ├───layouts
    ├───partials
    └───scripts

This is what my webpack.config.js looks like

module.exports = {
    mode: 'development', 
    entry: join(paths.webpackSrc, 'js', 'site.js'), // points to 'src/assets/js/site.js'
    plugins: [
        new CleanWebpackPlugin()
    ],
    output: {
        filename: 'bundle.js',
        path: paths.webpackDst, // points to 'dist/assets'
        publicPath: paths.webpackPublicPath, // points to '/assets/'
    },
    devServer: {
        contentBase: './dist',
    },
    module: {
        rules: [
            {
                test: /\.(scss|css)$/,
                use: [
                    { loader: 'style-loader' },
                    { loader: 'css-loader' },
                    { loader: 'postcss-loader', options: { plugins: function () { return [require('autoprefixer')]; } } },
                    { loader: 'sass-loader' }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                loader: 'file-loader',
                options: {
                    outputPath: 'fonts'
                }
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                loader: 'file-loader',
                options: {
                    outputPath: 'img'
                }
            },        
        ]
    }
}

And this is a part from my entry point site.js

import 'bootstrap';
import 'popper.js'; 
import '../scss/_stylesheet.scss';

import Avatar from '../img/avatar.jpg';

var avatarImgNavbar = document.getElementById('avatar');
avatarImgNavbar.src = Avatar;

I can see webpack picking up the assets and they do show up in the correct corresponding dist/assets/ folders. However an html file being stored in dist/site does not seem to find the assets, though styles coming from scss are getting applied.

Why is that? And how can I fix this?


Solution

  • Figured it out by myself. This publicPath: '/assets/' should actually be publicPath: '../assets/' and then the asset paths are correct.