angular: Ivy: Unable to write a reference
đ bug report
Affected Package
@angular/compiler-cli
Is this a regression?
No, does not seem so.
Description
When building my Angular app with Ivy enabled, I get this error:
ERROR in Unable to write a reference to AccordionDirective in /Users/dirkluijk/path/to/project/libs/widgets/src/lib/accordion/accordion.directive.ts from /Users/dirkluijk/path/to/project/libs/widgets/src/lib/accordion/accordion.module.ts
đŹ Minimal Reproduction
I have a complex project setup, a monorepo with multiple Angular libs.
đ„ Exception or Error
With some debug statements in node_modules/@angular/compiler-cli/src/ngtsc/imports/src/emitter.js
my output looks like this:
$ ng serve p1
0% compiling
EMITTED LocalIdentifierStrategy HttpClientModule /Users/dirkluijk/path/to/project/libs/api/src/lib/api.module.ts
EMITTED AbsoluteModuleStrategy HttpClientModule /Users/dirkluijk/path/to/project/libs/api/src/lib/api.module.ts
EMITTED AbsoluteModuleStrategy HttpClientXsrfModule /Users/dirkluijk/path/to/project/libs/api/src/lib/api.module.ts
EMITTED AbsoluteModuleStrategy HttpClientXsrfModule /Users/dirkluijk/path/to/project/libs/api/src/lib/api.module.ts
EMITTED LocalIdentifierStrategy AccordionDirective /Users/dirkluijk/path/to/project/libs/widgets/src/lib/accordion/accordion.module.ts
Date: 2019-03-17T19:52:02.577Z
Hash: 655d0cccad5d9464bf74
Time: 7484ms
chunk {main} main.js, main.js.map (main) 1.89 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 704 bytes [initial] [rendered]
chunk {polyfills.es5} polyfills.es5.js, polyfills.es5.js.map (polyfills.es5) 322 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.08 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 643 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 330 kB [initial] [rendered]
ERROR in Unable to write a reference to AccordionDirective in /Users/dirkluijk/path/to/project/libs/widgets/src/lib/accordion/accordion.directive.ts from /Users/dirkluijk/path/to/project/libs/widgets/src/lib/accordion/accordion.module.ts
Failed to compile.
đ Your Environment
Angular Version:
Angular CLI: 8.0.0-beta.7
Node: 10.9.0
OS: darwin x64
Angular: 8.0.0-beta.8
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.800.0-beta.7
@angular-devkit/build-angular 0.800.0-beta.7
@angular-devkit/build-optimizer 0.800.0-beta.7
@angular-devkit/build-webpack 0.800.0-beta.7
@angular-devkit/core 8.0.0-beta.7
@angular-devkit/schematics 8.0.0-beta.7
@angular/cdk 7.1.1
@angular/cli 8.0.0-beta.7
@ngtools/webpack 8.0.0-beta.7
@schematics/angular 8.0.0-beta.7
@schematics/update 0.800.0-beta.7
rxjs 6.3.3
typescript 3.1.6
webpack 4.29.6
Anything else relevant? I make use of Typescript paths, combined with barrel files.
{
"compilerOptions": {
"paths": {
"@p1/api": [
"libs/api/src"
],
"@p1/common": [
"libs/common/src"
],
"@p1/testing": [
"libs/testing/src"
],
"@p1/interactions": [
"libs/interactions/src"
],
"@p1/widgets": [
"libs/widgets/src"
],
"@p1/features": [
"libs/features/src"
]
},
}
}
When I remove the error throw in node_modules/@angular/compiler-cli/src/ngtsc/imports/src/emitter.js
, it seems that the files that fail are completely random:
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 36
- Comments: 61 (25 by maintainers)
Commits related to this issue
- feat(ivy): re-export the compilation scope of NgModules privately This commit refactors the aliasing system to support multiple different AliasingHost implementations, which control specific aliasing... — committed to alxhub/angular by alxhub 5 years ago
- feat(ivy): re-export the compilation scope of NgModules privately This commit refactors the aliasing system to support multiple different AliasingHost implementations, which control specific aliasing... — committed to alxhub/angular by alxhub 5 years ago
- feat(ivy): re-export the compilation scope of NgModules privately This commit refactors the aliasing system to support multiple different AliasingHost implementations, which control specific aliasing... — committed to alxhub/angular by alxhub 5 years ago
- feat(ivy): enable re-export of the compilation scope of NgModules privately This commit refactors the aliasing system to support multiple different AliasingHost implementations, which control specifi... — committed to alxhub/angular by alxhub 5 years ago
- feat(ivy): enable re-export of the compilation scope of NgModules privately This commit refactors the aliasing system to support multiple different AliasingHost implementations, which control specifi... — committed to alxhub/angular by alxhub 5 years ago
- feat(ivy): enable re-export of the compilation scope of NgModules privately This commit refactors the aliasing system to support multiple different AliasingHost implementations, which control specifi... — committed to alxhub/angular by alxhub 5 years ago
- feat(ivy): enable re-export of the compilation scope of NgModules privately This commit refactors the aliasing system to support multiple different AliasingHost implementations, which control specifi... — committed to alxhub/angular by alxhub 5 years ago
- feat(ivy): enable re-export of the compilation scope of NgModules privately (#33177) This commit refactors the aliasing system to support multiple different AliasingHost implementations, which contro... — committed to AndrusGerman/angular by alxhub 5 years ago
Hello all! For people monitoring this issue, I just wanted to give a quick update. Iâve put together a design doc describing the problem and my proposed solution. The basic idea is that in
tsconfig.json
youâll tell the Angular compiler which of your path-mapped libraries are âprivateâ. That will give the compiler enough information to correctly generate imports for the directives/components within those libraries.Same error:
Only happens with Ivy.
@p3x-robot this works in my case:
"rootDir": "."
to thecompilerOptions
in the roottsconfig.json
BTW, thank you guys @pburkindine @james-criscuolo, youâre my favorite
I have exactly same problem, IMO
freq
will not be low Is there any workaround?Hi we met the same problem, I think the freq is not
low
, and it blocks lots of angular lib to migrate to ivy. https://github.com/NG-ZORRO/ng-zorro-antd/pull/3740/files#diff-5@alxhub Wow, thank you for your detailed explanation! Yes, it was hard to debug, as I didnât even know what it is used for exactly.
So you say that a barrel file from an Angular Package Format module (e.g. built with ngPackagr) is not the same as a regular barrel file from a path-mapped directory? I didnât know that before.
The reason I use this project layout, is that it should not matter if the package was actually pre-built or just a âlocal libraryâ (monorepo approach). As a matter of fact, I just use the Nx Workspace project layout which is basically a Angular App + Angular Libs monorepo structure.
I will create a tracking issue at the Nrwl repo as well. In the mean time, what is your suggestion for monorepos like this?
I think Ivy is far from production stable.
@JoostK I can provide a repo here https://github.com/gnomeontherun/clarity/tree/angular9.
Run
ng build --prod
to see the following write reference error:I managed to get it working folloing @rt-gavrilov workaround and this article https://medium.com/@raviroshan.talk/fix-for-continuous-build-of-library-in-angular-workspace-c18422bab927
Steps to follow:
Library index.ts
ng-package.json
Change the paths inside compilerOptions to reference projects instead of dist
root tsconfig.json
AppModule
Now I can livereload angular libraries, wich is very convenient for development. Iâm currently using â@angular/coreâ: â~9.0.0-next.3â. Hope it helps someone.
Seems like the main issue is that people want to avoid building library separately when it is consumed by the application and of course others also want a way to build the library separately and publish it.
Here are my thoughts, lets consider such mapping of paths in tsconfig:
Desired behavior from my side:
xyz-core
should be allowed (just like any external lib)xyz-core
lib imports with relative paths (scoped to the library) and imports viaxyz-core/*
path should be allowed. The latter is a bit more explicit and lets you avoid imports starting with 'âŠ/âŠ/âŠ/` (we also have tslint rule for this).xyz-core/*
in application / other library. Currently build still works.At least this seem to work in non-ivy build,
Now the problem as I see is that when you build application, and import
some.service.ts
fromxyz-core
, it will most likely import other files which some of them may not even be part of barrel file (private) or use import fromxyz-core/utils/index
.Maybe tsconfig.lib.ts could be used when path mapping points to a library barrel file to enrich typescript configuration (and ivy) with extra mappings during build? This way mapping of
xyz-core/*
could be left inside tsconfig.lib.json@alxhub: Thank you for your hard work on this. Really appreciated!
For me at least the solution with a regular @nrwl/nx setup was just to add
"rootDir": "."
to thecompilerOptions
intsconfig.json
; thanks @james-criscuoloOn to the next errorâŠ
Iâm impressed by your debugging here! Out of curiosity, how hard was it to follow the logic?
Youâre correct that the library not being in
rootDirs
is the cause of your error. This is not a supported configuration at the moment.Currently, we support generating imports to files in two places:
APF guarantees that if FooModule is imported from âpackage/fooâ, then the components it declares (e.g. FooComponent) are also available by importing âpackage/fooâ.
Your path-mapped packages are of a third kind - outside the project, but also not in the APF. So assuming this layout:
your app might write
which is perfectly valid to do. However, Itâs not valid to assume that
WidgetComponent
is also importable via the same path@p1/widgets/module
, as it would be in an APF package. So what import should the Ivy compiler generate?The obvious answer is
@p1/widgets/component
, but how does the compiler arrive at this? It would have to reverse engineer the path mapping and figure out that a filelibs/widgets/src/X
should be referred to as@p1/widgets/X
. And the same directory can have multiple paths mapped to it. Path mappings were never intended to work this way.So today, we donât support this kind of layout. As we start looking more at this kind of multi-project use case, maybe weâll introduce some mechanisms to support this.
by the way, do you guys know why Ivy is why has a 100kb larger bundle?
I fixed it! I am all repos on Ivy on Angular 8.1.0! The paths are working now, it looks like it does not like the
@Host()
decorator for Ivy. I replaced with a global variable and it is working! Ivy is picky, but I hacked it!THANKS YO ALL!
@p3x-robot They do that for all issues that doesnât affect the majority of users based on my experience. Also itâs not OP adding the labels, itâs the Angular-team. @dirkluijk is innocent.
I am no longer receiving the
Unable to write a reference
error. The problem was that mypaths
mapping intsconfig.json
was configured such that the libraries were referenced in theprojects
directory instead of thedist
directory (for live library reload capability as commented above by @vgb1993). I understand however that this is not a supported configuration.@JoostK thanks for responding. I added your suggested configuration but same result. I will try to create a reproducible repo that I can share.
as of 8.2.12 it is not deployed here: https://github.com/angular/angular/blob/8.2.12/packages/compiler-cli/src/ngtsc/imports/src/alias.ts Should have a FileToModuleAliasingHost classâŠ
@matsko: Will this be shipped in Angular@8.x.x?
Ivy does not like raw modules in
node_modules
. i needed a build step and move those packages into an out of node_modules into calledbuild-modules
(just copied those 2 modules into the build-modules folder) and now it is perfect.I did some digging into the angular source and discovered my
rootDir
was âwrongâ so the build process wasnât finding anything. I happen to have a repo where thebuild
directory and thesrc
directory are in the same directory, and have set it up so that i can run my npm scripts from that parent and everything works. To get past this problem, I needed to add arootDir
argument to mytsconfig.json
in mybuild
directory pointing to mysrc
directory. I had not set therootDir
intsconfig.json
previously, but now I can get past this error and complete a build (now on to runtime errors đ )I realize this was mentioned earlier, but given I had no
rootDir
orrootDirs
at all, I ignored it. If you also did that, it now appears one of the two must be set.