angular-cli: Angular 12 ng build --watch won't update running ionic serve application

🐞 Bug report

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • extract-i18n
  • run
  • config
  • help
  • version
  • doc

Is this a regression?

Yes it used to work with @angular-devkit/build-angular: 0.1102.13

Description

Building an Angular lib with the newest version (ng build), doesn't update the ionic application using this lib, run with ionic serve. With bigger libs the ng build process can outrun the serve or gets stuck.

🔬 Minimal Reproduction

Can be reproduced using this bug repo. First run ng build --watch in the lib folder, then ionic serve in the app folder. Changing anything in the lib component back-button won’t update it in the application, even though both app and lib recompile.

To change to the working version run npm run goodvers Updating anything now will update it in the browser like it is supposed to be.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 15 (1 by maintainers)

Commits related to this issue

Most upvoted comments

Discussed this in the CLI triage meeting today and it’s a bit awkward since Webpack caching uses the package version to identify changes in node_modules/. They get around this problem by exposing an option, but we’d rather not add Webpack-specific options on Angular and we also don’t want to ask users to remember and use such an option as we’d rather this “just worked” by default, before the user wastes hours debugging stale builds.

Our main thought to solve this problem is to “stamp” library builds by adding a unique string to the end of the package.json version. This would create a version like: 0.1.2+0123456789, which would change on each build either using a hash of the entire package or a simple timestamp of the build. This causes the package version to change on every build of the library so Webpack knows to invalidate its cache.

The tricky question is when to stamp the version. Our initial approach is to simply stamp the build when the user runs ng build --watch on a library. A user would only ever do this for a development build, so we can be reasonably sure that the library is being linked to some application somewhere, meaning the stamped version will be needed to bust the Webpack cache of that application. If you only ng build a library, that is treated as a production build where the user would not want their version stamped, so we won’t modify it in this case.

There is an edge case if the user already has a 0.1.2+something-else string in their version. I’m not able to immediately confirm the semantics, but from my understanding anything after the + is meant to identify the build, so if the user already has this then Angular should probably leave it alone, since that should be sufficient for caching unless they are misusing + semantics (which is possible and I could be wrong here, we should probably double check).

This does break one expected invariant about the CLI, which is that the output of ng build and ng build --watch are not the same. This is a bit awkward and doesn’t make logical sense, but this difference in behavior allows us to more closely align with what the user wanted, which we think is a good trade off in this case. It also means that if a user does a one-off build of their library, it won’t bust the Webpack cache of their application. This is an unfortunate sharp edge, but we don’t expect this to be a common use case to actually affect many users.

TL;DR: We will make ng build --watch “stamp” the build by appending a timestamp / hash to the package version to bust the Webpack cache automatically. ng build without --watch will not modify the version at all and keep its current behavior.

For future reference, one alternative we discussed was adding a new stampVersion flag with the above behavior of appending a hash / timestamp to the output package.json. We would then migrate existing apps (and update ng new) to enable this by default in their development configuration (but would be false for the default production configuration). By doing this, dev builds would always include the cache busting string while production builds would leave the package version unchanged.

This sounds great but introduces a lot more complexity. stampVersion would need to be public API due to how flexible Angular configurations are, which adds a lot more configurability but is also much more effort to support and maintain. Migrating existing apps is also tricky because Angular configurations are so powerful. Users may have multiple configurations which they see as “development” and want to add this flag to, and we don’t have an understanding of this and can’t intelligently add this flag automatically for users. Such a migration is effectively limited to the configuration named development, since we generate it by default and it has common (though not universal) semantics.

Our thought process for now it to prefer the ng build --watch solution has it does not affect the public API and dodges the configurations issue.

ng-packagr version 12.0.6+ contains the version stamping fix that @dgp1130 described above.

Let me reopen this to discuss the issue in our next team meeting if we should provide an option to disable managed paths.

In general, if this would will be added it would most likely be configured via an environment variable.

Alternatively, a 3rd party builder can also be used in this case to configure this option.

That being said we don’t really recommend using npm linking.