Skip to content

Sourcemap doesn't work with devtool option contain "eval" #529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
genshinw opened this issue May 8, 2020 · 12 comments · Fixed by #827
Closed

Sourcemap doesn't work with devtool option contain "eval" #529

genshinw opened this issue May 8, 2020 · 12 comments · Fixed by #827

Comments

@genshinw
Copy link

genshinw commented May 8, 2020

  • Operating System:
  • Node Version: 10.15.2
  • NPM Version: 6.4.1
  • webpack Version: 4.41.6
  • mini-css-extract-plugin Version: 0.9.0

Expected Behavior

Use the devtool options with "eval" such as "cheap-module-eval-source-map", the extract css file can map to the really css or sass file.
image

Actual Behavior

My entry file 'main.js' which import 'testSass.scss', with the devtool options "cheap-module-eval-source-map" to get the fast rebuild . But it'can not map the body style to the real sass file.
image
If I change devtool to "cheap-module-source-map" without 'eval', It works.

Code

// webpack.config.js
module.exports = {
  mode: 'development', // 'production'
  devtool: 'cheap-module-source-map',
  entry: {
    'learn': './src/main.js',
  },
  module: {
    rules: [ // 添加对模块处理特定规则
      {
        test: /\.s[ac]ss$/i,
        use: [{
          loader: MiniCssExtractPlugin.loader,
          options: {hmr: true}
          },
          {loader: 'css-loader', options: {sourceMap: true}},
          {loader: 'sass-loader', options: {sourceMap: true}},]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css'
    }),
    new HtmlWebpackPlugin(),
  ],
  devServer: {
    port: 9000,
    hot: true
  }
}

How Do We Reproduce?

You can use the config above . If cannot reproduce , I will give a repo later.

Addition

I found an hack with add the sourcemapPlugin with devtools in #29 (comment)

new webpack.SourceMapDevToolPlugin({ 
      filename: "[file].map",
      exclude: ["/vendor/"]
    }),
```js
@genshinw
Copy link
Author

Hi @sokra , has any solution?

@alexander-akait
Copy link
Member

alexander-akait commented Aug 10, 2020

Yes, it is limitation, eval doesn't work with CSS, you need to use source-map, we need documented it

@andy0130tw
Copy link

andy0130tw commented Jan 24, 2022

After hacking around a while, I have found that it is actually possible to have CSS source maps inlined when devtool option contains "eval". To be precise, this plugin currently only supports source maps that are emitted in separate files. In our case, this is not possible since our devtool option expects no .map files emitted. We can still include an inline source map, though. What I have done is to replace this line of src/index.js...

return new ConcatSource(externalsSource, source);

... with:

const result = new ConcatSource(externalsSource, source);
const m = result.map();
// if the source map information is available...
if (m != null) {
  const encoded = Buffer.from(JSON.stringify(m)).toString('base64');
  const footer = `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${encoded} */`;
  result.add(new RawSource(footer));
}
return result;

And we have embedded the source map. Now the devtool can detect it properly.

@andy0130tw
Copy link

andy0130tw commented Jan 25, 2022

Follow-up: After reading webpack's source code a little bit more, I manage to adjust the configuration accordingly so it produces the inline source map instead, without touching the source code of mini-css-extract-plugin:

{
  /* ... */
  plugins: [
    new MiniCssExtractPlugin(),
    new webpack.SourceMapDevToolPlugin({
      test: /\.css$/i,
      filename: null,
      append: '/*# sourceMappingURL=[url] */',
    })
  ]
}

Normally we would turn off the devtool option, but if we are using an "eval-*-source-map" as its value, it is applying a different plugin EvalSourceMapDevToolPlugin. As long as the plugin we add is NOT touching JS files, we won't interfere that option: https://github.com/webpack/webpack/blob/v5.67.0/lib/WebpackOptionsApply.js#L225-L246

This also solves issue #29 and seems more elegant than both the original and my previous solution.

@lazyunderscore
Copy link

After hacking around a while, I have found that it is actually possible to have CSS source maps inlined when devtool option contains "eval". To be precise, this plugin currently only supports source maps that are emitted in separate files. In our case, this is not possible since our devtool option expects no .map files emitted. We can still include an inline source map, though. What I have done is to replace this line of src/index.js...

return new ConcatSource(externalsSource, source);

... with:

const result = new ConcatSource(externalsSource, source);
const m = result.map();
// if the source map information is available...
if (m != null) {
  const encoded = Buffer.from(JSON.stringify(m)).toString('base64');
  const footer = `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${encoded} */`;
  result.add(new RawSource(footer));
}
return result;

And we have embedded the source map. Now the devtool can detect it properly.

It really works! Nice solution

@caseyjhol
Copy link

@alexander-akait Is there a reason the proposed solution above by @andy0130tw is not already implemented by default to get eval- sourcemaps working? Is there some other disadvantage/downside I'm missing?

@alexander-akait
Copy link
Member

@caseyjhol You can just set sourceMap: true for css-loader and it will work the same

@caseyjhol
Copy link

caseyjhol commented Mar 10, 2025

@alexander-akait I just tested that, and can confirm that the resulting output is not the same. sourceMappingURL is not included at the bottom of files, and it seems sourcemaps don't work at all.

Webpack: v5.98.0
mini-css-extract-plugin: v2.9.2
css-loader: v7.1.2
resolve-url-loader: v5.0.0
sass-loader: v16.0.5

        rules: {
                {
                    test: /\.s[ac]ss$/,
                    exclude: /node_modules/,
                    use: [
                        MiniCssExtractPlugin.loader,
                        {
                            loader: 'css-loader',
                            options: {
                                sourceMap: true,
                            },
                        },
                        {
                            loader: 'resolve-url-loader',
                            options: {
                                sourceMap: true,
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: true,
                            },
                        },
                    ]
                },
        },
        devtool: 'eval-cheap-module-source-map',

What does work is the above suggested SourceMapDevToolPlugin configuration, but only if sourceMap: true is not set for css-loader.

What else might I be missing?

@alexander-akait
Copy link
Member

Eval source maps works only with JS, it is by design, what is why you need include new webpack.SourceMapDevToolPlugin, in future we want to implement something like:

devtool: {
  /\.js/: "eval-cheap-module-source-map",
  /\.css/": "source-map"
}

So such things will be easy to setup

@caseyjhol
Copy link

caseyjhol commented Mar 10, 2025

Ah, I see. Thank you for clarifying. Is there an estimated timeline for that feature? If not, is it a feature the team would be open to pull requests for?

As a shorthand, it would be great if we could simply set devtool: 'eval-cheap-module-source-map' and have Webpack automatically do devtool: 'source-map' for CSS files, since I suspect most people who want eval source maps for JS also would like sourcemaps for CSS. Essentially, fall back to source-map for file types that don't support eval source maps.

Thanks again for the added insight.

@alexander-akait
Copy link
Member

Ah, I see. Thank you for clarifying. Is there an estimated timeline for that feature? If not, is it a feature the team would be open to pull requests for?

Yeah, PR welcome, we didn't do it only because no one sent this improvement.

@andy0130tw
Copy link

Glad to hear that my solution was helpful. Although I left the project in early 2024 that used this plugin-based workaround, I believe that it should still be working fine. If anyone can test it and draft a PR with proper attribution, I would greatly appreciate it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants