angular-cli: Source map not working for SCSS files

Recently I updated cli version 1.3.2 to 1.6.3 and after that I can’t see scss source mapped file in developer tools in Chrome of Firefox .

Versions : 1.6.3

Angular CLI: 1.6.3
Node: 8.9.3
OS: win32 x64
Angular: 5.0.0
... animations, common, compiler, compiler-cli, core, forms
... http, platform-browser, platform-browser-dynamic
... platform-server, router

@angular/cli: 1.6.3
@angular/language-service: 4.4.6
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.3
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.4.2
webpack: 3.10.0

Repro steps

  • Create new angular app using ng new sample-app
  • Add scss file in angular-cli.json "styles": ["styles/styles.scss"]
  • Launch app using ng serve -sm -ec
  • Inspect styles using chrome dev-tools.

Observed behavior

No actual scss file, only style.bundle.css where all the styles compiled. image

Desired behavior

Actual scss file can be seen in the developer tools with the line number image

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 22
  • Comments: 87 (4 by maintainers)

Commits related to this issue

Most upvoted comments

works for me using version 6.0!!

solution:

  1. modify angular.json to add –extract-css, in 6.0 this argument is removed from ng serve
 "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
           ---
          },
          "configurations": {
            "production": {
              ---
            },
            "serve": {
              "extractCss": true,
               ---
            }
          }
        },

hen change serve->options->browserTarget->project-name:build to project-name:build:serve

"serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "open": true,
            "browserTarget": "<project-name>:build:serve"
          },
          "configurations": {
            "production": {
              ---
            }
          }
        }
  1. run ng serve --source-map image

Some Context:

  • using angular-cli version 1.6.6
  • project is generated by the CLI.
  • using Scss

I remembered it was a weird thing in Webpack config where I had to add extra config to allow sourcemap (in addition to the plugin config).

Solution: In “node_modules@angular\cli\models\webpack-configs\common.js” file, in line 162, Add a line devtool: 'source-map', in the returned common configuration object in the getCommonConfig function, e.g.

    ...
    catch (e) { }
    return {
        devtool: 'source-map',        // add this line
        resolve: {
            extensions: ['.ts', '.js'],
             ...

Tested with the following Commands in terminal (also works with Sass @import):

ng serve           // no sourcemap
ng serve -sm -ec   // has sourcemap
ng serve --sourcemap --extract-css  // has sourcemap   
ng serve --sourcemap --extractCss   // has sourcemap   

Sourcemapping for General (Non-component level) SCSS Compilation

@metasong’s solution works for ANGULAR 6

  1. modify angular.json to add --extract-css, in 6.0 this argument is removed from ng serve
 <span class="pl-s"><span class="pl-pds">"</span>build<span class="pl-pds">"</span></span>: {
          <span class="pl-s"><span class="pl-pds">"</span>builder<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>@angular-devkit/build-angular:browser<span class="pl-pds">"</span></span>,
          <span class="pl-s"><span class="pl-pds">"</span>options<span class="pl-pds">"</span></span>: {
           <span class="pl-ii">---</span>
          },
          <span class="pl-s"><span class="pl-pds">"</span>configurations<span class="pl-pds">"</span></span>: {
            <span class="pl-s"><span class="pl-pds">"</span>production<span class="pl-pds">"</span></span>: {
              <span class="pl-ii">---</span>
            },
            <span class="pl-s"><span class="pl-pds">"</span>serve<span class="pl-pds">"</span></span>: {
              <span class="pl-s"><span class="pl-pds">"</span>extractCss<span class="pl-pds">"</span></span>: <span class="pl-c1">true</span>,
               <span class="pl-ii">---</span>
            }
          }
        },
  1. Then change serve->options->browserTarget->project-name:build to project-name:build:serve
<span class="pl-s"><span class="pl-pds">"</span>serve<span class="pl-pds">"</span></span>: {
          <span class="pl-s"><span class="pl-pds">"</span>builder<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>@angular-devkit/build-angular:dev-server<span class="pl-pds">"</span></span>,
          <span class="pl-s"><span class="pl-pds">"</span>options<span class="pl-pds">"</span></span>: {
            <span class="pl-s"><span class="pl-pds">"</span>open<span class="pl-pds">"</span></span>: <span class="pl-c1">true</span>,
            <span class="pl-s"><span class="pl-pds">"</span>browserTarget<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span><project-name>:build:serve<span class="pl-pds">"</span></span>
          },
          <span class="pl-s"><span class="pl-pds">"</span>configurations<span class="pl-pds">"</span></span>: {
            <span class="pl-s"><span class="pl-pds">"</span>production<span class="pl-pds">"</span></span>: {
              <span class="pl-ii">---</span>
            }
          }
        }
  1. run ng serve --source-map

image

v1.7.3 still no change. 👎

version 1.7.4 still not work, even try patched with devtool: 'source-map', Plz show me how to fix this issue.

Issue still present in v1.7.0 The workaround DOES NOT WORK in v1.7.0!

Edit: Not sure why down voted, the work around does not work for me anymore when using CLI v1.7.0

Angular CLI: 1.7.0
Node: 6.11.2
OS: darwin x64
Angular: 5.2.5
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

@angular/cli: 1.7.0
@angular-devkit/build-optimizer: 0.3.1
@angular-devkit/core: 0.3.1
@angular-devkit/schematics: 0.3.1
@ngtools/json-schema: 1.2.0
@ngtools/webpack: 1.10.0
@schematics/angular: 0.3.1
@schematics/package-update: 0.3.1
typescript: 2.6.2
webpack: 3.11.0

patch doesn’t work in 1.7.0. Trying to work on styling is a nightmare without sourcemaps, please fix!

I have same issue, and still wait for fixing. This is a critical issue, it blocks rapid development.

Same issue here when I upgraded from 1.4.7 to 1.6.5. Please fix, this is a major blocker!

This is making it very hard to work and debug css styling issues.

I’ve had this problem from 1.5 onwards

This is main reason why I am still using Angular 4 and cli 1.4.x in production and not upgrading to Angular 5.

Dnia 5 stycznia 2018 04:42 Rukshan Lakshitha Dangalla <notifications@github.com> napisał(a): Recently I updated cli version 1.3.2 to 1.6.3 and after that I can't see scss source mapped file in developer tools in Chrome of Firefox . Versions : 1.6.3 Angular CLI: 1.6.3Node: 8.9.3OS: win32 x64Angular: 5.0.0… animations, common, compiler, compiler-cli, core, forms… http, platform-browser, platform-browser-dynamic… platform-server, router@angular/cli: 1.6.3@angular/language-service 4.4.6@angular-devkit/build-opt 0.0.36@angular-devkit/core: 0.0.22@angular-devkit/schemati 0.0.42@ngtools/json-schema: 1.1.0@ngtools/webpack: 1.9.3@schematics/angular: 0.1.11@schematics/schematics: 0.0.11typescript: 2.4.2webpack: 3.10.0 Repro steps Create new angular app using ng new sample-app Add scss file in angular-cli.json "styles": ["styles/styles.scss"] Launch app using ng serve -sm -ec Inspect styles using chrome dev-tools. Observed behavior No actual scss file, only style.bundle.css where all the styles compiled. zasobygwp.pl Desired behavior Actual scss file can be seen the developer tools with the line number zasobygwp.pl — You are receiving this because you are subscribed to this thread. Reply to this email directly, zasobygwp.pl view it on GitHub , or zasobygwp.pl mute the thread .

@smlombardi You have entered the line in the wrong place.

This is where I imagine you have placed it:

return {
  resolve: {
    devtool: 'source-map',
    ...
  }
}

in needs to be in the return object one level higher:

return {
  devtool: 'source-map',
  resolve: { ... },
  ...
}

Sourcemapping for Component-level SCSS Files

Can you confirm, @metasong, @frensuren, @CharltonC, @rukshandangalla, @michael-letcher?

Suprisingly, the following solution works without any configuring of Angular 6’s angular.json file.

Simply add /*# sourceURL=your-comp-style.component.scss */ to the bottom of your component-level .scss file.

Code

screen shot 2018-06-06 at 3 30 06 pm

Run

ng serve --source-map

Result in Chrome

screen shot 2018-06-06 at 3 37 02 pm

version 1.7.3 does’t work, even patched with devtool: 'source-map', anyone know why

One just wonders when the team is planning to actually fix this critical piece of tooling.

Had some spare time to test it out. As suspected, it was caused by “raw-loader” the plugin. I tried enabling the sourcemap with the option for “raw-loader” plugin like follows (approx. line 180) but unfortunately didn’t work.

const commonLoaders = [
        { 
               loader: 'raw-loader',
               // option added here but didn't work
               options: {
                  sourceMap: cssSourceMap,
                  import: false,
            }                
        },
    ];

Perhaps the good news is that it is not a super verbose work around. It has turned into a verbose work around. It seems that “raw-loader” is only used for Html beside the “styles.js” file. Not sure what it may break though. Please do check.

Solution

  1. requires the devtool: 'source-map' in the “common.js” file as per previous discussion
  2. requires “css-loader” & “exports-loader” plugin to be installed as dependency in CLI a) in terminal, under your project folder, navigate to “node_modules/@angular/cli” b) install the plugin as dependency: npm install --save css-loader exports-loader
  3. in the file “node_modules@angular\cli\models\webpack-configs\styles.js” file, make a few changes: a) swap out the variable commonLoaders (approx. line 180) with css-loader one, for example:
    /*     const commonLoaders = [
        { loader: 'raw-loader' },
    ]; */
   // new code looks something like this
    const commonLoaders = [
        {
            loader: 'css-loader',
            options: {
                sourceMap: cssSourceMap,
                import: false,
            }
        }
    ];
   ...

b) Right underneath the commonLoaders, add the 'exports-loader?module.exports.toString()', above the ...commonLoaders. This is the same as CLI 1.6.6 and eliminates the error “compiler.js:2520 Uncaught Error: Expected ‘styles’ to be an array of strings.” in the devtool console

    ...
    // load component css as raw strings
    const rules = baseRules.map(({ test, use }) => ({
        exclude: globalStylePaths, test, use: [
            'exports-loader?module.exports.toString()',           // <-- add this line
            ...commonLoaders,
            {
                loader: 'postcss-loader',
                ...

Test Context:

  • angular-cli version 1.7.0
  • node v6.9.4
  • Scss

Tested with the following Commands in terminal (also works with Sass @import):

ng serve           // no sourcemap
ng serve -sm -ec   // has sourcemap
ng serve --sourcemap --extract-css  // has sourcemap   
ng serve --sourcemap --extractCss   // has sourcemap   

My2cents. @michael-letcher I have tested using CLI 1.7.0 and can confirm the work around is no longer working. It was strange as the Webpack API related to the sourcemap fix did not change as far as I am concerned.

Did a little more digging & comparing the webpack config file, found that the new CLI is using Webpack plugin “raw-loader” which does not yet support sourcemap (somehow the ticket has been closed but I am not sure if the sourcemap has been implemented). See the link below: https://github.com/webpack-contrib/raw-loader/pull/8

As for reference, there is a difference block of code in “webpack-config/style.js” file, the commonLoaders variable:

  • CLI 1.7.0 line 180: “raw-loader” is used
  • CLI 1.6.6 line 170: “css-loader” (and “postcss-loader”) is used

“raw-loader” could be the issue here.

Source map not working for LESS files

I have the same issue with Less files too.

The component LESS files appear, but the styles brought in via the CLI are not.

Versions

Angular CLI: 1.6.2
Node: 6.11.2
OS: darwin x64
Angular: 5.1.2
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

@angular/cli: 1.6.2
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.40
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.2
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.10
typescript: 2.4.2
webpack: 3.10.0

@icenold Installed css-loader and exports-loader dependencies for @angular/cli i) navigate to “node_modules/@angular/cli” ii) do: npm install --save css-loader exports-loader iii) Modify the file “node_modules@angular\cli\models\webpack-configs\styles.js” contents, mine was in line 180
Replace

     const commonLoaders = [
        { loader: 'raw-loader' },
    ]; 

with this

const commonLoaders = [
        {
            loader: 'css-loader',
            options: {
                sourceMap: cssSourceMap,
                import: false,
            }
        }
    ];

Also Replace

 // load component css as raw strings
    const rules = baseRules.map(({ test, use }) => ({
        exclude: globalStylePaths, test, use: [
            ...commonLoaders,
            {
                loader: 'postcss-loader',
                options: {
                    ident: 'embedded',
                    plugins: postcssPluginCreator,
                    sourceMap: cssSourceMap
                }
            },
            ...use
        ]
    }));

With

// load component css as raw strings
    const rules = baseRules.map(({ test, use }) => ({
        exclude: globalStylePaths, test, use: [
                'exports-loader?module.exports.toString()',
                ...commonLoaders,
            {
                loader: 'postcss-loader',
                options: {
                    ident: 'embedded',
                    plugins: postcssPluginCreator,
                    sourceMap: cssSourceMap
                }
            },
            ...use
        ]
    }));

This worked for me

This gets to a point where it just takes too much effort or work around to solve a fundamental issue. There are too many unknowns as in what we need to test against the solution so that other functionalities don’t break because the work around involves changes in so many areas. I think it would best to leave this to original author as in why there was a major change in the implementation from v1.7.0 onwards.

I can share some observations for reference purpose only. Apart from the changes I mentioned, if you do either of the following, the font error mentioned by @smlombardi disappears.

  • If you replace the node_modules\@angular\cli\models\webpack-configs\style.js file from CLI v1.6.6 to CLI v1.70 it will work. (requires an extra npm dependency called cssnano for the CLI)
  • If you comment out the PostcssCliResources in the postcssPluginCreator constant in the node_modules\@angular\cli\models\webpack-configs\style.js file, like following (It is using a node_modules\@angular\cli\plugins\postcss-cli-resources.js file which was not in v1.6.6 before):
        ...
        { url: 'rebase' },
    ]),
    // PostcssCliResources({
    // ...
    // }) ,
    autoprefixer({ grid: true }),
];

Hope this helps. For now I myself am just going to stick with CLI v1.6.6

+1, no more source maps with @angular/cli: 1.7.1

I create such file as postinstall can patch it. inspired from angular aio https://github.com/angular/angular/tree/master/aio/tools/cli-patches

in your project create following files

tools/cli-patches/patch.js

const fs = require('fs');
const sh = require('shelljs');

const PATCH_LOCK = 'node_modules/@angular/cli/models/webpack-configs/.patched-webpack-enable-sourcemap';

//can generate patch file by `git diff` or use `diff -Nur`
if (!fs.existsSync(PATCH_LOCK)) {
  sh.exec('patch -p0 -i tools/cli-patches/webpack-enable-sourcemap.patch');
  sh.touch(PATCH_LOCK);
}

tools/cli-patches/webpack-enable-sourcemap.patch

--- node_modules/@angular/cli/models/webpack-configs/common.js 2018-02-08 09:10:11.000000000 +0800
+++ node_modules/@angular/cli/models/webpack-configs/common.js 2018-02-20 20:36:43.000000000 +0800
@@ -158,6 +158,7 @@
     }
     catch (e) { }
     return {
+        devtool: buildOptions.sourcemaps ? 'source-map' : false,
         resolve: {
             extensions: ['.ts', '.js'],
             modules: ['node_modules', nodeModules],

package.json

...
 "scripts": {
   "postinstall": "node tools/cli-patches/patch.js"
 }
...

Glad it works for everyone. Cheers.

As I can see many folks have this issue. What can we do about this?

It does not show references to my project’s scss files nor to bootstrap 4’s scss files. Only to styles.bundle.css.

Still sourceMap / extractCSS is not working for component specific styles

image

"@angular-devkit/build-angular": "^0.6.8",
"@angular/cli": "^6.0.8",

I found the source of the issue within the @angular-devkit/build-angular package.

You can temporarily fix this yourself editing changing the sourcemap option for both instances of postcss-loader in the following file ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/styles.js change

sourceMap: cssSourceMap

to

sourceMap: cssSourceMap ? 'inline' : false
    const rules = baseRules.map(({ test, use }) => ({
        exclude: globalStylePaths, test, use: [
            { loader: 'raw-loader' },
            {
                loader: 'postcss-loader',
                options: {
                    ident: 'embedded',
                    plugins: postcssPluginCreator,
                    sourceMap: cssSourceMap ? 'inline' : false
                }

I’ll file an issue with the @angular-devkit/build-angular repository. edit: ah that package is in this repo, ha. I submitted a pull request with the fix.

The sourceURL= solution helps at least tell you the file, but still is far from ideal. It references generated css, so line numbers do not match up and any imported styles will show as belonging to the importing file.

@daddyschmack you have a typo, it should be extractCss and not extractsCss, although I was trying this method with a new angular project and its not working with the last couple cli versions.

@CharltonC Thanks, your solution worked for me for angular cli 1.7.4. It is now showing the scss sourcemaps. #issuecomment-373430066

downgraded to 1.6.6 and applied fix by @CharltonC - source maps work as expected. my steps:

  • update global angular:
[sudo] npm uninstall -g @angular/cli 
npm cache clean 
[sudo] npm install -g @angular/cli
  • npm cache clear --force
  • npm cache verify
  • npm i @angular/cli@1.6.6 or use exact version in package.json "@angular/cli": "1.6.6", and do npm i
  • go to node_modules@angular\cli\models\webpack-configs\common.js:162
...
    catch (e) { }
    return {
        devtool: 'source-map',        // add this line
        resolve: {
            extensions: ['.ts', '.js'],
             ...
  • done

@smlombardi I ended up going with gulp for now because I am working on styling and needed something that would also work for deploy. My config may be oversimplified, but it works. I am using font-awesome 4.7, bootstrap 4 and a single entry point for global SCSS. I added the font-awesome fonts as assets in .angular-cli.json so they get copied, a style sheet reference to project’s index.html and emptied the styles array. In my styles/styles.scss file I set $fa-css-prefix, $fa-font-path vars appropriately, then import font-awesome and bootstrap .SCSS from relative node_modules paths.

I have gulp calling ng cli commands defined in package.json. NOTE: May run into issues without –delete-output-path=false on ng build command

added to index.html head:

<link href="styles.css" rel="stylesheet">

relevant styles.scss:

$fa-css-prefix: fa;
$fa-font-path: "assets/fonts";

@import "../../node_modules/font-awesome/scss/font-awesome";
@import "../../node_modules/bootstrap/scss/bootstrap";
@import "../../node_modules/bootstrap/scss/bootstrap-grid";

// .. other imports and custom SCSS

relevant package.json scripts:

"ngbuild": "ng build --prod -oh=none --delete-output-path=false",
"ngbuilddevw": "ng build --dev --watch --delete-output-path=false",

gulp dependencies:

"cssnano": "^3.10.0",
"gulp": "3.9.1",
"gulp-postcss": "7.0.1",
"gulp-rename": "1.2.2",
"gulp-sass": "3.2.0",
"gulp-sourcemaps": "2.6.4"

gulpfile.js:

const fs = require('fs');
const nodeSpawn = require('child_process').spawn;
const gulp = require('gulp');

const plugins = {
	sourcemaps: require('gulp-sourcemaps'),
	sass: require('gulp-sass'),
	postcss: require('gulp-postcss')
}
const cssnano = require('cssnano');

var STYLES_SRC = './src/styles/';
var STYLES_ENTRY = './src/styles/styles.scss';
var STYLES_DEST = './dist/';

var processors = [
	cssnano({
		discardComments: { removeAll: true },
		discardUnused: false, // unsafe, see http://goo.gl/RtrzwF
		zindex: false, // unsafe, see http://goo.gl/vZ4gbQ
		reduceIdents: false // unsafe, see http://goo.gl/tNOPv0
	})
];

var isProd = false;

// execute process
function spawn(command, args, cb) {
	var proc = nodeSpawn(command, args, {
		stdio: 'inherit',
		detached: false,
		env: process.env, shell: true
	});
	proc.on('error', function (err) { console.error(err) });
	if (cb != null) {
		proc.on('close', function (code, signal) { cb(code); });
	}
	return proc;
}

// watch styles task
gulp.task('watch::styles', ['build.styles'], function (done) {
	gulp.watch(STYLES_SRC + '**/*.scss', ['build.styles']);
});

// Build styles task
gulp.task('build.styles', function () {
	var src = 
		[STYLES_ENTRY];
	
	return isProd ?
		gulp.src(src)
			.pipe(plugins.sass({ includePaths: ['./node_modules/'] }).on('error', plugins.sass.logError))
			.pipe(plugins.postcss(processors))
			.pipe(gulp.dest(STYLES_DEST))
		: gulp.src(src)
			.pipe(plugins.sourcemaps.init())
			.pipe(plugins.sass({ includePaths: ['./node_modules/'] }).on('error', plugins.sass.logError))
			.pipe(plugins.sourcemaps.write(''))
			.pipe(gulp.dest(STYLES_DEST));
});

// task to build and watch dev
gulp.task('build.devw', function (done) {
	spawn('npm', ['run ngbuilddevw'], done);
	gulp.start('watch::styles');
});

// task to build prod
gulp.task('build.prod', function () {
        isProd = true;
	spawn('npm', ['run ngbuild'], function (code) {
		gulp.start('build.styles');
	});
});

Hope this is of some help.

I use ng serve -sm -ec and it does not work for global styles. I don’t use component styles.

@michael-letcher Thanks. missed that. I confirm it’s working now for scss.

@smlombardi, it looks like your devtool definition is not at right level of configuration. Examine the structure of return {…} @CharltonC provided. The exact line number in the common.js file may vary. I hope this helps.

@smlombardi Yeah, seems like a bug from at least 1.6.2 onwards

I am not even using ~ we use:

      "styles": [
        "../node_modules/prismjs/themes/prism.css",
        "../node_modules/@ngx-loading-bar/core/loading-bar.css",
        "../node_modules/ng2-toastr/bundles/ng2-toastr.min.css",
        "sass/designsystem/designsystem.scss",
        "styles.scss"
      ],
      "scripts": [
        "../node_modules/jquery/dist/jquery.slim.js",
        "../node_modules/popper.js/dist/umd//popper.min.js",
        "../node_modules/bootstrap/dist/js/bootstrap.js"
      ],

The css is complied and works for all of these, but no source maps.