Angular-cli: Module path prefix is not used to resolve styleUrl or templateUrl with AoT

Created on 27 Feb 2017  ·  7Comments  ·  Source: angular/angular-cli

OS?

Windows 10

Versions.

@angular/cli: 1.0.0-rc.0
node: 7.5.0
os: win32 x64
@angular/common: 4.0.0-rc.1
@angular/compiler: 4.0.0-rc.1
@angular/core: 4.0.0-rc.1
@angular/flex-layout: 2.0.0-rc.1
@angular/forms: 4.0.0-rc.1
@angular/http: 4.0.0-rc.1
@angular/platform-browser: 4.0.0-rc.1
@angular/platform-browser-dynamic: 4.0.0-rc.1
@angular/router: 4.0.0-rc.1
@angular/cli: 1.0.0-rc.0
@angular/compiler-cli: 4.0.0-rc.1

Repro steps.

Due to reasons we have our style sheets in a separate root folder. A couple versions ago we were able to load the styling using:

@Component({
    //...
    styleUrls: [
        "@style_folder/components/component/name.component.scss"
    ]
})

Then something changed a couple versions ago and module paths were resolved as relative paths, so ./ was appended to the url. This is done in the loader-utils package. I've read there that I could append a ~ to the url, to convert it to a module request. (~@style_folder/bla/bla) This worked splendidly (with the minor downside that I could no longer navigate to it using my IDE).

We are in the process of making our application AoT compatible, and to our big surprise, the ~ trick doesn't work there, because AoT thinks it's a relative path no matter what.

We would prefer it to not have all relative paths inside our styleUrls (../../../ horror). Better would be that both JIT and AoT look at the paths defined in tsconfig.json (like it was before I believe) and look there for a definition, and only after that assume it's a relative path if there is no match.

1 (urgent) bufix

All 7 comments

Sounds like a bug to me. Thanks for reporting it!

@sumitarora can you have a look?

@PierreDuc Is there a repo that I can check the issue. I tried to replicate and it seems to be failing in bot JIT and AOT with or witout ~.

 ~/w/o/t/t2   master *…  ng s                                                                                           1.4m  Tue 14 Mar 13:13:38 2017
** NG Live Development Server is running on http://localhost:4200 **
Hash: 789faea35224a98f2cfe
Time: 4933ms
chunk    {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 158 kB {4} [initial] [rendered]
chunk    {1} main.bundle.js, main.bundle.js.map (main) 5.06 kB {3} [initial] [rendered]
chunk    {2} styles.bundle.js, styles.bundle.js.map (styles) 9.91 kB {4} [initial] [rendered]
chunk    {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.26 MB [initial] [rendered]
chunk    {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]

ERROR in ./src/app/hello/hello.component.ts
Module not found: Error: Can't resolve '@style-paths/hello.component' in '/Users/sumitarora/workspace/open-source/temp/t2/src/app/hello'
 @ ./src/app/hello/hello.component.ts 22:17-56
 @ ./src/app/app.module.ts
 @ ./src/main.ts
 @ multi webpack-dev-server/client?http://localhost:4200 ./src/main.ts
webpack: Failed to compile.
^C⏎                                                                                                                                                        !  ~/w/o/t/t2   master *…  ng s --aot                                                                                13.3s  Tue 14 Mar 13:21:33 2017
** NG Live Development Server is running on http://localhost:4200 **
Hash: f040d2d99ec59b023a6d
Time: 2439ms
chunk    {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 158 kB {4} [initial] [rendered]
chunk    {1} styles.bundle.js, styles.bundle.js.map (styles) 9.91 kB {4} [initial] [rendered]
chunk    {2} main.bundle.js, main.bundle.js.map (main) 1.1 kB {3} [initial] [rendered]
chunk    {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 1.07 MB [initial] [rendered]
chunk    {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]

ERROR in ENOENT: no such file or directory, open '/Users/sumitarora/workspace/open-source/temp/t2/src/app/hello/~@style-paths/hello.component'

ERROR in ./src/main.ts
Module not found: Error: Can't resolve './$$_gendir/app/app.module.ngfactory' in '/Users/sumitarora/workspace/open-source/temp/t2/src'
 @ ./src/main.ts 4:0-74
 @ multi webpack-dev-server/client?http://localhost:4200 ./src/main.ts
webpack: Failed to compile.
^C⏎                                                                                                                                                        !  ~/w/o/t/t2   master *…  ng s                                                                                      22.6s  Tue 14 Mar 13:21:59 2017
** NG Live Development Server is running on http://localhost:4200 **
Hash: f7a7a95c3f6047402914
Time: 4891ms
chunk    {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 158 kB {4} [initial] [rendered]
chunk    {1} main.bundle.js, main.bundle.js.map (main) 5.06 kB {3} [initial] [rendered]
chunk    {2} styles.bundle.js, styles.bundle.js.map (styles) 9.91 kB {4} [initial] [rendered]
chunk    {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.26 MB [initial] [rendered]
chunk    {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]

ERROR in ./src/app/hello/hello.component.ts
Module not found: Error: Can't resolve './@style-paths/hello.component' in '/Users/sumitarora/workspace/open-source/temp/t2/src/app/hello'
 @ ./src/app/hello/hello.component.ts 22:17-58
 @ ./src/app/app.module.ts
 @ ./src/main.ts
 @ multi webpack-dev-server/client?http://localhost:4200 ./src/main.ts
webpack: Failed to compile.
^C⏎                                                                                                                                                        !  ~/w/o/t/t2   master *…  ng s --aot                                                                                23.4s  Tue 14 Mar 13:22:31 2017
** NG Live Development Server is running on http://localhost:4200 **
Hash: d4f674febff20caea8c9
Time: 2440ms
chunk    {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 158 kB {4} [initial] [rendered]
chunk    {1} styles.bundle.js, styles.bundle.js.map (styles) 9.91 kB {4} [initial] [rendered]
chunk    {2} main.bundle.js, main.bundle.js.map (main) 1.1 kB {3} [initial] [rendered]
chunk    {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 1.07 MB [initial] [rendered]
chunk    {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]

ERROR in ENOENT: no such file or directory, open '/Users/sumitarora/workspace/open-source/temp/t2/src/app/hello/@style-paths/hello.component'

ERROR in ./src/main.ts
Module not found: Error: Can't resolve './$$_gendir/app/app.module.ngfactory' in '/Users/sumitarora/workspace/open-source/temp/t2/src'
 @ ./src/main.ts 4:0-74
 @ multi webpack-dev-server/client?http://localhost:4200 ./src/main.ts
webpack: Failed to compile.
^C⏎

@sumitarora I've created a repo https://github.com/PierreDuc/angular-cli-test.git

If you run ng serve, it works fine, but if you run ng serve --aot it fails. I did notice that if you specify paths inside the tsconfig.json, that these are not taken into consideration (any more) while resolving style urls. As far as I know, that's how it used to work, but I could be mistaken.

How it is now:

  • ~style/path/to/style.scss
    This will be resolved as a module path in JIT, which in the case of the repo I posted will be src/style/path/to/style.scss. In AOT this gets parsed to src/app/~style/path/to/style.scss. So a ./ is prepended to the url, even though there is a ~ (module identifier).

  • style/path/to/style.scss
    Unfortunately this used to work, but nowadays this is resolved as a relative path in both JIT and AOT by prepending ./ to the url

The parsing is done, at least for JIT in the loader-utils package. AOT doesn't seem to be using this package. This is probably because ngc already fails because of the faulty path. I guess this is going to be more an issue at @angular itself.

Preferably (at least for me) will be that a styleUrl or templateUrl will not be prepended by ./ when there is a match in the paths inside the tsconfig.json. Best would be not to prepend at all, but I believe that will break a lot of current builds.

Less preferable, but still workable would be that in AOT the ~ notation also works, the only downside is that IDE navigation is not working using this notation

This is actually a "bug" in JIT. styleUrls and templateUrl are supposed to be relative only, both in AOT and JIT.

What JIT does is replace styleUrls: [ 'example' ] with styles: [ require('example') ] which is then passed down to webpack which does the resolution of example, etc. What AOT does is read the file directly without using webpack. This logic aligns with ngc. We should not allow invalid URLs.

https://github.com/angular/angular-cli/pull/3842 should have aligned both together, but instead relies on webpack to resolve it in JIT. The solution here is to remove the webpack resolution from the loader.

We're aware this will cause pain for people and are talking internally to make sure the plan is clear. ~ or path mapping should have never worked in JIT.

That's what I was afraid of. I suspect this 'feature' of ~ or path mapping won't find it's way back soon into cli, unless they adopt it in ngc. Guess I have to a write a script to replace all module paths to relative paths in my projects.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NCC1701M picture NCC1701M  ·  3Comments

hareeshav picture hareeshav  ·  3Comments

sysmat picture sysmat  ·  3Comments

brtnshrdr picture brtnshrdr  ·  3Comments

hartjo picture hartjo  ·  3Comments