Source maps don't work with Hugo 0.43, 0.44: Path issue

I have a bit of trouble getting source maps to work with Hugo 0.43.

Based on the example project I enable source maps like this:

{{ $styles := resources.Get (.Scratch.Get "scssPath") | toCSS (dict "enableSourceMap" true) }}

<link rel="stylesheet" href="{{ $styles.RelPermalink }}">

I can see that this works because if I scroll all the way down to the CSS file, I see:

/*# sourceMappingURL=post.css.map */

But neither FireFox nor Chrome actually recognise the source maps in the developer tools. There I see styles coming from post.css, the generated CSS file from the individual .scss files.

I think this problem happens because the source map is not available at that URL mentioned in the CSS file. If I navigate to http://localhost:1313/post.css.map, Hugo returns:

404 page not found

Did I make a mistake somewhere?

It works fine for me, which does not help you a whole lot …

You should see a *.map when you visit in the browser, but it is hard for me to see what that path should actually be with all the scratching …

It’s indeed a URL problem.

Hugo renders my CSS file at http://localhost:1313/assets/css/post-hugo.css.

In that CSS file I have:

/*# sourceMappingURL=post-hugo.css.map */

But that source map (http://localhost:1313/post-hugo.css.map) gives a 404.

I can find the right one at http://localhost:1313/assets/css/post-hugo.css.map in the browser (it shows a JSON file with the source files and more).


The Scratch variables figure out which CSS file to render based on the type of content:

<!-- Index CSS -->
{{ if .IsHome }} 
    {{ .Scratch.Set "scssPath" "assets/css/index.scss" }}
<!-- Page CSS -->
{{ else if eq .Section "" }} 
    {{ .Scratch.Set "scssPath" "assets/css/page.scss" }}
<!-- Category pages CSS -->
{{ else if .IsNode }} 
    {{ .Scratch.Set "scssPath" "assets/css/category.scss" }}
<!-- Post css -->
{{ else }} 
    {{ .Scratch.Set "scssPath" (print "assets/css/post-" .Section ".scss") }}
{{ end }}

{{ if .Site.IsServer }}
    {{ $styles := resources.Get (.Scratch.Get "scssPath") | toCSS (dict "enableSourceMap" true) }}

    <link rel="stylesheet" href="{{ $styles.RelPermalink }}">
{{ else }}
    {{ $styles := resources.Get (.Scratch.Get "scssPath") | toCSS | minify | fingerprint "md5" }}
    <link rel="stylesheet" href="{{ $styles.RelPermalink }}">
{{ end }}

I have those SCSS files in themes/theme2018/assets/assets/css/. I deliberately used the /assets/ folder twice here. That way the CSS files appear at website.com/assets/css/ when rendered, which better matches my server setup.


Edit: In the Console tab of the Developer tools I get this warning message:

Source map error: SyntaxError: JSON.parse: bad escaped character at line 6 column 21 of the JSON data
Resource URL: http://localhost:1313/assets/css/post-hugo.css
Source Map URL: post-hugo.css.map[Learn More]

If I browse in the browser to the source map at http://localhost:1313/assets/css/post-hugo.css.map, I see there the following:

{
	"version": 3,
	"file": "post-hugo.css",
	"sourceRoot": "C:/site",
	"sources": [
		"themes\theme2018\assets\assets\css\post-hugo.scss",
		"themes/theme2018/assets/scss/meta/_mixins.scss",
		"themes/theme2018/assets/scss/meta/_variables.scss",
		"themes/theme2018/assets/scss/parts/_reset.scss",
		"themes/theme2018/assets/scss/parts/_general.scss",
		"themes/theme2018/assets/scss/parts/_header.scss",
		"themes/theme2018/assets/scss/parts/_content.scss",
		"themes/theme2018/assets/scss/parts/_footer.scss",
		"themes/theme2018/assets/scss/parts/_responsive.scss",
		"themes/theme2018/assets/scss/contenttypes/_post.scss",
		"themes/theme2018/assets/scss/syntax/_syntax.scss"
	],
    ...
}

The line number that the console warns about contains this:

"themes\theme2018\assets\assets\css\post-hugo.scss",

I don’t know why the slashes in that URL are different from the other URLs listed under "sources" in the JSON source map.

I also don’t know what the warning means. It looks like the browser can find the source map after all, but has a problem reading it.

Edit: If I change the slashes in the .scss path the other way around, the problem is not fixed. So this does not help:

{{ .Scratch.Set "scssPath" (print "assets\\css\\post-" .Section ".scss") }}

(I’m on Windows by the way, if that’s relevant for how Hugo generates the source map paths.)

Friendly bump. :slight_smile: I still haven’t got source maps to work. The error message in Firefox and Chrome’s developer tools is still there with Hugo 0.44.

If this isn’t a user error on my part, let me know and I’ll head over to GitHub.

I’m having trouble with sourcemaps as well. Using this:

{{ $cssOpts := (dict "targetPath" "css/main.css" "enableSourceMap" true ) }}
{{ $styles := resources.Get "scss/main.scss" | toCSS $cssOpts | postCSS | fingerprint }}
<link rel="stylesheet" href="{{ $styles.Permalink }}" integrity="{{ $styles.Data.Integrity }}" media="screen">

Produces a CSS file with no sourcemaps line at the bottom. Everything else is working fine.

You need to show a failing example project for anyone to answer that question.

Are the any commons from people having trouble with source maps? Windows?

See https://github.com/Jos512/hugo-source-maps-error . The project’s readme file contains a summary of the problem.

I’m on Windows 7, I use hugo_extended_0.44_Windows-64bit.zip.

My CSS file does have a source map line at the bottom:

/*# sourceMappingURL=style.css.map */

Does perhaps your postCSS operation strip away the source map? (Just a guess, since your problem is a bit different than mine I don’t really know.)

1 Like

Hi all,

I just want to follow up this interesting thread and provide more information.

I have tried the following options. Consider the similar templates taken from my project.

    {{ $cssOpts := (dict "targetPath" "styles/hyde-hyde.css" "enableSourceMap" true) }}
    {{ $styles := ... }}
    <link rel="stylesheet" href="{{ $styles.Permalink }}" integrity="{{ $styles.Data.Integrity }}">

i. Only toCSS with sourcemaps and fingerprint

    {{ $styles := resources.Get "scss/hyde-hyde.scss" | toCSS $cssOpts | fingerprint }}

The sourcemaps seems working fine as the CSS rules in the generated HTMLs can be traced back to SCSS files/lines. There is /*# sourceMappingURL=hyde-hyde.css.map */ at the end of the generated CSS.

ii. a) Add postCSS

    {{ $styles := resources.Get "scss/hyde-hyde.scss" | toCSS $cssOpts | postCSS | fingerprint }}

The CSS rules in the HTML are only traced back to the finger-printed version of the CSS, not SCSS. In the generated CSS file, there are no sourcemaps comment at the end like (i).

ii. b) Add autoprefixer to postCSS

    {{ $styles := resources.Get "scss/hyde-hyde.scss" | toCSS $cssOpts | postCSS (dict "use" "autoprefixer") | fingerprint }}

In this case, the CSS rules refer to stdin:xxx. The sourcemaps is in-lined at the end of the generated CSS like /*# sourceMappingURL=data:application/json;base64,..... */.
I tested this especially in three browsers Chrome, Safari, Firefox and see the same result.

iii. Add minify

    {{ $styles := resources.Get "scss/hyde-hyde.scss" | toCSS $cssOpts | minify | fingerprint }}

This is similar to (ii.a), i.e. CSS rules refer to the generated minified fingerprinted CSS files, not to SCSS.

Do these cases help to shed any light or something else should I try?

Thanks,
Huy

  1. I can add this: When I’m in server mode, I tend to run without 1) minification 2) postCSS (because it slow down the process). If I work in Chrome, PostCSS is mostly redundant …
  2. I only use source maps in server mode.
  3. The source maps are generated by LibSASS, it does not know anything about any later file processing. This should not be surprising.

I agree with @bep. My setup for CSS in basehof.html is this:

{{ if .Site.IsServer }}
    {{ $cssOpts := (dict "targetPath" "styles/main.css" "enableSourceMap" true ) }}
    {{ $styles := resources.Get "scss/main.scss" | toCSS $cssOpts }}
    <link rel="stylesheet" href="{{ $styles.Permalink }}" media="screen">
{{ else }}
    {{ $cssOpts := (dict "targetPath" "styles/main.css" ) }}
    {{ $styles := resources.Get "scss/main.scss" | toCSS $cssOpts | postCSS | minify | fingerprint }}
    <link rel="stylesheet" href="{{ $styles.Permalink }}" integrity="{{ $styles.Data.Integrity }}" media="screen">
{{ end }}

This isn’t work for me with the template code you posted.


I’ve opened a GitHub issue for my problem here: Source maps trigger error in Firefox & Chrome: path issue.

SCSS sourcemaps can be enabled, and are output correctly for the most part. The JSON “slash issue” that @Jura is describing on Windows is separate – as @bep stated, it is likely within LibSASS. There is a second issue here that should be easy to fix, though.

(resources.Get "css/style.scss" | toCSS (dict "enableSourceMap" true))

However, once I add PostCSS, the comment is stripped out, and the sourcemaps from SASS are not updated.

Looking into the PostCSS docs and the postcss-cli code, it looks like a --map option needs to be passed to the CLI to enable “separate-file” sourcemaps.CLI code docs

To support this, then, we’ll need to be able to add a “map” option along-side the “noMap” option that can already be passed into the PostCSS resource function.

Thank you @Jura, when I removed the postCSS call (had done that anyway to remove autoprefixer from my process) the sourcemaps appeared and are working properly.

2 Likes

I’m planning on another (great) release on Monday …

5 Likes

Great, thank you! Issue filed for the PostCSS sourcemap support: https://github.com/gohugoio/hugo/issues/4980.

Thanks for fixing the issue so quickly and including it in the 0.45 release. Really appreciate it! :slight_smile:

1 Like