2

I have created the html boilerplate with webpack. The problem which i'm facing is, if i call image in scss like "background: url('/img/img.png');" it doesn't taking. Here, I've attached the webpack file and folder structure. I used to try with "url-loader", this is also not working. Please help someone to fix this issue, because i have been tried so long to get this done but still can't able to find the solution.

This is my folder structure,

Project
     |   
     +-- html
     |  |  
     |  +-- css
     |  +-- img
     |  +-- js
     |  +-- index.html
     |    
     +-- src
     |  |  
     |  +-- js
     |  +-- scss

webpack file

'use strict';
let webpack = require('webpack');
let path = require('path');
let nodeModulesPath = path.join(__dirname, 'node_modules');
let ExtractTextPlugin = require("extract-text-webpack-plugin");
let exp = []; // multiple exports array

// Exports configs for each language
let configs = [
    {
        name: 'min',
        entry: './src/index.js',
        scssRule: {
            test: /\.scss$/,
            use: ExtractTextPlugin.extract({
                use: [{
                    loader: "css-loader",
                    options: { minimize: true },
                },
                {
                    loader: "sass-loader",
                    options: { minimize: true },
                },
                ],
                fallback: "style-loader"
            }),
        }
    }
];

// Generate exports module for each config
for (let c of configs) {
    var e = {
        context: __dirname,
        watch: true,
        entry: c.entry,
        output: {
            path: path.resolve(__dirname, 'html/'),
            //pathinfo: true,
            filename: "js/app.js"
        },
        module: {
            rules: [{
                enforce: 'pre',
                test: /\.js$/,
                exclude: /node_modules/,
                loader: "jshint-loader"
            },
            {
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    use: [{
                        loader: "css-loader",
                        options: { minimize: true },
                    }],
                    fallback: "style-loader"
                }),
            },
            c.scssRule,
            {
                test: /\.(ttf|eot|woff|woff2|svg)$/,
                loader: 'file-loader',
                options: {
                    name: '../[path].[ext]',
                    publicPath: '../',
                    emitFile: false
                },
            },
            {
                test: /\.(jpe?g|png|gif|svg)$/i,
                loader: 'file-loader',
                options: {
                    name: '../[path].[ext]',
                    publicPath: '../',
                    emitFile: false
                },
            }
            ]
        },
        // Use the plugin to specify the resulting filename (and add needed behavior to the compiler)
        plugins: [
            new ExtractTextPlugin({
                filename: 'css/app.css'
            }),
            new webpack.optimize.UglifyJsPlugin({
                compressor: { warnings: false }
            })
        ]
    }
    exp.push(e);
}

module.exports = exp;
Sathya
  • 1,704
  • 3
  • 36
  • 58

1 Answers1

3

The file-loader options have to be changed to work as desired. You want file-loader to emit the file to the output directory, otherwise you would need to copy the images manually instead of having it automated, therefore you should not set emitFile: false.

Your output directory is html/ and with the current name ../[path].[ext] you would put the files outside of the output directory (in your projects root directory), but that is not desirable since you should be able to deploy the output directory as is, without having to add anything outside of it (the build directory can be seen as the root of the server). Also [path] does not include the filename, but only the path to it. Assuming you want all the images in html/img/ you could use name: 'img/[name].[ext]'.

The public path is used as a prefix in every path, which can be useful when serving it from a different base URL, for example if you served your app on /my-app/ you would also need to request /my-app/img/name.png and not /img/name.png (public path takes care of this). See also output.publicPath.

The two file-loader rules (fonts and images) could look like this:

{
    test: /\.(ttf|eot|woff|woff2)$/,
    loader: 'file-loader',
    options: {
        name: 'fonts/[name].[ext]',
        publicPath: '/'
    },
},
{
    test:  /\.(jpe?g|png|gif|svg)$/i,
    loader: 'file-loader',
    options: {
        name: 'img/[name].[ext]',
        publicPath: '/'
    },
},
Michael Jungo
  • 31,583
  • 3
  • 91
  • 84