bholloway / resolve-url-loader

Webpack loader that resolves relative paths in url() statements based on the original source file
563 stars 71 forks source link

Missing file name and line numbers in the console in case of error #50

Closed wujekbogdan closed 5 years ago

wujekbogdan commented 7 years ago

When I make a syntax error in the scss code, I can see an error that looks like this:

    ERROR in ./~/css-loader!./~/resolve-url-loader!./~/postcss-loader!./~/sass-loader/lib/loader.js?sourceMap!./src/scss/app.scss
    Module build failed:
      red;
     ^
          Property "red" must be followed by a ':'
          in /Users/username/htdocs/myproject/src/scss/utils/media.scss (line 2, column 3)

So, I can see what happened and where it happened. It's a line 2, column 3, media.scss file.

But when I mistype the resource url, for example:

.my-class {
  background: url('this/path/is/wrong.png')
}

then this is what I see in the console:

ERROR in ./~/css-loader!./~/resolve-url-loader!./~/postcss-loader!./~/sass-loader/lib/loader.js?sourceMap!./src/scss/app.scss
    Module not found: Error: Can't resolve './this/path/is/wrong.png' in '/Users/username/htdocs/myproject/src/scss'
     @ ./~/css-loader!./~/resolve-url-loader!./~/postcss-loader!./~/sass-loader/lib/loader.js?sourceMap!./src/scss/app.scss 6:35524-35545

So, I can only see that this is something related to scss and a the ./this/path/is/wrong.png file. But there's no scss file name in the console output and no line number.

It happens only when I provide a path to an unexisting resource in the url(), so I assume that this is a bug in the resolve-url-loader. Correct me if I'm wrong.

This is my webpack config:

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const SpritesmithPlugin = require('webpack-spritesmith');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    entry: [
        './src/js/app.js',
        './src/scss/app.scss'
    ],
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'js/app.js'
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        'scss': 'vue-style-loader!css-loader!postcss-loader!sass-loader',
                    }
                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.(png|jpg|gif|svg)$/,
                exclude: /(sprites|sprites@2x).png/,
                use: [{
                    loader: 'file-loader',
                    options: {
                        name: '[path][name].[ext]',
                        context: './src/img/',
                        outputPath: 'img/',
                        publicPath: '../img/'
                    }
                },
                    {
                        loader: 'image-webpack-loader'
                    }
                ]
            },
            {
                test: /\.(eot|otf|ttf|woff)$/,
                use: [{
                    loader: 'file-loader',
                    options: {
                        name: '[path][name].[ext]',
                        context: './src/font/',
                        outputPath: 'font/',
                        publicPath: '../font/'
                    }
                }]
            },
            {
                test: /(sprites|sprites@2x).png/,
                loader: 'file-loader',
                options: {
                    name: '[name].[ext]',
                    outputPath: 'img/',
                    publicPath: '../img/'
                }
            },
            {
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        'css-loader',
                        'resolve-url-loader',
                        'postcss-loader',
                        'sass-loader?sourceMap'
                    ]
                })
            }
        ]
    },
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        },
        modules: [
            'node_modules',
            'temp' // spritesmith generated files
        ]
    },
    plugins: [
        new FriendlyErrorsWebpackPlugin(),
        new CopyWebpackPlugin([{
            context: './src/font/',
            from: '**/*',
            to: 'font/' // It's relative to ./dist
        }]),
        new ExtractTextPlugin('/css/app.css'),
        new SpritesmithPlugin({
            src: {
                cwd: path.resolve(__dirname, 'src/img/sprites/'),
                glob: '*.png'
            },
            target: {
                image: path.resolve(__dirname, 'temp/sprites.png'),
                css: path.resolve(__dirname, 'temp/sprites.scss')
            },
            retina: '@2x',
            apiOptions: {
                cssImageRef: "~sprites.png"
            }
        })
    ],
    devServer: {
        historyApiFallback: true,
        noInfo: true
    },
    performance: {
        hints: false
    },
    devtool: '#eval-source-map'
};

if (process.env.NODE_ENV === 'production') {
    module.exports.devtool = '#source-map';
    module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            sourceMap: true,
            compress: {
                warnings: false
            }
        }),
        new webpack.LoaderOptionsPlugin({
            minimize: true
        })
    ])
}

And this is my package.json

{
  "name": "myproject",
  "version": "1.0.0",
  "description": "",
  "main": "gulpfile.js",
  "dependencies": {
    "bootstrap": "4.0.0-alpha.6",
    "jquery": "^3.1.1",
    "lodash": "^4.17.4",
    "normalize.scss": "^0.1.0",
    "outdated-browser": "^1.0.2",
    "salvattore": "^1.0.9",
    "sassy-gridlover": "^4.0.0",
    "slick-carousel": "^1.6.0",
    "vue": "^2.2.2",
    "vue-router": "^2.3.0",
    "vue-template-compiler": "^2.2.2"
  },
  "devDependencies": {
    "autoprefixer": "^6.7.6",
    "babel-core": "^6.0.0",
    "babel-eslint": "^7.1.1",
    "babel-loader": "^6.4.0",
    "babel-preset-es2015": "^6.9.0",
    "copy-webpack-plugin": "^4.0.1",
    "cross-env": "^3.2.3",
    "css-loader": "^0.27.1",
    "extract-text-webpack-plugin": "^2.1.0",
    "file-loader": "^0.10.1",
    "friendly-errors-webpack-plugin": "^1.6.1",
    "image-webpack-loader": "^3.2.0",
    "node-sass": "^4.5.0",
    "object-fit-images": "^3.1.3",
    "path": "^0.12.7",
    "postcss-loader": "^1.3.3",
    "postcss-object-fit-images": "^1.1.2",
    "resolve-url-loader": "^2.0.2",
    "sass-loader": "^6.0.3",
    "style-loader": "^0.13.2",
    "vinyl-fs": "^2.4.4",
    "vinyl-ftp": "^0.6.0",
    "vue-loader": "^11.1.4",
    "vue-style-loader": "^2.0.3",
    "webpack": "^2.2.1",
    "webpack-build-notifier": "^0.1.13",
    "webpack-dev-server": "^2.4.1",
    "webpack-spritesmith": "^0.3.3"
  },
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack --progress --hide-modules --watch",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
    "deploy": "yarn run build && node deploy"
  },
  "browser": {
    "slick": "./node_modules/slick-carousel/slick/slick.js"
  },
  "browserify-shim": {
    "slick": {
      "exports": "null"
    }
  }
}

It's not an environment related issue. It happens on Windows and on Mac. Is there anything else I can provide you with?

bholloway commented 7 years ago

Unfortunately this is what you get with webpack.

The file does not matter until it gets to the CSS loader. The CSS loader treats the file like any other import.

Just setup a simple rule for a single Sass file and use only the sass loader and CSS loader. You should see exactly the same behaviour without using this loader.

wujekbogdan commented 7 years ago

OK, thank you for the clarification. I wasn't sure is it the resolve-url-loader issue or something else. So, what is the proper place to report this issue? webpack core repo?

bholloway commented 7 years ago

@wujekbogdan I had a thought...

It may be that css-loader would give you better line numbers but that the source-map is not getting through.

Please try

I would hope one or both of these gives you a better location. However I don't think anything will give you such a nicely formatted error as you originally hoped.

To answer your question: url() statements are processed by the css-loader.