x-yuri
x-yuri

Reputation: 18823

Images don't get loaded when source maps are enabled

package.json:

{
  "dependencies": {
    "css-loader": "^0.26.0",
    "file-loader": "^0.9.0",
    "html-webpack-plugin": "^2.24.1",
    "node-sass": "^3.13.0",
    "sass-loader": "^4.0.2",
    "style-loader": "^0.13.1",
    "webpack": "^1.13.3"
  }
}

webpack.config.js:

var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './1.js',
    output: {
        path: 'dist',
        filename: 'bundle.js',
    },
    module: {
        loaders: [
            {test: /\.png$/, loader: 'file'},
            {test: /\.css$/, loaders: ['style', 'css?sourceMap']},
            {test: /\.sass$/, loaders: ['style', 'css?sourceMap', 'sass?sourceMap']},
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: 'template.ejs',
        }),
    ],
};

template.ejs:

<!doctype html>
<html>
<body>

<div></div>

</body>
</html>

1.js:

require('./1.css');
require('./1.sass');

1.sass:

div
    width: 100px
    height: 100px
    margin: auto
    background: url(1.png) no-repeat

1.css:

body {
    margin: 0;
    background: url(1.png) no-repeat;
}

Then

$ npm i
$ rm -rf dist/* && ./node_modules/.bin/webpack

And open http://example.com/dist in browser. Both images are not displayed. But if you remove sourceMap query param from css loaders, it'll work out.

What's the matter? How to remedy it?

Upvotes: 1

Views: 83

Answers (1)

x-yuri
x-yuri

Reputation: 18823

What the doc has to say:

style-loader:

Note about source maps support and assets referenced with url: when style loader is used with ?sourceMap option, the CSS modules will be generated as Blobs, so relative paths don't work (they would be relative to chrome:blob or chrome:devtools). In order for assets to maintain correct paths setting output.publicPath property of webpack configuration must be set, so that absolute paths are generated.

css-loader:

They are not enabled by default because they expose a runtime overhead and increase in bundle size (JS SourceMap do not). In addition to that relative paths are buggy and you need to use an absolute public path which include the server url.

And here are some related issues.

So, when you enable source maps, css files are added as blobs. And relative paths stop working. My guess is it's style-loader's doing. No offense here, maybe there's no better way.

And one way to deal with it is... disable source maps :) The second one, to specify absolute url in output.publicPath. And by absolute I mean the one with a domain name. And the third option is... to extract css code into separate files, with extract-text-webpack-plugin.

Here's the webpack.config.js with code resolving the issue commented out. Choose the option which suits you best:

var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: './1.js',
    output: {
        path: 'dist',
        filename: 'bundle.js',
        // publicPath: 'http://example.com/dist/',   // (2)
    },
    module: {
        loaders: [
            {test: /\.png$/, loader: 'file'},
            {test: /\.css$/, loaders: ['style', 'css?sourceMap']},
            // {test: /\.css$/, loader: ExtractTextPlugin.extract('style', 'css?sourceMap')},   // (3)
            {test: /\.sass$/, loaders: ['style', 'css?sourceMap', 'sass?sourceMap']},
            // {test: /\.sass$/, loader: ExtractTextPlugin.extract('style', 'css?sourceMap!sass?sourceMap')},   // (3)
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: 'template.ejs',
        }),
        // new ExtractTextPlugin('[name].css'),   // (3)
    ],
};

Upvotes: 2

Related Questions