Angular-cli: ng serve - npm linked library changes(updates) are not reflected in UI

Created on 5 May 2017  Β·  85Comments  Β·  Source: angular/angular-cli

Bug Report or Feature Request (mark with an x)

- [x] bug report -> please search issues before submitting
- [ ] feature request

Versions.

@angular/cli: 1.0.1
node: 6.10.1
os: darwin x64
@angular/common: 4.1.1
@angular/core: 4.1.1
@angular/forms: 4.1.1
@angular/http: 4.1.1
@angular/platform-browser: 4.1.1
@angular/platform-browser-dynamic: 4.1.1
@angular/router: 4.1.1
@angular/cli: 1.0.1
@angular/compiler: 4.1.1
@angular/compiler-cli: 4.1.1

macOs Sierra 10.12.4
Node: v6.10.1
Npm: 3.10.10

Repro steps.

  • Generate 'myProject' with angular-cli
  • Add a private npm package: npm install @private/etcPackage --save (it's a angular4 library)
  • Go to the private package local path and 'npm link'
  • Go to 'myProject' and run: npm link @private/etcPackage
  • Delete 'node_modules' from 'myProject/node_modules/@private/etcPackage'
  • start serve: ng serve --aot
  • on library project, '/localpath/etcPackage' run gulp (this will trigger watch and build on change)

Since this dist folder it's linked with node_modules one in my angular project 'myProject' for every build the package is update.

The log given by the failure.

Doesn't update UI on changes.

Desired functionality.

When the library (etc - in our case) it's compiled along with it's resources, the angular-cli project should see the changes and update the UI. Eg: external html templates and css - not updated.

Mention any other details that might be useful.

  • I'm using templateUrl: 'etc.html' and not have any template inline;
  • If any change is made to componentName.ts file - this is reflected on screen (eg: variables);
  • Changes exist after library it gets build in 'myProject/node_modules/@private/etcPackage' folder, so link it's working;
  • Even if i refresh page, and I check main.bundle.js - changes are there compiled, but still are not visible on screen unless I stop serve and start it again.

--

Question is, anything can be done or need create a separate watch script to support both the library and myProject?

help wanted 1 (urgent)

Most helpful comment

I do have kind of a similar problem and tried to create a simple example that hightlights it.

Libraries used:

  • AngularCLI to create the project (https://github.com/angular/angular-cli) -> Version 1.0.3
  • generator-angular2-library to create the library (https://github.com/jvandemo/generator-angular2-library) -> Version 10.1.0

Dev Environment:

Projects used:

Steps to reproduce:
Clone the two mentioned repositories

In angular-library:

  • npm install && npm run build
  • cd dist && npm link

In cli-project

  • npm link angular-library
  • npm install
  • npm start

Open App in Browser - you should see "Sample component 2" as the second heading.

Go back to the angular-library project.

  • npm run build:watch
  • Change the template of the fiel "sample.component.ts" in the src folder (e. g. remove the word "sample"

It is getting recompiled directly by gulp, the dist folder is updated correctly.
In the cli-project, the content of "node_modules/angular-library/index.js" got also updated correctly.
However, the cli does not recompile, therefore the browser will not reload either.
Restarting the cli with ng serve will then make the change finally visible.

Expected behaviour:
CLI starts recompiling when some npm linked module in the node_modules directory changes

All 85 comments

The reproduction of this issue is highly dependent on the build process you're using for your library. Can you provide a runnable repro we can look at?

I do have kind of a similar problem and tried to create a simple example that hightlights it.

Libraries used:

  • AngularCLI to create the project (https://github.com/angular/angular-cli) -> Version 1.0.3
  • generator-angular2-library to create the library (https://github.com/jvandemo/generator-angular2-library) -> Version 10.1.0

Dev Environment:

Projects used:

Steps to reproduce:
Clone the two mentioned repositories

In angular-library:

  • npm install && npm run build
  • cd dist && npm link

In cli-project

  • npm link angular-library
  • npm install
  • npm start

Open App in Browser - you should see "Sample component 2" as the second heading.

Go back to the angular-library project.

  • npm run build:watch
  • Change the template of the fiel "sample.component.ts" in the src folder (e. g. remove the word "sample"

It is getting recompiled directly by gulp, the dist folder is updated correctly.
In the cli-project, the content of "node_modules/angular-library/index.js" got also updated correctly.
However, the cli does not recompile, therefore the browser will not reload either.
Restarting the cli with ng serve will then make the change finally visible.

Expected behaviour:
CLI starts recompiling when some npm linked module in the node_modules directory changes

Fun fact: Cannot reproduce on macOS Sierra 10.12.4

Was able to reproduce using the @joachimprinzbach 's projects on:
Windows 10 OS Build: 14393.1198
Node: v6.10.3
with @angular/cli v1.0.3

Interestingly enough though: ng build --watch within the cli-project correctly sees changes to the library and rebuilds properly.

I recently started using the cli on windows, I'm having the same problem, to the point that I have to restart the server every other change.

Fun fact, this doesn't happen on Mac

Hey I think I know what's going on... that generator was based on a WIP starter of mine (https://github.com/filipesilva/angular-quickstart-lib), and I ran into this problem last week while making the linked lib docs (https://github.com/angular/angular-cli/pull/6292).

Turns out you cannot delete dist/ as this breaks the link (at least on windows). I updated my starter to reflect that, but the yeoman generator still deletes dist.

I opened an issue in https://github.com/jvandemo/generator-angular2-library/issues/91 to have it fixed.

Also, big kudos to @joachimprinzbach for the awesome repro. Once I saw the setup I instantly knew what was going on. Detailed repros rock 🀘

@filipesilva I have also seen that problem when I deleted the dist folder. The cli recognizes the change and the build brakes. This is a bug in the generator.

However, if you follow my steps in the same order as mentioned (build the library first, then start the watch task) - the problem is different. The library content gets correctly updated in the apps node_modules folder, the link works just fine. The only problem is, that the cli does not recognize the change. No recompilation happens, not even an error. The webpack-dev-server might be the problem?

@joachimprinzbach are you sure it's different? The watch task calls compile, which in turn calls clean:dist. That would mean it causes the same problem. Regardless, I'm going run through it to see.

You're right, something else is at play here. I followed everything and could see a refresh, node_modules content would reflect it, but the webpage would not change.

I also saw an error after a bunch of refreshes:

webpack: Compiled successfully.
webpack: Compiling...
Hash: b9005ad7c696c1f77702
Time: 7041ms
chunk    {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 157 kB {4} [initial]
chunk    {1} main.bundle.js, main.bundle.js.map (main) 4 kB {3} [initial] [rendered]
chunk    {2} styles.bundle.js, styles.bundle.js.map (styles) 10.5 kB {4} [initial]
chunk    {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.4 MB [initial] [rendered]
chunk    {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry]

ERROR in ../angular-library/dist/index.js
Module build failed: Error: ENOENT: no such file or directory, open 'D:\sandbox\angular-library\dist\index.js'
    at Error (native)
 @ ./src/app/app.module.ts 12:0-47
 @ ./src/main.ts
 @ multi webpack-dev-server/client?http://localhost:4200 ./src/main.ts
webpack: Failed to compile.

I think this this is caused by several files being deleted and regenerated at the same time. If you delete 'clean:dist', from line 173 and 182, refreshes work fine.

Now I'm not sure this is a CLI/Webpack problem. Is it reasonable to expect the build system to figure out that deleted JS modules are going to come back in a split second?

Maybe it is reasonable, and this problem has already been solved in Webpack somehow. Or maybe Webpack cannot deal with this. I don't know at the moment.

@TheLarkInn: Hey Sean, ever seen something like this?

@filipesilva, @joachimprinzbach — Just fo confirm that I am seeing the same behavior here (on Mac).

Setup:

  1. generate library using generator-angular2-library in directory my-lib
  2. in my-lib, run gulp to build my-lib/dist
  3. in my-lib/dist, run npm link
  4. generate app with Angular CLI in my-app
  5. in my-app, run npm link my-lib
  6. import my-lib in app.module.ts
  7. in my-app, run ng serve --aot

Scenario:

  1. change file in my-lib/src
  2. gulp will pick up change and regenerate my-lib/dist
  3. ng-serve --aot detects a change and recompiles successfully
  4. the web page does not reflect the change

Learnings so far:

  1. files in my-app/node_modules update correctly
  2. angular-cli does seem to detect the change and runs a compilation, but the output does not reflect the change
  3. running ng serve instead of ng serve --aot shows the change correctly

I will perform some additional research before work later this week πŸ‘

Watch recording to see it happening live on screen

Hm, I wonder why some users didn't see it in OSX then... and I should add that for me, on Windows, ng serve did not update (I didn't need --aot to repro).

I had similar issue with angular/cli 1.0.6.

-update were not always reflected
-I needed to shut ngServe down to get the updates
-Compilation time took sometimes too long (1min)

what worked for me was downgrading to version angular/[email protected]

i would recommend trying different service releases out the find a good working match of different libs.
by the way, i am using node v7.10.0

npm uninstall -g @angular/cli
npm chache clean
npm install -g @angular/[email protected]

hi, does anyone have a solution for this problem?

I have the same issue here. Working on
macOS Sierra 10.12.5.
@angular/[email protected]
node v8.1.2

This problem has obviously nothing to do with @jvandemo generator (great work btw).

try add a new method / property to a services, provided by a dependency lib linked to your cli-project, while both build-chains are listening for changes.
dependency lib and cli project will rebuild as expected but if you try to call this new method within the cli-project it will crash.

Method 'doSomething' does not exist on type 'MyService'

if you ng serve the cli-project again it works.

Can anyone reproduce this?

hi tom,

which editor are you using?

Am 23.06.2017 16:30 schrieb "Tom" notifications@github.com:

hi, does anyone have a solution for this problem?

I have the same issue here. Working on
macOS Sierra 10.12.5.
@angular/[email protected]
node v8.1.2

This problem has obviously nothing to do with @jvandemo
https://github.com/jvandemo generator (great work btw).

try add a new method / property to a services, provided by a dependency
lib linked to your cli-project, while both build-chains are listening for
changes.
dependency lib and cli project will rebuild as expected but if you try to
call this new method within the cli-project it will crash.

Method 'doSomething' does not exist on type 'MyService'

if you ng serve the cli-project again it works.

Can anyone reproduce this?

β€”
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/angular/angular-cli/issues/6195#issuecomment-310680557,
or mute the thread
https://github.com/notifications/unsubscribe-auth/APx6Y2JE9baoh-qDxUgvRbPBrqvO3Xc0ks5sG8wAgaJpZM4NR67M
.

VS Code Version 1.13.1

hi,

I think the cause can be vs code editor. Can you try to make changes with
the normal textedit and look if the changes get updated?

vs code has its own build in file watch mechanism and this can be likely to
clash with webpack's filewatch.

2017-06-24 0:28 GMT+02:00 Tom notifications@github.com:

VS Code Version 1.13.1

β€”
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/angular/angular-cli/issues/6195#issuecomment-310786706,
or mute the thread
https://github.com/notifications/unsubscribe-auth/APx6Y8ZIxamd782Mnd3ttxXjQnoJ0En7ks5sHDwdgaJpZM4NR67M
.

nice idea, but no, same behaviour if i use vim to edit my dependency lib.
i think the problem isn't the watch, because both the build setups get triggered correctly if i change a symlinked dependency.

what i also learned is that i can change property values or remove methods of a service provided by a linked dependency lib. But if i add new stuff, a new property for example, then my ng-cli app doesn't know about it. unless i restart the build process.

@synctom did you ever find a solution to this? We are seeing the same issue in our project but can't pinpoint the cause.

Same issue here, using npm-linked module in an angular app. The module is a plain typescript module with no angular dependencies. It uses tsc to produce a dist folder containing index.js and index.d.ts. The package.json specifies these as main and types.

Repro steps:

  • create new npm package my-package which exports Test
  • create new angular app my-app
  • use npm link to link package into the app
  • in app, import { Testing } from 'my-package'
  • run ng serve (fails: export is Test not Testing)
  • change my-package export Test to Testing
  • angular app rebuild is triggered, but has error:

ERROR in [...]/linked-lib-test/src/app/app.component.ts (2,10): Module '"[...]/linked-lib-test/node_modules/linked-lib/dist/index"' has no exported member 'Testing'.

File under node_modules/linked-lib/dist/index.js clearly does have an exported member Testing.

Stopping ng serve and then running it again results in a successful build.

screen shot 2017-07-25 at 3 14 00 pm

hi @tanyagray, unfortunately the issue still remains. angular cli is utilizing webpack to resolve module dependencies and build bundles. i believe the problem is somewhere in there.

In addition, the title of this issue is kind of misleading.
this problem isn't limited to ui changes.

looks like some kind of caching issue during module resolution.

For those of you who are using generator-angular2-library and are suffering from broken links with a linked library (using npm link) during development, could you please try the following:

  1. open gulpfile.js in the root of your library directory
  2. replace the clean:dist task with:
gulp.task('clean:dist', function () {

  // Delete contents but not dist folder to avoid broken npm links
  // when dist directory is removed while npm link references it.
  return deleteFolders([
    distFolder + '/**',
    '!' + distFolder,
    '!' + distFolder + '/*.umd.js'
  ]);
});
  1. run gulp in your library directory
  2. consume your library in an Angular CLI app (instructions)
  3. run ng serve in your Angular CLI app
  4. make a change to your library and see if the consuming application picks up the changes properly
  5. post a comment in this issue to let us know if it works for you or not

It would be great to get feedback on whether this prevents the issue in different environments.

Thanks in advance! πŸ‘

hi @jvandemo,

thanks for you effort! definitely fixes this issue where gulp and webpack deleting and reading the dist-folder simultaneously.

But still, try to rename a public method of a service provided by a linked dependency, it won't work, until you stop and execute ng serve again.

@synctom — I think the issue you are referring to is an underlying Webpack issue.

Did the change in the gulpfile.js resolve the issue with refreshing the browser during library rebuilds (where Webpack complains about missing files when gulp is rebuilding the library)?

Thanks again for testing, much appreciated! πŸ‘

yes indeed, webpack doesn't complain about missing files anymore after implementing your fix.

@synctom — Excellent, thank you for the confirmation!

is there any workaround for assets folder as well in dist folder as well?

Hi,

I do have a problem with the update/refresh behavior of _ng serve_ in an other way. TBH it does depend more on a different issue with _NgModule annotation_

Uncaught Error: Unexpected value '[object Object]' imported by the module 'AppModule'. Please add a @NgModule annotation.

and how to resolve it when using npm link.

Dev Environment

Windows 7
npm: 3.10.10
node: 6.11.1
Angular CLI: 1.3.0
Yo: 2.0.0
generator-angular2-library: 11.4.0
VS Code: 1.16.1

Projects

App created with the Angular CLI
https://github.com/Wampe/Angular-CLI-App-6195

Library created with the generator-angular2-library based on the yeoman generator
https://github.com/Wampe/Angular-Lib-6195
(Gulp file modifications for clean:dist mentioned by @jvandemo considered)

Steps to reproduce

  1. Load repositories

  2. Angular-Lib-6195 (@wampe/lib-6195)

  • [ ] npm install
  • [ ] npm run build (or gulp build)
  • [ ] cd dist
  • [ ] npm link
  1. Angular-CLI-App-6195
  • [ ] npm link @wampe/lib-6195
  • [ ] npm install
  • [ ] npm start (or ng serve)

Now when you open the App in Browser you should get the _NgModule annotation_ error in console.

  1. Back to Angular-Lib-6195
  • [ ] npm run build:watch
  • [ ] Change anything you want and save it.

Now comes the fun: the update/refresh of _ng serve_ works fine itself now (until this step). But just with the problem that with every update the _NgModule annotation_ error appears again and again...

  1. Back to Angular-CLI-App-6195

Now the App works. The default implementation of the Angular CLI template gets showen.
But now the update/refresh behavior of _ng serve_ doesnΒ΄t work anymore. Interestingly, update/refresh while running ng _build --watch_ in the App project works (how already mentioned in this thread).

tl;dr
Is it the expected behavior of _ng serve_ to "ignore" updates in a source (via npm link) when using _--preserve-symlinks_ or how can I get the update/refresh when using it?

I am experiencing the same type of issue. I have a main project and an external module (npm linked). I serve the application using ng serve.

As @synctom said, if I update existing methods it works fine but if I add new content (like a new method on a service) inside the external module and try using it in my main project, ng serve outputs error like:

ERROR in app/main/components/login/login.component.ts (36,18): Property 'hello' does not exist on type 'LoginFlow'.

ng serve success, only when I restart. Also, running ng build (main project) on a new terminal while ng serve is running works without any error. So I think there is some caching issue (ng serve, webpack or whatever, ...). I've inspected the /gendir of the external module and the newly added method is present and correct.

I've tried with the last stable release of cli (1.4.3) & adding --poll option on ng serve & adding more watchers (inotify). Also I build my external module with ngc

Here is my setup:

@angular/cli: 1.2.7
node: 6.11.0
os: linux x64
@angular/animations: 4.3.6
@angular/common: 4.3.6
@angular/compiler: 4.3.6
@angular/core: 4.3.6
@angular/forms: 4.3.6
@angular/http: 4.3.6
@angular/platform-browser: 4.3.6
@angular/platform-browser-dynamic: 4.3.6
@angular/router: 4.3.6
@angular/cli: 1.2.7
@angular/compiler-cli: 4.3.6
editor: VScode

Good news guys, i found the issue.

As I already suspected it's a caching issue located in a Webpack plugin that compiles your angular code.

Check @ngtools/webpack/src/plugin.js in the node_modules folder of your cli application.

Just remove or uncomment:

this._compilerHost.enableCaching();

Can anyone confirm?

@synctom Your solution works perfectly :)

I tried once with ng serve which built successfuly without error this time (after making change to my external module & updated my main app). I'm reinstalling all my dependencies (npm) for further tests but npm seems down with scoped packages right now.

@synctom In my case it doesnΒ΄t help.

By the way (a stupid question):

Check @ngtools/webpack/src/plugin.js in your node_modules folder.

Global? Local (App) or local (library)? I did try each case.

@Wampe ./node_modules/@ngtools/webpack/src/plugin.js in your angular-cli application. updated my answer, thanks.

I'm getting the exact same thing @Wampe is describing (also using the gulp fix from @jvandemo ), and have tried the /@ngtools/webpack/src/plugin.js fix also mentioned by @synctom and nothing has fixed the issue completely.

When doing ng serve, I'm getting the same type of Uncaught Error at runtime (mine giving me Uncaught Error: Unexpected value 'MyLibraryModule' imported by the module 'AppModule'. Please add a @NgModule annotation.). When doing ng serve --preserve-symlinks, there's no recompilation triggered by the Angular CLI application.

hi @deckerbd, hi @Wampe

if you want to store your angular components / pipes / modules / etc. in a external package (and probably link it to your app while developing) make sure you ...

  1. list all @angular/* dependencies as peerDependencies (package.json of your external lib)
  2. list all @angular/* dependencies as devDependencies (package.json of your external lib)
  3. remove all @angular/* dependencies from dependencies (package.json of your external lib)
  4. modify /src/tsconfig.app.json within your cli app like this
{
  "compilerOptions": {
    // ...
    // Note: these paths are relative to `baseUrl` path.
    "paths": {
      "@angular/*": [
        "../node_modules/@angular/*"
      ]
    }
  }
}

This ensures that typescript will always load the local copies of the angular-modules your library asks for.

learned from angular-cli wiki

Hey @synctom

Double-checked and I have all the steps you mentioned already done (peerDependencies, devDependencies correct and match, no dependencies listed, tsconfig.app.json in app modified), still the same thing. @Wampe looks to have this in their repo as well if I'm not mistaken.
```@angular/cli: 1.4.2
node: 8.2.1
npm: 5.3.0
os: win32 x64 (Windows 10)
@angular/common: 4.4.3
@angular/compiler: 4.4.3
@angular/compiler-cli: 4.4.3
@angular/core: 4.4.3
@angular/forms: 4.4.3
@angular/platform-browser: 4.4.3
@angular/platform-browser-dynamic: 4.4.3
@angular/router: 4.4.3
typescript: 2.2.2
yo: 2.0.0
generate-angular2-library: 11.4.0

With my new dev environment

Windows 10
npm: 3.10.10
node: 6.11.4
Angular CLI: 1.4.4
Yo: 2.0.0
generator-angular2-library: 11.4.0
VS Code: 1.16.1
and the newest npm package versions

I do still have the same issue like written in (comment)
So it seems in my case it is not an issue with a specific version (of any dev resource or OS) or it isn not still fixed.

"paths": { "@angular/*": [ "../node_modules/@angular/*" ] }

@synctom I tried it with and without the path declaration. Meanwhile if I understand it right it is obsolete?
comment 1 | comment 2
Maybe @filipesilva can say more.

@Wampe - While developing a library, you'll need to have all of your peer dependencies also installed via devDependencies - otherwise you could not compile.
And if you do so, you definitely need to add paths to your typescript-configuration.

BUT if you are using angular2-library its a litte bit different. ;) a angular2-library project works like a factory that produces a 'npm-linkable' output (see dist folder). and this output has its own package.json without any devDependencies. so in this case, no paths is required.

But only because you link the dist folder to you cli-app, not the library itself.

@Wampe - could you please try this:

  • npm unlink lib-6195 with:

    npm unlink @wampe/lib-6195 (in app)
    and
    npm unlink (in lib)

  • rebuild your lib with 'npm run build'

  • then copy the dist-folder to a different location, out of your lib-folder, thats important.
  • then link the dist folder again
  • try to modify your code in dist folder while cli app is running

Any different behavior?

Great Scott!

@synctom It works! There is a different behavior.

I have linked the dist folder outside of the workspace directory. Now I can use ng serve without --preserve-symlinks and without the @NgModule annotation error. When I generate the dist by gulp into the folder outside of the workspace it also reflects the changes in the library and the app shows the updates directly.

So what is the root of all evil?

npm link works differently since npm version 5.

thanks to @stevencohn, he explained the issue pretty good https://github.com/angular/angular/issues/15763#issuecomment-312296944

Current solutions are:

Solution1: Remove symlink and then copy dist folder into node_modules.
Solution2: Delete node_modules from library project.
Solution3: Build library into dist folder that is not inside library project.

@synctom I guess that moving the dist folder outside the lib folder makes sure we do not get polluted by its node_modules, right?

Is there any way to ask the compiler to ignore all the lib's node_modules? (because moving the folder outise is not very handy)
Maybe using "compilerOptions": "paths": { "*": ["../node_modules/*"]} ?

EDIT: I tried "*": ["../node_modules/*"], it does not work

Any ideas @jvandemo? πŸ€”
https://github.com/angular/angular-cli/issues/6195#issuecomment-334706792

I have found a solution without moving the dist folder.
Instead, I remove the lib's node_modules folder, and I replace it with a symlink to the project's node_modules.
Hence, there is only one unique node_modules, no confusion possible, but it is available on both sides, so we can run build, tests, have IDE auto-completion, etc.

same issue here :(

Similar problem here, we've got angular cli based app and library created using https://github.com/filipesilva/angular-quickstart-lib.

We followed steps from https://github.com/angular/angular-cli/wiki/stories-linked-library and
tried using npm link and also referencing library inside src/tsconfig.app.json of cli based project (through path pointing to src/lib of library).

In both cases, we are getting "Please add a @NgModule annotation" error once cli based app is run. We pinned it down to problem with @angular/core inside library's node_modules. Current work around for us is:
-> temporarily rename 'library_folder/node_modules/@angular/core' to something else like core1
-> run npm start in cli based app
-> rename core1 back to core inside library

We would very much appreciate this being fixed as manual rename step is really annoying.

The node_modules symlink solution is mentionned here https://github.com/angular/angular-cli/issues/6195#issuecomment-334755843 does work fine.
But there is another solution:

  • first make a symlink to your lib src folder into your project:
cd project/src
ln -s ../../library/src ./lib
  • then use tsconfig paths to fix the path:
    "paths": {
      "my-library": ["lib"]
    }

And now your lib code is in the project code (it will trigger autoreload and so on), but you can use import things just like if it was a regular dependency:

import { MyComponent } from 'my-library';

(credits should go @sunew https://github.com/plone/plone.restapi-angular/commit/6f9984f462b5ce0a65a02fb7fc4f5774a32bb146)

I just tried symlink solution as you described @ebrehault . It does reference the library code without needing to delete/rename node_modules/@angular/core but it doesn't trigger code refresh in cli based app when library code changes

UPDATE -. posted wrong link at first

See here:
https://github.com/plone/plone.restapi-angular/blob/master/docs/development.rst

Maybe you need some step.
Code refresh works for me (+ sourcemaps, debugger, etc).

The documentation here https://github.com/angular/angular-cli/wiki/stories-linked-library is not very clear, but after reading 100's of tickets for angular-cli I think I can conclude that method is for building the library first, and then running on the buildt version (ie. the js and not the ts)). The method uses tsconfig paths for the peerdependencies of the library, so angular does not get loaded twice (in perhaps different versions).

For plain development, debugging, exploring the code in the debugger, etc. my method works fine (docs/development.rst)

Let me know if you can make it work following docs/development.rst - maybe I forgot to document some step...

@adamlubek with node_modules symlink approach, I forgot to mention an important:

you need to create a package.json in library/src and add it as dependency in your project:

npm install ../library/src

It will create a symlink to library/src and code changes in the lib will trigger the CLI.

But anyway, @sunew solution is certainly cleaner and better.

Hi at all!

I have found a β€œsolution” (more a workaround I think) in other way. But first...

@ebrehault I am confused about your _node_modules symlink_ approach. It may work (did not test it) but if I do understand it right it is limited to the one App project. So you are just able to use the library with this one App (do I understand it right?). How would you re-use the library in other projects?

@sunew Your solution is similar to the one of @synctom (comment) or not? In your case you do copy the dist folder into the App project directly, right?

My Workaround
Depending on the β€œget the dist folder out of the lib folder” comments by @synctom and @sunew I have tried the following approach.

What to do (based on my repositories):

  1. Set the path of the dist folder in the _gulpfile.js_ to the global node_modules.

const distFolder = path.join(process.env.AppData, '\\npm\\node_modules\\@wampe\\lib-6195');

Now dist gets generated into the global _node_modules_ directly (no _npm link_ usage in the library project).

  1. Extend the delete function in the _gulpfile.js_ with the _force_ option.
function deleteFolders(folders) {
  return del(folders, { force: true });
}

This option is necessary for the delete process outside of the workspace.

  1. Link the generated dist folder (in global node_modules) into the App project
    npm link @wampe/lib-6195

  2. Run ng serve (without --preserve-symlinks). The App should get showen (No ngModule annotation error).

  3. Make any changes in the library

After a manually gulp build (or automatically by gulp build:watch) again in the library project the changes should be reflected in the App (in Browser).

In short: Just move the dist folder to the global node_modules

disadvantage
The dist folder is out of the workspace. So I have to navigate to the globals.
In the meanwhile I am using gulp-directory-sync so it would be justifiable for me to have the dist folder redundant if I sync the local dist with the global dist.

advantages
β€’ I can use the library (while developing) in multiple projects
β€’ Several developers in a team can work together on the library and use it based on this uniform approach
β€’ ng serve without --preserve-symlinks
β€’ Changes in the library getting reflected
β€’ I do not have to set any paths in any config files

This is just a workaround but this approach works best for me in my case until this issue is fixed.

@Wampe my solution can work with several projects as far as those projets have identical dependencies (as they will share the same node_modules).
So yes it is a restriction.

I finally got it working without any need for rename/delete of node_modules in libraries.
But, I encountered problems with symlink on win10 machine and I ended up using mklink through admin command prompt (instead of git bash).

Steps:

  1. install your lib in cli based app
  2. in root of your cli based app, create folder to hold libs (e.g. C:\CliApp\symlinklibs)
  3. create symlink to root src of your library (say your library root i.e. index.ts is in "C:\featureLib\src\lib" e.g.
    mklink /J "C:\CliApp\symlinklibs\featureLib" "C:\featureLib\src\lib"
  4. Now, with symlink created, in tsconfig.app.json located in C;\CliApp\src, add:
"paths": {
        "feature-lib-packagejson-name": [
            "../symlinklibs/featureLib"
        ]
}
  1. In .angular-cli.json add:
  "defaults": {
    "build": {
      "preserveSymlinks": true
    }
  }

thanks @ebrehault and @sunew ,your comments and documentation are very much appreciated!

I have the same problem on a mac 10.12.6 with:

@angular/cli: 1.5.2
@angular-devkit/build-optimizer: 0.0.33
@angular-devkit/core: 0.0.20
@angular-devkit/schematics: 0.0.36
@ngtools/json-schema: 1.1.0
@schematics/angular: 0.1.5
typescript: 2.5.3
webpack: 3.8.1

I used https://github.com/trekhleb/angular-library-seed as a initial setup.

Same as @sebastian-man for me. The hack proposed by @synctom (disabling webpack caching) works fine, but it seems to be deprecated to disable caching https://github.com/angular/angular-cli/issues/7939.

Still waiting for an acceptable solution ? This problem is a big one for lib developpement isn't it ?

@sebastian-man @juliemr The solution is really quite simple, as described in the link in my above post.

@sunew
I try your steps but this didnt solved my problem.

In my project I add this to the appplication/tsconfig.json

"paths": {
      "@angular/*": [
        "node_modules/@angular/*"
      ],
      "@company/my-library": [
        "packages/@company/my-library"
      ]
    },

In the application/src/tsconfig.app.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "baseUrl": "./",
    "module": "es2015",
    "types": []
  },
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ]
}

But same behavior. The app is reloaded but without the change.

In my library I also tried to change some things from the angular-library-seed.

So I create a own package.json with:

{
  "name": "@company/my-library",
  "version": "0.0.1",
  "description": "Library",
  "main": "./index.umd.js",
  "module": "./index.js",
  "typings": "./index.d.ts",
  "license": "MIT",
  "author": {
    "name": "Username",
    "url": "http://www.domain.com"
  },
  "dependencies": {},
  "peerDependencies": {
    "@angular/common": "5.x",
    "@angular/core": "5.x",
    "rxjs": "5.x",
    "zone.js": "0.x"
  }
}

And copy this to my library/dist folder.
In my dist folder I do the npm link command. So the link is to the compiled library source.

But this all didnt solved my problem.
Currently its pain in the a** to develop our custom library.

I hope there is any handle solution (i mean without change manually the library and stuff like this, that isnt practicable in a team).

@sunew
After reading your document again I get the point that you link directly to the src folder and not the compiled js. But what I didnt know is how to resolved this if I didnt compile the library?

"main": "./index.umd.js",
"module": "./index.js",
"typings": "./index.d.ts",

Update
Ok the entries main, module, typings seems to be ignored if i linked directly the src folder.

And with this it works like @sunew told πŸ‘
So thx @sunew for sharing this!

Ok it works fine when creating a specific symlink to have the src of the library in the consuming app, thank you for that.
But I don't get the point if the lib dependency is not in the node_modules folder ?
If I understand well your solution @sunew, you never treat those dependencies as npm packages, but only as "linked sources" ?

Please consider this simple development workflow :

  • I create a new application
  • I install my external library using npm install, it appears in node_modules
  • Now I need to make changes in my library
  • I use npm link to make the node_modules/library of my application target my local sources
  • But I want these changes to be live reloaded, and for now it doesn't work.

Did I miss a solution for that case ?

@julien-arhs

  • in your-library place a package.json under src/ but without entries in dependencies
  • in your-library goto src/ and type npm link
  • goto your project and type npm link your-library

Thats it.

Nice ! I didn't get the trick to create a package.json at src level for linking.
Does the content of the file matter ? Or is the purpose only to change the npm linking scope ?

@julien-arhs the src/package.json will allow you to indicate the proper entry point:

"main": "./index.ts",

It works without any main value, index.ts must be a kind of default.
But for understanding it is probably better to write it.

I have tried the solution of @sunew exactly step by step (on Windows, with mklinkinstead of ln) but the update/refresh behavior (while ng serve) does not work.

@julien-arhs @ebrehault Do you also use Mac like @sebastian-man ? Is it just a Windows thing?

I use a Mac os 10.12.6.
Did you also try to link you src folder using npm link as explained by @sebastian-man ?
And don't forget to use the ng serve --preserve-symlinks or set it as default in angular-cli.json

"defaults": {
    "styleExt": "scss",
    "component": {},
    "build": {
      "preserveSymlinks": true
    }
  }

For me, it works on MacOSX and Ubuntu.

@julien-arhs I have defined --preserve-symlinks in the angular-cli.json.
In this case I did not use npm link. The using of npm link as described in my inital post here would bring the same problem and in the end to set own soft links manually seems to be the same as npm link does.
Or do you mean I shall use the manual softlink declaration AND npm link the same time?

@ebrehault Thanks.

Both methods worked for me. But the npm link method to link the library in the /node-modules folder of the project is the better way to do it imo.

As said by @sebastian-man :

in your-library place a package.json under src/ but without entries in dependencies
in your-library goto src/ and type npm link
goto your project and type npm link your-library

@julien-arhs What does "worked for me" means in your case? Just to consume the library in the CLI App? Or even more the code refresh when library code changes when running the CLI app with ng serve?

Also the code refresh.
I've built my lib using this generator https://github.com/tinesoft/generator-ngx-library:

  • I run the gulp task to watch/re-build the lib.
  • The served consuming app is refreshed with changes.

Windows:10, Library generated by generator-angular2-library. Linked dist dir inside lib using npm.

  1. Angular Cli: 1.4.2
    Run cmd: ng serve --preserve-symlinks
    when lib changes, cli detects changes, browser does NOT reflect changes.

  2. Angular Cli :1.2.7
    Works as expected.

I then ejected webpack from cli 1.4.2 setup using ng eject.
Added ngtools/webpack to package.json

ngtools/[email protected] works.
ngtools/[email protected] fails. This coincides with 1.3.0 release of angular cli and the introduction of --preserve-symlinks?

I cannot figure out what has changed between ngtools/webpack 1.6.0-rc5 and 1.6.0 ?

I am using cli 1.2.7 for now.

After spending some time investigating this issue I found the following solution for linking angular libs by source. Some has already been outlined above but this is the summary:

  • run npm link from the source directory of your library
  • run npm link <libname> from the root of your consuming application
  • add the following to the tsconfig.json or tsconfig.app.json of your consuming application:
    "include": [ "../node_modules/<libname>/**/*", "**/*"]
  • add the --preserve-symlinks option to either the ng serve or ng build commands

This should fix the compilation errors. You may notice that during ng serve the file watcher in angular-cli/webpack doesn't trigger a recompile from library source file changes. This is due to the --preserve-symlinks flag not propagating to the webpack file watcher. I have opened an issue here: https://github.com/webpack/watchpack/issues/61 Essentially you need to open the node_modules\watchpack\lib\DirectoryWatcher.js file in your consuming application and change followSymlinks from false to true.

It is not ideal as you need to hardcode paths to the tsconfig.json file but its the best solution i could find apart from messing around with copying lib code into the source tree or using external commands to manage links/junctions.

What works for me is to consume the library when compiled separately by ngc --watch, and not let the host app compile the library. ng serve in the host app still picks up changes made by the separate library compilation process. Have to use the preserveSymlinks option as said here to avoid duplicate instances of common libraries from node_modules, but otherwise no need to configure anything extra tsconfig.json of the consuming app.

My solution is implemented in my own experimental library packager ngmakelib, and some notes about linking / watching can be found here:

https://github.com/fintechneo/ngmakelib/blob/master/README.md#watch-mode-during-development

Can you still reproduce this issue?

Little late for the party, but...

if anyone still has issues of that kind, try angular cli.
The "library" schematic (called by ng g library) will generate a nice, clean and official solution for building external libraries.

And yes, also supports watch mode out of the box.

learn more:
https://github.com/angular/angular-cli/wiki/stories-create-library

Yeah I remembered watching this ticket when I had to build external libraries with a third party tool like ngPackagr. With angular cli, I think this has now no reason to live. (at least for the next versions of cli)

I am using new angular cli and library schematics, but still can reproduce the issue(((
I am building the library with ng build lib-name --watch , install library from local folder, and run main application with ng serve with preserveSymlinks.

@ToniaDemchuk did you enable resource-inlining in tsconfig.lib.json?

"angularCompilerOptions": { "enableResourceInlining": true }

@ToniaDemchuk did you enable resource-inlining in tsconfig.lib.json?

"angularCompilerOptions": { "enableResourceInlining": true }

@synctom Yes, I did

Can you kindly provide the output of ng version?

Angular CLI: 7.1.4
Node: 8.11.3
OS: win32 x64
Angular: 7.1.4
... animations, cli, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package Version

@angular-devkit/architect 0.11.4
@angular-devkit/build-angular 0.11.4
@angular-devkit/build-optimizer 0.11.4
@angular-devkit/build-webpack 0.11.4
@angular-devkit/core 7.1.4
@angular-devkit/schematics 7.1.4
@angular/cdk 7.2.0
@angular/flex-layout 7.0.0-beta.22
@angular/material 7.2.0
@ngtools/json-schema 1.1.0
@ngtools/webpack 7.1.4
@schematics/angular 7.1.4
@schematics/update 0.11.4
ng-packagr 4.4.5
rxjs 6.3.3
typescript 3.1.6
webpack 4.23.1

I'm sorry, but we can't reproduce the problem.

Remember that we have a large number of issues to resolve, and have only a limited amount of time to reproduce your issue.
Short, explicit instructions make it much more likely we'll be able to reproduce the problem so we can fix it.

If the problem persists, please open a new issue following our submission guidelines.

A good way to make a minimal repro is to create a new app via ng new repro-app and adding the minimum possible code to show the problem. Then you can push this repository to github and link it here.

πŸ˜ƒ I was able to solve my issue. I'm not using any npm/yarn/lerna linked packages. Instead I'm just using tsconfig.json paths. All of my shared libraries are imported from @shared/.... The key to getting change detection working for shared libraries was to set the baseUrl and rootDir to the parent folder of my shared folder.

File Structure:

- api
- shared
- ui
  - angular.json
  - src
    - app
      - tsconfig.app.json
    - tsconfig.json

tsconfig files:

// ui/src/tsconfig.json
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "../",
    "rootDir": "../",
    "outDir": "./dist/out-tsc",
    // ...
    "paths": {
      "@ui/*": ["./ui/src/app/*"],
      "@shared/*": ["./shared/*"]
    }
  }
}

// ui/src/app/tsconfig.app.json
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app"
  },
  "include": [
    "./**/*.ts",
    "../../shared/**/*.ts"
  ],
  "exclude": [
    "test.ts",
    "**/*.spec.ts",
    "../../api/**/*.ts"
  ]
}

I'm on Angular 7.

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

MateenKadwaikar picture MateenKadwaikar  Β·  3Comments

hartjo picture hartjo  Β·  3Comments

rwillmer picture rwillmer  Β·  3Comments

NCC1701M picture NCC1701M  Β·  3Comments

jmurphzyo picture jmurphzyo  Β·  3Comments