Description
When creating source maps with the CSS loader the file paths that are generated are wrong and don't follow the format which is used for JavaScript files.
CSS Loader defines a sourceRoot (webpack://
) for the source map. Additionally webpack://
is added a second time within the SourceMapDevToolPlugin
when the file names are generated using ModuleFilenameHelpers
. This finally results in this file path for the css file: 'webpack:///webpack:///components/Test.css'
See this simple Example:
src
-- components
-- -- Test.css
-- -- Test.js
-- app.js
webpack.config.js
with Test.js
:
import React, { Component, PropTypes } from 'react';
import './Test.css';
export default class Test extends Component {
render() {
return (
<div className="test"></div>
);
}
}
and app.js
:
import React from 'react';
import { render } from 'react-dom';
import Test from './components/Test'
render(<Test />, document.getElementById('demo'))
and webpack.config.js
:
import path from 'path';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
const srcPath = path.join(__dirname, 'src');
const buildPath = path.join(__dirname, 'dev');
module.exports = {
context: srcPath,
entry: [
'./app.js'
],
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].chunk.js',
path: buildPath
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loaders: ['babel-loader']
},
{
test: /\.css/,
loader: ExtractTextPlugin.extract('style', ['css?sourceMap'])
}
]
},
plugins: [
new ExtractTextPlugin('[name].style.css')
],
devtool: 'source-map'
};
If you skip into the source map creation you can see that moduleFileNames
in SourceMapDevToolPlugin
is correct for the JS files:
[
'webpack:///./components/Test.js',
'webpack:///./components/Test.css'
]
However, if you look at the moduleFileNames
for the source map from the CSS Loader you get:
[
'webpack:///webpack:///components/Test.css'
]
This is obviously wrong. I would expect the same path that was generated for the JS files.
While digging a little bit deeper into it I found out that the JS source maps that are processed always contain the absolute path to the JS file and an empty sourceRoot
property.
This could be easily changed in the loader. Just return the absolute path and don't pass a sourceRoot
property.
var moduleJs;
if(query.sourceMap && result.map) {
// add a SourceMap
map = result.map;
if(map.sources) {
map.sources = map.sources.map(function(source) {
return source.split("!").pop();
}, this);
map.sourceRoot = "";
}
map.file = map.file.split("!").pop();
map = JSON.stringify(map);
moduleJs = "exports.push([module.id, " + cssAsString + ", \"\", " + map + "]);";
} else {
moduleJs = "exports.push([module.id, " + cssAsString + ", \"\"]);";
}
By doing this moduleFileNames
now contains the correct path.
[
'webpack:///./components/Test.css'
]
The source maps that are generated by this change are correct and work as expected. I have not yet submitted a pull request because I first wanted to check with you if this change might have any other implications that I am not aware of.
This might also help to fix #194