Angular-cli: Stylesheet from (npm) linked package not loaded correctly

Created on 9 Dec 2016  路  26Comments  路  Source: angular/angular-cli

OS

Tested on both Windows 7 and Linux (Fedora 24)

Version

$ ng --version
angular-cli: 1.0.0-beta.22-1
node: 4.6.1
os: linux x64

The app was created using CLI.

Repro steps

  1. Install a package containing a stylesheet (say bootstrap-sass, actually any package will do) globally via npm.
  2. git clone https://github.com/twbs/bootstrap-sass.git into a working directory, cd to that working directory and perform npm link command.
  3. ng new project in another separate directory, cd to the newly create project directory and perform npm link bootstrap-sass. This will create a bootstrap-sass symlink in node_modules pointing to the local git repository.
  4. Modify angular-cli.json to reference the stylesheet in the linked package.
      "styles": [
        "../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss",
        "styles.scss"
      ],
  1. ng serve and observe that styles from bootstrap is not exported correctly in the index page.
  2. ng build and observe that the generated styles.bundle.js does not do "exports.push()".

The log given by the failure

There was no error log, webpack declared the "bundle is now valid".

Mention any other details that might be useful

Using normal npm install approach does not have this issue. i.e. after npm unlink bootstrap-sass && npm install bootstrap-sass then all is fine.

Use case: I have a forked gentelella repository locally to fix some of the issues I found, so I cannot just simply npm install it in my project. Using npm link approach as I outlined above should work. It seems angular-cli (or webpack, I am not sure) is being confused by symlink. As a temporary workaround, I replace the stylesheet reference in the angular-cli.json with an absolute path to the stylesheet file in the local git repo.

devkibuild-angular low help wanted broken triage #1 bufix

Most helpful comment

@filipesilva As mentioned in this comment the fix only appears to apply to SCSS/CSS/JS, but not to static assets like font files (used by font-awesome, material-design-icons, etc).

Should we open a separate issue for that?

All 26 comments

For a cleaner workaround, you can npm install using the path to the forked package.

For a cleaner workaround, you can npm install using the path to the forked package.

@clydin Thanks for your reply. The npm install will just install a snapshot of the local repo. This would force me to redo the install each time I make changes in my local repo. With symlink all changes are automatically reflected in my project using the linked package.

I also do not want to just check-in the stylesheet in question into my own project repo and use the @import in the styles.scss as the workaround (although it would also work) because: 1) I don't want to break the linkage with upstream so that I could still easily merge upstream changes; 2) I can also easily contribute back my fixes back to upstream.

Using @import "../node_modules/gentelella/src/scss/custom"; in the styles.scss as the workaround now. The sass preprocessor handles the symlink well.

CLI doesn't seem to copy anything outside of the src folder, but should be able to copy from node_modules.

To reproduce this weird issue just try to copy file one level up of src folder

@serhiisol it can copy from outside src, in the example repo for #3542 it pulls the styles for buttons but the column styles are not applying.

@zackarychapple where is the copy process specified in this repo? angular cli json doesn't have it in example you've provided : https://github.com/zackarychapple/bootstrap-ng2/blob/master/angular-cli.json

@serhiisol I tried @import "../node_modules/bootstrap/scss/bootstrap-flex"; in https://github.com/zackarychapple/bootstrap-ng2/blob/master/src/styles.scss as well as in the angular-cli.json and neither option worked.

@zackarychapple but your last comment is opposite to the one before :)

@serhiisol you're right the code I committed was after I removed the line that copied from src.

@hansl is it possible to add the ability to resolve node_modules directly in the sass with something like https://github.com/jtangelder/sass-loader as this issue is fixed?

Now that https://github.com/angular/angular-cli/issues/3401 is done, it should be feasible to do something like what was originally requested:

"styles": [
  { "input": "../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss", "output": "bootstrap.css" },
  "styles.scss"
],

Can you see if this solves it?

I have upgraded to angular-cli 1.0.0-beta.24 to test this and modifed my angular-cli.json as you suggested. Still not working if the input file is in a symlink directory. It works only if the input file is in a normal directory.

EDIT: correct typo.

@filipesilva As mentioned in this comment the fix only appears to apply to SCSS/CSS/JS, but not to static assets like font files (used by font-awesome, material-design-icons, etc).

Should we open a separate issue for that?

@Splaktar this functionality now exists for assets as well.

Closing as outdated. If this is still a problem, please let me know.

@filipesilva Could you provide a reference for implementing this? I'm having a similar issue

I am also running into this same issue. Whenever I try to add a .css file to my .angular-cli.json from a symlinked directory within node_modules (from npm link), it does not pull it in to the build.

The exact same .css file in a non-symlinked directory gets pulled in just fine, but that does not do me any good.

I tried the solution posted a couple of posts above by @filipesilva but it did not change the behavior.

Edit: Using @require in my application's base .scss file to load the .css file from the linked node_modules folder does allow me to work around for now, but it is not an ideal solution.

Reopening as there are reports of this still happening for scss files.

This is probably related: If the node_modules directory itself is a symlink, css files are ignored as well.

I also encounter this bug and I must say it is VERY difficult to debug. No warning, no error at all. The styles.bundle.js file even includes the correct path to the css file!!!

My project uses yarn workspaces so symlink css is very common. Until angular-cli found a proper way to deal with symlink css-loader, the only work around and false-negative way is to import css files directly into a global .scss file, then include the scss file in .angular-cli.json.

This way the compiler will throw an error when the file is not resolved by css-loader. Really looking forward to this problem being solved, it's been a show stopper for us.

Greetings! Is there an ETA on this? I recently expanded my project to a second application, with a lot of duplicate node_modules required. So I moved the node_modules directory up one level, and created windows symlinks from each projects' node_modules directory to the node_directory one level up. Seems to be working for the most part except, as indicated in the past, the CSS files aren't being pulled in.

I'm also experiencing this. I'm trying to co-develop a css library alongside our application. We store our fonts inside of the css library, so the scss import workaround does not work. ng serve breaks because the CLI looks inside of the app directory for those fonts rather than inside the linked module. Are there any plans to pull this out of the backlog?

+1 same here

Cannot import css from angular.json if node_modules is a symbolic link.

Hello, I have a similar issue, I have a common node_modules directory that I link in my projects with:
(windows) mklink /J node_modules D:\node_modules
(linux) ln -s ~/node_modules
All seems to work but including css files in node_modules(e.g. "node_modules/bootstrap/dist/css/bootstrap.min.css") to angular.json.
Adding such css to src/style.css by
@import "~bootstrap/dist/css/bootstrap.min.css";
works fine, but I cannot use angular.json to do that.
Deleting node_modules symlink and copying the whole node_modules directory inside the project let angular.json css import from node_modules working again.
So it seems the angular-cli has issues with symbolic links to node_modules.

I hit what I thought was a similar issue and used the shell script below to build and example environment to work in.

#!/bin/bash
#
# ngcli_bug3500.sh
#
# This creates an ng project and add a unit test to which fails
# if @angular/cli issue 3500 is unfixed 
#
#
# (C) Roger Gammans <[email protected]>
# This file can be freely redistributed.

## Comment this out to use an already in scope @Angular/cli installation
npm i @angular/cli

npx ng new cli3500 --defaults
cd cli3500
mkdir foo
cat > foo/test.css <<EOF

.nothere {
    display: none;
}

EOF
ln -s foo bar
mv src/app/app.component.spec.ts src/app/app.component.spec.ts.orig
head -n -1 src/app/app.component.spec.ts.orig > src/app/app.component.spec.ts
cat >> src/app/app.component.spec.ts  << EOF

  it('should render check element invisibly', () => {
    /* This checks the access to the new css ; which should hide it
     */
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('div.nothere').offsetHeight).toBe(0);
  });
});

EOF

cat >> src/app/app.component.html << EOF
<div class="nothere">Some texts this is any.</div>
EOF

## Add './bar/test.css' to angular json
#  first write out a node script to
#  do the change then execute it.
cat > mod_ng_json.js <<EOF
'use strict';

function do_append(ary, value) {
    ary[ary.length] = value
}

const fs = require('fs');

// Read in angular.json
let rawdata = fs.readFileSync('angular.json.bak');
let cli_conf= JSON.parse(rawdata);

// Change it and write it out
do_append(cli_conf["projects"]["cli3500"]["architect"]["build"]["options"]["styles"],"./bar/test.css")
do_append(cli_conf["projects"]["cli3500"]["architect"]["test"]["options"]["styles"],"./bar/test.css")

fs.writeFileSync('angular.json',JSON.stringify(cli_conf,null,2));

EOF
mv angular.json angular.json.bak
nodejs mod_ng_json.js

#Run the app tests (one should fail if this bug is not fixed)
npx ng test

Using the created app I聽tracked the fact the the stylesheets where being loaded by webpack, but by their canonical absolute path.

This (eventually)聽lead me to looking at webpack bugs and I聽found this , https://github.com/webpack/webpack/issues/8824 , which then lead me to the webpack resolveSymlink option.

With a bit more digging I聽can make the test project I聽generated pass the tests by changing the options for the test command in angular.json (and other commands will need it as well) to add

        "test": {
          "options": {
            "preserveSymlinks": true,
           ...
         }
  }

It appears there might be some downside of symlink paths not being watched correctly with this option, and the webpack bug does suggest the issue could also be fixed by adding an extra reference to absolute canonical path to the webpack loader spec as well as the path 'through' the symlink.

Hope this help..

I think I've also run into something related to this:
in the "styles" section of angular.json, if I include a CSS file that is actually a symlink, angular builds the project OK and includes that symlinked CSS file, but if I make a change in the targeted CSS file, angular does not pick up the change and reload the new style.

Steps:

  • Create a new angular project, ng new
  • Take a CSS file that I'd like to share between angular projects, say "mystyle.scss".
  • I keep the file in a shared location and then symlink it within each angular project and then point to the symlinked version in angular.json.
  • Angular correctly builds & serves the app using "ng serve" (good!)
  • Make a change to mystyle.scss
  • Angular does not reload styles after this change or any subsequent change.
  • If I replace the symlinked version with the actual file, angular notices changes in that file and reloads the styles appropriately.
  • I also have "preserveSymlinks"=true in angular.json and tsconfig.json.

Still hapenning in this date. I just changed from NPM to PNPM (which apparently creates symlink for node_modules folder). Now none of my recently "migrated" projects are loading styles... No SCSS for me, just plain old CSS.

Any idea on when are we gonna have solution for this? And any temporary workaround? A good one?

Was this page helpful?
0 / 5 - 0 ratings