angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.77k stars 11.98k forks source link

ng serve - npm linked library changes(updates) are not reflected in UI #6195

Closed tirnovanuaurel closed 4 years ago

tirnovanuaurel commented 7 years ago

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.

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.

--

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

filipesilva commented 7 years ago

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?

joachimprinzbach commented 7 years ago

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

Libraries used:

Dev Environment:

Projects used:

Steps to reproduce: Clone the two mentioned repositories

In angular-library:

In cli-project

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

Go back to the angular-library project.

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

joachimprinzbach commented 7 years ago

Fun fact: Cannot reproduce on macOS Sierra 10.12.4

danwulff commented 7 years ago

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.

phmello commented 7 years ago

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

filipesilva commented 7 years ago

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 🤘

joachimprinzbach commented 7 years ago

@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?

filipesilva commented 7 years ago

@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.

filipesilva commented 7 years ago

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.
filipesilva commented 7 years ago

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.

joachimprinzbach commented 7 years ago

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

jvandemo commented 7 years ago

@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

filipesilva commented 7 years ago

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).

goekaypamuk commented 7 years ago

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/cli@1.0.5

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/cli@1.0.5

synctom commented 7 years ago

hi, does anyone have a solution for this problem?

I have the same issue here. Working on macOS Sierra 10.12.5. @angular/cli@1.1.2 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?

goekaypamuk commented 7 years ago

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/cli@1.1.2 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 .

synctom commented 7 years ago

VS Code Version 1.13.1

goekaypamuk commented 7 years ago

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 .

synctom commented 7 years ago

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.

tanyagray commented 7 years ago

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

tanyagray commented 7 years ago

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:

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
synctom commented 7 years ago

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.

jvandemo commented 7 years ago

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! 👍

synctom commented 7 years ago

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.

jvandemo commented 7 years ago

@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! 👍

synctom commented 7 years ago

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

jvandemo commented 7 years ago

@synctom — Excellent, thank you for the confirmation!

Janatbek commented 7 years ago

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

wmbch commented 7 years ago

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)

  1. Angular-CLI-App-6195

Now when you open the App in Browser you should get the NgModule annotation error in console.

  1. Back to Angular-Lib-6195

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?

GooSP commented 7 years ago

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
synctom commented 7 years ago

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?

GooSP commented 7 years ago

@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.

wmbch commented 7 years ago

@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.

synctom commented 7 years ago

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

deckerbd commented 7 years ago

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.

synctom commented 7 years ago

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

deckerbd commented 7 years ago

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.


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
wmbch commented 7 years ago

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.

synctom commented 7 years ago

@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.

synctom commented 7 years ago

@Wampe - could you please try this:

Any different behavior?

wmbch commented 7 years ago

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?

synctom commented 7 years ago

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.

ebrehault commented 7 years ago

@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

synctom commented 7 years ago

Any ideas @jvandemo? 🤔 https://github.com/angular/angular-cli/issues/6195#issuecomment-334706792

ebrehault commented 7 years ago

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.

mscudlik commented 7 years ago

same issue here :(

adamlubek commented 7 years ago

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.

ebrehault commented 7 years ago

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:

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)

adamlubek commented 7 years ago

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

sunew commented 7 years ago

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...